Skip to content

Commit ef1bd0b

Browse files
committed
P0847R7 Deducing this
1 parent 2360a59 commit ef1bd0b

File tree

7 files changed

+237
-54
lines changed

7 files changed

+237
-54
lines changed

source/basic.tex

Lines changed: 43 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -865,6 +865,32 @@
865865
\end{itemize}
866866
\end{note}
867867

868+
\pnum
869+
Two non-static member functions have
870+
\defnadjx{corresponding}{object parameters}{object parameter} if:
871+
\begin{itemize}
872+
\item
873+
exactly one is an implicit object member function
874+
with no \grammarterm{ref-qualifier} and
875+
the types of their object parameters\iref{dcl.fct},
876+
after removing top-level references,
877+
are the same, or
878+
\item
879+
their object parameters have the same type.
880+
\end{itemize}
881+
Two non-static member function templates have
882+
\defnadjx{corresponding}{object parameters}{object parameter} if:
883+
\begin{itemize}
884+
\item
885+
exactly one is an implicit object member function
886+
with no \grammarterm{ref-qualifier} and
887+
the types of their object parameters,
888+
after removing any references,
889+
are equivalent, or
890+
\item
891+
the types of their object parameters are equivalent.
892+
\end{itemize}
893+
868894
\pnum
869895
Two declarations \defn{correspond}
870896
if they (re)introduce the same name,
@@ -885,25 +911,23 @@
885911
each declares a function or function template, except when
886912
\begin{itemize}
887913
\item
888-
both declare functions with the same parameter-type-list,
914+
both declare functions with the same non-object-parameter-type-list,
889915
\begin{footnote}
890916
An implicit object parameter\iref{over.match.funcs}
891917
is not part of the parameter-type-list.
892918
\end{footnote}
893919
equivalent\iref{temp.over.link} trailing \grammarterm{requires-clause}s
894920
(if any, except as specified in \ref{temp.friend}), and,
895921
if both are non-static members,
896-
the same \grammarterm{cv-qualifier}s (if any) and
897-
\grammarterm{ref-qualifier} (if both have one), or
922+
they have corresponding object parameters, or
898923
\item
899924
both declare function templates with equivalent
900-
parameter-type-lists,
925+
non-object-parameter-type-lists,
901926
return types (if any),
902927
\grammarterm{template-head}s, and
903928
trailing \grammarterm{requires-clause}s (if any), and,
904929
if both are non-static members,
905-
the same \grammarterm{cv-qualifier}s (if any) and
906-
\grammarterm{ref-qualifier} (if both have one).
930+
they have corresponding object parameters.
907931
\end{itemize}
908932
\end{itemize}
909933
\begin{note}
@@ -923,16 +947,23 @@
923947
\begin{codeblock}
924948
typedef int Int;
925949
enum E : int { a };
926-
void f(int); // \#1
927-
void f(Int) {} // defines \#1
928-
void f(E) {} // OK: another overload
950+
void f(int); // \#1
951+
void f(Int) {} // defines \#1
952+
void f(E) {} // OK: another overload
929953

930954
struct X {
931955
static void f();
932-
void f() const; // error: redeclaration
956+
void f() const; // error: redeclaration
933957
void g();
934-
void g() const; // OK
935-
void g() &; // error: redeclaration
958+
void g() const; // OK
959+
void g() &; // error: redeclaration
960+
961+
void h(this X&, int);
962+
void h(int) &&; // OK: another overload
963+
void j(this const X&);
964+
void j() const&; // error: redeclaration
965+
void k();
966+
void k(this X&); // error: redeclaration
936967
};
937968
\end{codeblock}
938969
\end{example}

source/classes.tex

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -997,15 +997,15 @@
997997
\indextext{member function!volatile}%
998998
\indextext{member function!const volatile}%
999999
\begin{note}
1000-
A non-static member function can be declared with
1000+
An implicit object member function can be declared with
10011001
\grammarterm{cv-qualifier}{s}, which affect the type of the \keyword{this}
10021002
pointer\iref{expr.prim.this},
10031003
and/or a \grammarterm{ref-qualifier}\iref{dcl.fct};
10041004
both affect overload resolution\iref{over.match.funcs}
10051005
\end{note}
10061006

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

10111011
\rSec2[special]{Special member functions}
@@ -2484,7 +2484,7 @@
24842484
\nontermdef{conversion-declarator}\br
24852485
ptr-operator \opt{conversion-declarator}
24862486
\end{bnf}
2487-
shall have no parameters and
2487+
shall have no non-object parameters and
24882488
specifies a conversion from \tcode{X} to
24892489
the type specified by the \grammarterm{conversion-type-id},
24902490
interpreted as a \grammarterm{type-id}\iref{dcl.name}.

source/declarations.tex

Lines changed: 68 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3440,10 +3440,10 @@
34403440

34413441
\begin{bnf}
34423442
\nontermdef{parameter-declaration}\br
3443-
\opt{attribute-specifier-seq} decl-specifier-seq declarator\br
3444-
\opt{attribute-specifier-seq} decl-specifier-seq declarator \terminal{=} initializer-clause\br
3445-
\opt{attribute-specifier-seq} decl-specifier-seq \opt{abstract-declarator}\br
3446-
\opt{attribute-specifier-seq} decl-specifier-seq \opt{abstract-declarator} \terminal{=} initializer-clause
3443+
\opt{attribute-specifier-seq} \opt{\keyword{this}} decl-specifier-seq declarator\br
3444+
\opt{attribute-specifier-seq} \opt{\keyword{this}} decl-specifier-seq declarator \terminal{=} initializer-clause\br
3445+
\opt{attribute-specifier-seq} \opt{\keyword{this}} decl-specifier-seq \opt{abstract-declarator}\br
3446+
\opt{attribute-specifier-seq} \opt{\keyword{this}} decl-specifier-seq \opt{abstract-declarator} \terminal{=} initializer-clause
34473447
\end{bnf}
34483448

34493449
The optional \grammarterm{attribute-specifier-seq} in a \grammarterm{parameter-declaration}
@@ -3552,6 +3552,66 @@
35523552
\end{codeblock}
35533553
\end{example}
35543554

3555+
\pnum
3556+
An \defn{explicit-object-parameter-declaration} is
3557+
a \grammarterm{parameter-declaration} with a \keyword{this} specifier.
3558+
An explicit-object-parameter-declaration shall appear only as
3559+
the first \grammarterm{parameter-declaration} of
3560+
a \grammarterm{parameter-declaration-list} of either:
3561+
\begin{itemize}
3562+
\item
3563+
a \grammarterm{member-declarator}
3564+
that declares a member function\iref{class.mem}, or
3565+
\item
3566+
a \grammarterm{lambda-declarator}\iref{expr.prim.lambda}.
3567+
\end{itemize}
3568+
A \grammarterm{member-declarator} with an explicit-object-parameter-declaration
3569+
shall not include
3570+
a \grammarterm{ref-qualifier} or a \grammarterm{cv-qualifier-seq} and
3571+
shall not be declared \keyword{static} or \keyword{virtual}.
3572+
\begin{example}
3573+
\begin{codeblock}
3574+
struct C {
3575+
void f(this C& self);
3576+
template <typename Self> void g(this Self&& self, int);
3577+
3578+
void h(this C) const; // error: \tcode{const} not allowed here
3579+
};
3580+
3581+
void test(C c) {
3582+
c.f(); // OK, calls \tcode{C::f}
3583+
c.g(42); // OK, calls \tcode{C::g<C\&>}
3584+
std::move(c).g(42); // OK, calls \tcode{C::g<C>}
3585+
}
3586+
\end{codeblock}
3587+
\end{example}
3588+
3589+
\pnum
3590+
A function parameter declared with an explicit-object-parameter-declaration
3591+
is an \defnadj{explicit object}{parameter}.
3592+
An explicit object parameter shall not be
3593+
a function parameter pack\iref{temp.variadic}.
3594+
An \defnadj{explicit object}{member function} is a non-static member function
3595+
with an explicit object parameter.
3596+
An \defnadj{implicit object}{member function} is a non-static member function
3597+
without an explicit object parameter.
3598+
3599+
\pnum
3600+
The \defnadj{object}{parameter} of a non-static member function is either
3601+
the explicit object parameter or
3602+
the implicit object parameter\iref{over.match.funcs}.
3603+
3604+
\pnum
3605+
A \defnadj{non-object}{parameter} is a function parameter
3606+
that is not the explicit object parameter.
3607+
The \defn{non-object-parameter-type-list} of a member function is
3608+
the parameter-type-list of that function with the explicit object parameter,
3609+
if any, omitted.
3610+
\begin{note}
3611+
The non-object-parameter-type-list consists of
3612+
the adjusted types of all the non-object parameters.
3613+
\end{note}
3614+
35553615
\pnum
35563616
A function type with a \grammarterm{cv-qualifier-seq} or a
35573617
\grammarterm{ref-qualifier} (including a type named by
@@ -6383,16 +6443,16 @@
63836443
\tcode{std::coroutine_traits<R, P$_1$, $\dotsc$, P$_n$>::promise_type},
63846444
where
63856445
\tcode{R} is the return type of the function, and
6386-
$\tcode{P}_1 \dotsc \tcode{P}_n$ are the sequence of types of the function parameters,
6387-
preceded by the type of the implicit object parameter\iref{over.match.funcs}
6446+
$\tcode{P}_1 \dotsc \tcode{P}_n$ are the sequence of types of the non-object function parameters,
6447+
preceded by the type of the object parameter\iref{dcl.fct}
63886448
if the coroutine is a non-static member function.
63896449
The promise type shall be a class type.
63906450

63916451
\pnum
63926452
In the following, $\tcode{p}_i$ is an lvalue of type $\tcode{P}_i$,
63936453
where
6394-
$\tcode{p}_1$ denotes \tcode{*this} and
6395-
$\tcode{p}_{i+1}$ denotes the $i^\textrm{th}$ function parameter
6454+
$\tcode{p}_1$ denotes the object parameter and
6455+
$\tcode{p}_{i+1}$ denotes the $i^\textrm{th}$ non-object function parameter
63966456
for a non-static member function, and
63976457
$\tcode{p}_i$ denotes
63986458
the $i^\textrm{th}$ function parameter otherwise.

source/expressions.tex

Lines changed: 56 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1194,7 +1194,7 @@
11941194

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

@@ -1213,8 +1213,10 @@
12131213
between the optional
12141214
\grammarterm{cv-qualifier-seq} and the end of the \grammarterm{function-definition},
12151215
\grammarterm{member-declarator}, or \grammarterm{declarator}. It shall not appear within
1216-
the declaration of a static member function of the current class (although its type and value category
1217-
are defined within a static member function as they are within a non-static
1216+
the declaration of either
1217+
a static member function or an explicit object member function
1218+
of the current class (although its type and value category
1219+
are defined within such member functions as they are within an implicit object
12181220
member function).
12191221
\begin{note}
12201222
This is because declaration matching does not
@@ -1450,7 +1452,7 @@
14501452
the type of a class member access expression\iref{expr.ref}
14511453
naming the non-static data member
14521454
that would be declared for such a capture
1453-
in the closure object of
1455+
in the object parameter\iref{dcl.fct} of the function call operator of
14541456
the innermost such intervening \grammarterm{lambda-expression}.
14551457
\begin{note}
14561458
If that \grammarterm{lambda-expression} is not declared \keyword{mutable},
@@ -1688,6 +1690,10 @@
16881690
In the \grammarterm{decl-specifier-seq} of the \grammarterm{lambda-declarator},
16891691
each \grammarterm{decl-specifier}
16901692
shall be one of \keyword{mutable}, \keyword{constexpr}, or \keyword{consteval}.
1693+
If the \grammarterm{lambda-declarator} contains
1694+
an explicit object parameter\iref{dcl.fct},
1695+
then no \grammarterm{decl-specifier} in the \grammarterm{decl-specifier-seq}
1696+
shall be \keyword{mutable}.
16911697
\begin{note}
16921698
The trailing \grammarterm{requires-clause} is described in \ref{dcl.decl}.
16931699
\end{note}
@@ -1792,14 +1798,51 @@
17921798
{ std::cout << v1 << v2 << v3; } );
17931799
auto q = p(1, 'a', 3.14); // OK: outputs \tcode{1a3.14}
17941800
q(); // OK: outputs \tcode{1a3.14}
1801+
1802+
auto fact = [](this auto self, int n) -> int { // OK: explicit object parameter
1803+
return (n <= 1) ? 1 : n * self(n-1);
1804+
};
1805+
std::cout << fact(5); // OK: outputs 120
1806+
\end{codeblock}
1807+
\end{example}
1808+
1809+
\pnum
1810+
Given a lambda with a \grammarterm{lambda-capture},
1811+
the type of the explicit object parameter, if any,
1812+
of the lambda's function call operator
1813+
(possibly instantiated from a function call operator template)
1814+
shall be either:
1815+
\begin{itemize}
1816+
\item
1817+
the closure type,
1818+
\item
1819+
a class type derived from the closure type, or
1820+
\item
1821+
a reference to a possibly cv-qualified such type.
1822+
\end{itemize}
1823+
\begin{example}
1824+
\begin{codeblock}
1825+
struct C {
1826+
template <typename T>
1827+
C(T);
1828+
};
1829+
1830+
void func(int i) {
1831+
int x = [=](this auto&&) { return i; }(); // OK
1832+
int y = [=](this C) { return i; }(); // error
1833+
int z = [](this C) { return 42; }(); // OK
1834+
}
17951835
\end{codeblock}
17961836
\end{example}
17971837

17981838
\pnum
17991839
The function call operator or operator template is declared
18001840
\keyword{const}~(\ref{class.mfct.non-static}) if and only if the
18011841
\grammarterm{lambda-expression}'s \grammarterm{parameter-declaration-clause} is not
1802-
followed by \keyword{mutable}. It is neither virtual nor declared \tcode{volatile}. Any
1842+
followed by \keyword{mutable} and
1843+
the \grammarterm{lambda-declarator} does not contain
1844+
an explicit object parameter.
1845+
It is neither virtual nor declared \tcode{volatile}. Any
18031846
\grammarterm{noexcept-specifier} specified on a \grammarterm{lambda-expression}
18041847
applies to the corresponding function call operator or operator template.
18051848
An \grammarterm{attribute-specifier-seq} in a \grammarterm{lambda-declarator} appertains
@@ -3073,6 +3116,10 @@
30733116
When a function is called, each parameter\iref{dcl.fct} is
30743117
initialized~(\ref{dcl.init}, \ref{class.copy.ctor}) with
30753118
its corresponding argument.
3119+
If the function is an explicit object member function and
3120+
there is an implied object argument\iref{over.call.func},
3121+
the list of provided arguments is preceded by the implied object argument
3122+
for the purposes of this correspondence.
30763123
If there is no corresponding argument,
30773124
the default argument for the parameter is used.
30783125
\begin{example}
@@ -3081,7 +3128,7 @@
30813128
int x = f<int>(); // error: no argument for second function parameter
30823129
\end{codeblock}
30833130
\end{example}
3084-
If the function is a non-static member
3131+
If the function is an implicit object member
30853132
function, the \keyword{this} parameter of the function\iref{expr.prim.this}
30863133
is initialized with a pointer to the object of the call, converted
30873134
as if by an explicit type conversion\iref{expr.cast}.
@@ -4328,11 +4375,13 @@
43284375
\begin{itemize}
43294376
\item
43304377
If the operand is a \grammarterm{qualified-id} naming a non-static or variant member \tcode{m}
4331-
of some class \tcode{C}, the result has type ``pointer to member
4378+
of some class \tcode{C}, other than an explicit object member function, the result has type ``pointer to member
43324379
of class \tcode{C} of type \tcode{T}'' and designates \tcode{C::m}.
43334380
\item
43344381
Otherwise, the result has type ``pointer to \tcode{T}'' and points to
43354382
the designated object\iref{intro.memory} or function\iref{basic.compound}.
4383+
If the operand names an explicit object member function\iref{dcl.fct},
4384+
the operand shall be a \grammarterm{qualified-id}.
43364385
\begin{note}
43374386
In particular, taking the address of a variable of type ``\cv{}~\tcode{T}''
43384387
yields a pointer of type ``pointer to \cv{}~\tcode{T}''.

0 commit comments

Comments
 (0)