This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 110b. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.

2023-01-15


1207. Type of class member in trailing-return-type

Section: 11.4.3  [class.mfct.non.static]     Status: C++11     Submitter: Jason Merrill     Date: 2010-10-06

[Voted into the WP at the March, 2011 meeting as part of paper N3282.]

Consider the following example:

    struct vector {
        struct iterator { };
        struct const_iterator { };
        iterator begin();
        const_iterator begin() const;
    };
    class block {
        vector v;
        auto end() const -> decltype(v.begin()) { return v.begin(); }
    };

Because the transformation of a member name into a class member access expression (11.4.3 [class.mfct.non.static] paragraph 3) only occurs inside the body of a non-static member function, the type of v in the trailing-return-type is non-const but is const in the return expression, resulting in a type mismatch between the return expression and the return type of the function.

One possibility would be to include the trailing-return-type as being subject to the transformation in 11.4.3 [class.mfct.non.static]. Note, however, that this is currently not in scope at that point (see issue 945).

Notes from the November, 2010 meeting:

The CWG felt that, because this is effectively an implicit parameter, the best approach would be to model its usability on the visibility of parameters: it could be named wherever a parameter of the function is in scope.

Proposed resolution (February, 2011):

  1. Change _N4567_.5.1.1 [expr.prim.general] paragraph 2 as follows, adding three new paragraphs:

  2. The keyword this names a pointer to the object for which a non-static member function (_N4868_.11.4.3.2 [class.this]) is invoked or a non-static data member's initializer (11.4 [class.mem]) is evaluated. The keyword this shall be used only inside the body of a non-static member function (11.4.2 [class.mfct]) of the nearest enclosing class or in a brace-or-equal-initializer for a non-static data member (11.4 [class.mem]). The type of the expression is a pointer to the class of the function or non-static data member, possibly with cv-qualifiers on the class type. The expression is a prvalue.

    If a function-definition or member-declarator declares a member function of a class X, the expression this is a prvalue of type “pointer to cv-qualifier-seq X” between the optional cv-qualifier-seq and the end of the function-definition or member-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 is defined within a static member function as it is within a non-static member function). [Note: the type and value category is defined even for the case of a static member function because declaration matching does not occur until the complete declarator is known, and this may be used in the trailing-return-type of the declarator. —end note]

    Otherwise, if a member-declarator declares a non-static data member (11.4 [class.mem]) of a class X, the expression this is a prvalue of type “pointer to X” within the optional brace-or-equal-initializer. It shall not appear elsewhere in the member-declarator.

    The expression this shall not appear in any other context.

    [Example:...

  3. Change _N4567_.5.1.1 [expr.prim.general] paragraph 10 as follows:

  4. An id-expression that denotes a non-static data member or non-static member function of a class can only be used:

  5. Change 11.4.3 [class.mfct.non.static] paragraph 3 as follows:

  6. When an id-expression (7.5 [expr.prim]) that is not part of a class member access syntax (7.6.1.5 [expr.ref]) and not used to form a pointer to member (7.6.2.2 [expr.unary.op]) is used in the body declaration of a non-static member function of class X, if name lookup (6.5 [basic.lookup]) resolves the name...