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

2024-05-06


643. Use of decltype in a class member-specification

Section: 9.2.9.3  [dcl.type.simple]     Status: NAD     Submitter: Alisdair Meredith     Date: 8 Aug 2007

11.4 [class.mem] paragraph 2 says,

A class is considered a completely-defined object type (6.8 [basic.types]) (or complete type) at the closing } of the class-specifier. Within the class member-specification, the class is regarded as complete within function bodies, default arguments, and exception-specifications (including such things in nested classes). Otherwise it is regarded as incomplete within its own class member-specification.

In particular, the return type of a member function is not listed as a context in which the class type is considered complete; instead, that case is handled as an exception to the general rule in 9.3.4.6 [dcl.fct] paragraph 6 requiring a complete type in the definition of a function:

The type of a parameter or the return type for a function definition shall not be an incomplete class type (possibly cv-qualified) unless the function definition is nested within the member-specification for that class (including definitions in nested classes defined within the class).

These rules have implications for the use of decltype. (The following examples use the not-yet-accepted syntax for specifying the return type of a function after its declarator, but the questions apply to the current syntax as well.) Consider:

    struct deduced {
      int test() { return 0; }
      auto eval( deduced& d )->decltype( d.test() ) {
        return d.test();
      }
    };

7.6.1.5 [expr.ref] paragraph 1 requires that the class type of the object or pointer expression in a class member access expression be complete, so this usage is ill-formed.

A related issue is the use of this in a decltype specifier:

    struct last_one {
      int test() { return 0; }
      auto eval()->decltype( this->test() ) {
        return test();
      }
    };

_N4868_.11.4.3.2 [class.this] paragraph 1 allows use of this only in the body of a non-static member function, and the return type is not part of the function-body.

Do we want to change the rules to allow these kinds of decltype expressions?

Rationale (February, 2008):

In the other cases where a class type is considered complete within the definition of the class, it is possible to defer handling the construct until the end of the definition. That is not possible for types, as the type may be needed immediately in subsequent declarations.

It was also noted that the primary utility of decltype is in generic contexts; within a single class definition, other mechanisms are possible (e.g., use of a member typedef in both the declaration of the operand of the decltype and to replace the decltype itself).