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

廉价感情. 提交于 2019-12-19 05:13:10

问题


Consider following code: (Ideone)

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

It gives me following error:

error: cannot call member function 'int S::a()' without object


On the other hand, this code compiles fine: (Ideone)

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


Why one example works, but another fails to compile?

Is compiler behavior fully correct in both examples?

If compiler is correct, then why the standard mandates such strange behavior?


回答1:


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.




回答2:


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.



来源:https://stackoverflow.com/questions/37038832/inside-of-a-class-why-auto-b-decltypea-works-but-decltypea

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!