Skip to content

P0847R7 Deducing this #5002

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Oct 15, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 43 additions & 12 deletions source/basic.tex
Original file line number Diff line number Diff line change
Expand Up @@ -865,6 +865,32 @@
\end{itemize}
\end{note}

\pnum
Two non-static member functions have
\defnadjx{corresponding}{object parameters}{object parameter} if:
\begin{itemize}
\item
exactly one is an implicit object member function
with no \grammarterm{ref-qualifier} and
the types of their object parameters\iref{dcl.fct},
after removing top-level references,
are the same, or
\item
their object parameters have the same type.
\end{itemize}
Two non-static member function templates have
\defnadjx{corresponding}{object parameters}{object parameter} if:
\begin{itemize}
\item
exactly one is an implicit object member function
with no \grammarterm{ref-qualifier} and
the types of their object parameters,
after removing any references,
are equivalent, or
\item
the types of their object parameters are equivalent.
\end{itemize}

\pnum
Two declarations \defn{correspond}
if they (re)introduce the same name,
Expand All @@ -885,25 +911,23 @@
each declares a function or function template, except when
\begin{itemize}
\item
both declare functions with the same parameter-type-list,
both declare functions with the same non-object-parameter-type-list,
\begin{footnote}
An implicit object parameter\iref{over.match.funcs}
is not part of the parameter-type-list.
\end{footnote}
equivalent\iref{temp.over.link} trailing \grammarterm{requires-clause}s
(if any, except as specified in \ref{temp.friend}), and,
if both are non-static members,
the same \grammarterm{cv-qualifier}s (if any) and
\grammarterm{ref-qualifier} (if both have one), or
they have corresponding object parameters, or
\item
both declare function templates with equivalent
parameter-type-lists,
non-object-parameter-type-lists,
return types (if any),
\grammarterm{template-head}s, and
trailing \grammarterm{requires-clause}s (if any), and,
if both are non-static members,
the same \grammarterm{cv-qualifier}s (if any) and
\grammarterm{ref-qualifier} (if both have one).
they have corresponding object parameters.
\end{itemize}
\end{itemize}
\begin{note}
Expand All @@ -923,16 +947,23 @@
\begin{codeblock}
typedef int Int;
enum E : int { a };
void f(int); // \#1
void f(Int) {} // defines \#1
void f(E) {} // OK: another overload
void f(int); // \#1
void f(Int) {} // defines \#1
void f(E) {} // OK: another overload

struct X {
static void f();
void f() const; // error: redeclaration
void f() const; // error: redeclaration
void g();
void g() const; // OK
void g() &; // error: redeclaration
void g() const; // OK
void g() &; // error: redeclaration

void h(this X&, int);
void h(int) &&; // OK: another overload
void j(this const X&);
void j() const&; // error: redeclaration
void k();
void k(this X&); // error: redeclaration
};
\end{codeblock}
\end{example}
Expand Down
6 changes: 3 additions & 3 deletions source/classes.tex
Original file line number Diff line number Diff line change
Expand Up @@ -997,15 +997,15 @@
\indextext{member function!volatile}%
\indextext{member function!const volatile}%
\begin{note}
A non-static member function can be declared with
An implicit object member function can be declared with
\grammarterm{cv-qualifier}{s}, which affect the type of the \keyword{this}
pointer\iref{expr.prim.this},
and/or a \grammarterm{ref-qualifier}\iref{dcl.fct};
both affect overload resolution\iref{over.match.funcs}
\end{note}

\pnum
A non-static member function may be declared
An implicit object member function may be declared
virtual\iref{class.virtual} or pure virtual\iref{class.abstract}.

\rSec2[special]{Special member functions}
Expand Down Expand Up @@ -2487,7 +2487,7 @@
\nontermdef{conversion-declarator}\br
ptr-operator \opt{conversion-declarator}
\end{bnf}
shall have no parameters and
shall have no non-object parameters and
specifies a conversion from \tcode{X} to
the type specified by the \grammarterm{conversion-type-id},
interpreted as a \grammarterm{type-id}\iref{dcl.name}.
Expand Down
78 changes: 69 additions & 9 deletions source/declarations.tex
Original file line number Diff line number Diff line change
Expand Up @@ -3435,10 +3435,10 @@

\begin{bnf}
\nontermdef{parameter-declaration}\br
\opt{attribute-specifier-seq} decl-specifier-seq declarator\br
\opt{attribute-specifier-seq} decl-specifier-seq declarator \terminal{=} initializer-clause\br
\opt{attribute-specifier-seq} decl-specifier-seq \opt{abstract-declarator}\br
\opt{attribute-specifier-seq} decl-specifier-seq \opt{abstract-declarator} \terminal{=} initializer-clause
\opt{attribute-specifier-seq} \opt{\keyword{this}} decl-specifier-seq declarator\br
\opt{attribute-specifier-seq} \opt{\keyword{this}} decl-specifier-seq declarator \terminal{=} initializer-clause\br
\opt{attribute-specifier-seq} \opt{\keyword{this}} decl-specifier-seq \opt{abstract-declarator}\br
\opt{attribute-specifier-seq} \opt{\keyword{this}} decl-specifier-seq \opt{abstract-declarator} \terminal{=} initializer-clause
\end{bnf}

The optional \grammarterm{attribute-specifier-seq} in a \grammarterm{parameter-declaration}
Expand Down Expand Up @@ -3547,6 +3547,66 @@
\end{codeblock}
\end{example}

\pnum
An \defn{explicit-object-parameter-declaration} is
a \grammarterm{parameter-declaration} with a \keyword{this} specifier.
An explicit-object-parameter-declaration shall appear only as
the first \grammarterm{parameter-declaration} of
a \grammarterm{parameter-declaration-list} of either:
\begin{itemize}
\item
a \grammarterm{member-declarator}
that declares a member function\iref{class.mem}, or
\item
a \grammarterm{lambda-declarator}\iref{expr.prim.lambda}.
\end{itemize}
A \grammarterm{member-declarator} with an explicit-object-parameter-declaration
shall not include
a \grammarterm{ref-qualifier} or a \grammarterm{cv-qualifier-seq} and
shall not be declared \keyword{static} or \keyword{virtual}.
\begin{example}
\begin{codeblock}
struct C {
void f(this C& self);
template <typename Self> void g(this Self&& self, int);

void h(this C) const; // error: \tcode{const} not allowed here
};

void test(C c) {
c.f(); // OK, calls \tcode{C::f}
c.g(42); // OK, calls \tcode{C::g<C\&>}
std::move(c).g(42); // OK, calls \tcode{C::g<C>}
}
\end{codeblock}
\end{example}

\pnum
A function parameter declared with an explicit-object-parameter-declaration
is an \defnadj{explicit object}{parameter}.
An explicit object parameter shall not be
a function parameter pack\iref{temp.variadic}.
An \defnadj{explicit object}{member function} is a non-static member function
with an explicit object parameter.
An \defnadj{implicit object}{member function} is a non-static member function
without an explicit object parameter.

\pnum
The \defnadj{object}{parameter} of a non-static member function is either
the explicit object parameter or
the implicit object parameter\iref{over.match.funcs}.

\pnum
A \defnadj{non-object}{parameter} is a function parameter
that is not the explicit object parameter.
The \defn{non-object-parameter-type-list} of a member function is
the parameter-type-list of that function with the explicit object parameter,
if any, omitted.
\begin{note}
The non-object-parameter-type-list consists of
the adjusted types of all the non-object parameters.
\end{note}

\pnum
A function type with a \grammarterm{cv-qualifier-seq} or a
\grammarterm{ref-qualifier} (including a type named by
Expand Down Expand Up @@ -6378,19 +6438,19 @@
\tcode{std::coroutine_traits<R, P$_1$, $\dotsc$, P$_n$>::promise_type},
where
\tcode{R} is the return type of the function, and
$\tcode{P}_1 \dotsc \tcode{P}_n$ are the sequence of types of the function parameters,
preceded by the type of the implicit object parameter\iref{over.match.funcs}
$\tcode{P}_1 \dotsc \tcode{P}_n$ are the sequence of types of the non-object function parameters,
preceded by the type of the object parameter\iref{dcl.fct}
if the coroutine is a non-static member function.
The promise type shall be a class type.

\pnum
In the following, $\tcode{p}_i$ is an lvalue of type $\tcode{P}_i$,
where
$\tcode{p}_1$ denotes \tcode{*this} and
$\tcode{p}_{i+1}$ denotes the $i^\textrm{th}$ function parameter
$\tcode{p}_1$ denotes the object parameter and
$\tcode{p}_{i+1}$ denotes the $i^\text{th}$ non-object function parameter
for a non-static member function, and
$\tcode{p}_i$ denotes
the $i^\textrm{th}$ function parameter otherwise.
the $i^\text{th}$ function parameter otherwise.
For a non-static member function,
$\tcode{q}_1$ is an lvalue that denotes \tcode{*this};
any other $\tcode{q}_i$ is an lvalue
Expand Down
63 changes: 56 additions & 7 deletions source/expressions.tex
Original file line number Diff line number Diff line change
Expand Up @@ -1194,7 +1194,7 @@

\pnum
\indextext{\idxcode{this}}%
The keyword \keyword{this} names a pointer to the object for which a non-static member
The keyword \keyword{this} names a pointer to the object for which an implicit object member
function\iref{class.mfct.non-static} is invoked or a non-static data member's
initializer\iref{class.mem} is evaluated.

Expand All @@ -1213,8 +1213,10 @@
between the optional
\grammarterm{cv-qualifier-seq} and the end of the \grammarterm{function-definition},
\grammarterm{member-declarator}, or \grammarterm{declarator}. It shall not appear within
the declaration of a static member function of the current class (although its type and value category
are defined within a static member function as they are within a non-static
the declaration of either
a static member function or an explicit object member function
of the current class (although its type and value category
are defined within such member functions as they are within an implicit object
member function).
\begin{note}
This is because declaration matching does not
Expand Down Expand Up @@ -1450,7 +1452,7 @@
the type of a class member access expression\iref{expr.ref}
naming the non-static data member
that would be declared for such a capture
in the closure object of
in the object parameter\iref{dcl.fct} of the function call operator of
the innermost such intervening \grammarterm{lambda-expression}.
\begin{note}
If that \grammarterm{lambda-expression} is not declared \keyword{mutable},
Expand Down Expand Up @@ -1688,6 +1690,10 @@
In the \grammarterm{decl-specifier-seq} of the \grammarterm{lambda-declarator},
each \grammarterm{decl-specifier}
shall be one of \keyword{mutable}, \keyword{constexpr}, or \keyword{consteval}.
If the \grammarterm{lambda-declarator} contains
an explicit object parameter\iref{dcl.fct},
then no \grammarterm{decl-specifier} in the \grammarterm{decl-specifier-seq}
shall be \keyword{mutable}.
\begin{note}
The trailing \grammarterm{requires-clause} is described in \ref{dcl.decl}.
\end{note}
Expand Down Expand Up @@ -1792,14 +1798,51 @@
{ std::cout << v1 << v2 << v3; } );
auto q = p(1, 'a', 3.14); // OK: outputs \tcode{1a3.14}
q(); // OK: outputs \tcode{1a3.14}

auto fact = [](this auto self, int n) -> int { // OK: explicit object parameter
return (n <= 1) ? 1 : n * self(n-1);
};
std::cout << fact(5); // OK: outputs 120
\end{codeblock}
\end{example}

\pnum
Given a lambda with a \grammarterm{lambda-capture},
the type of the explicit object parameter, if any,
of the lambda's function call operator
(possibly instantiated from a function call operator template)
shall be either:
\begin{itemize}
\item
the closure type,
\item
a class type derived from the closure type, or
\item
a reference to a possibly cv-qualified such type.
\end{itemize}
\begin{example}
\begin{codeblock}
struct C {
template <typename T>
C(T);
};

void func(int i) {
int x = [=](this auto&&) { return i; }(); // OK
int y = [=](this C) { return i; }(); // error
int z = [](this C) { return 42; }(); // OK
}
\end{codeblock}
\end{example}

\pnum
The function call operator or operator template is declared
\keyword{const}~(\ref{class.mfct.non-static}) if and only if the
\grammarterm{lambda-expression}'s \grammarterm{parameter-declaration-clause} is not
followed by \keyword{mutable}. It is neither virtual nor declared \tcode{volatile}. Any
followed by \keyword{mutable} and
the \grammarterm{lambda-declarator} does not contain
an explicit object parameter.
It is neither virtual nor declared \tcode{volatile}. Any
\grammarterm{noexcept-specifier} specified on a \grammarterm{lambda-expression}
applies to the corresponding function call operator or operator template.
An \grammarterm{attribute-specifier-seq} in a \grammarterm{lambda-declarator} appertains
Expand Down Expand Up @@ -3082,6 +3125,10 @@
When a function is called, each parameter\iref{dcl.fct} is
initialized~(\ref{dcl.init}, \ref{class.copy.ctor}) with
its corresponding argument.
If the function is an explicit object member function and
there is an implied object argument\iref{over.call.func},
the list of provided arguments is preceded by the implied object argument
for the purposes of this correspondence.
If there is no corresponding argument,
the default argument for the parameter is used.
\begin{example}
Expand All @@ -3090,7 +3137,7 @@
int x = f<int>(); // error: no argument for second function parameter
\end{codeblock}
\end{example}
If the function is a non-static member
If the function is an implicit object member
function, the \keyword{this} parameter of the function\iref{expr.prim.this}
is initialized with a pointer to the object of the call, converted
as if by an explicit type conversion\iref{expr.cast}.
Expand Down Expand Up @@ -4337,11 +4384,13 @@
\begin{itemize}
\item
If the operand is a \grammarterm{qualified-id} naming a non-static or variant member \tcode{m}
of some class \tcode{C}, the result has type ``pointer to member
of some class \tcode{C}, other than an explicit object member function, the result has type ``pointer to member
of class \tcode{C} of type \tcode{T}'' and designates \tcode{C::m}.
\item
Otherwise, the result has type ``pointer to \tcode{T}'' and points to
the designated object\iref{intro.memory} or function\iref{basic.compound}.
If the operand names an explicit object member function\iref{dcl.fct},
the operand shall be a \grammarterm{qualified-id}.
\begin{note}
In particular, taking the address of a variable of type ``\cv{}~\tcode{T}''
yields a pointer of type ``pointer to \cv{}~\tcode{T}''.
Expand Down
Loading