Inside of a class, why `auto b() -> decltype(a()) {}` works, but `decltype(a()) b() {}` does not?

后端 未结 2 920
傲寒
傲寒 2021-01-07 20:37

Consider following code: (Ideone)

struct S
{
    int a() {return 0;}
    decltype(a()) b() {return 1;}
};

It gives me following error:

相关标签:
2条回答
  • 2021-01-07 20:41

    A few additions to @Brian's answer:

    1. 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.

    2. 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.

    3. *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.

    0 讨论(0)
  • 2021-01-07 20:54

    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 expression this is a prvalue of type “pointer to cv-qualifier-seq X” 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.

    0 讨论(0)
提交回复
热议问题