Consider following code: (Ideone)
struct S
{
int a() {return 0;}
decltype(a()) b() {return 1;}
};
It gives me following error:
A few additions to @Brian's answer:
In the first example, the a()
is not transformed to (*this).a()
. That transformation is specified in [class.mfct.non-static]/3 and only takes place "in a context where this
can be used". Without this transformation, the code is then ill-formed for violating [expr.prim.id]/2:
An id-expression that denotes a non-static data member or non-static member function of a class can only be used:
as part of a class member access ([expr.ref]) in which the object expression refers to the member's class63 or a class derived from that class, or
to form a pointer to member ([expr.unary.op]), or
if that id-expression denotes a non-static data member and it appears in an unevaluated operand.
by using the id-expression a
, which denotes a non-static member function, outside the allowed contexts.
The fact that the transformation to class-member access doesn't take place is important because it makes the following code valid:
struct A {
int a;
decltype(a) b();
};
If decltype(a)
above were transformed into decltype((*this).a)
, then the code would be ill-formed.
*this
has a special exemption from the usual rule that the object in a class member access must have complete type ([expr.prim.this]/2):
Unlike the object expression in other contexts,
*this
is not required to be of complete type for purposes of class member access ([expr.ref]) outside the member function body.
Since a
is a non-static member function, a()
is interpreted as (*this).a()
. Quoting in part from [expr.prim.general]/3,
If a declaration declares a member function or member function template of a class
X
, the expressionthis
is a prvalue of type “pointer to cv-qualifier-seqX
” between the optional cv-qualifer-seq and the end of the function-definition, member-declarator, or declarator. It shall not appear before the optional cv-qualifier-seq and it shall not appear within the declaration of a static member function (although its type and value category are defined within a static member function as they are within a non-static member function).
The trailing-return-type comes after the optional cv-qualifier-seq (omitted in your examples, since S::b
is not cv-qualified) so this
can appear there, but it cannot appear before.