Title
Use of class type being defined in trailing-return-type
Status
cd5
Section
_N4567_.5.1.1 [expr.prim.general]
Submitter
Mike Miller

Created on 2014-01-17.00:00:00 last changed 2 months ago

Messages

Date: 2017-07-15.00:00:00

[Voted into the WP at the July, 2017 meeting.]

Date: 2017-05-15.00:00:00

Proposed resolution (May, 2017):

  1. Change 7.5.2 [expr.prim.this] paragraph 2 as follows:

  2. Unlike the object expression in other contexts, *this is not required to be of complete type for purposes of class member access (7.6.1.5 [expr.ref]) outside the member function body. [Note: Only class members declared prior to the declaration are visible. —end note] [Note: In a trailing-return-type, the class being defined is not required to be complete for purposes of class member access (7.6.1.5 [expr.ref]). Class members declared later are not visible. [Example:

      struct A {
        char g();
        template<class T> auto f(T t) -> decltype(t + g())
        { return t + g(); }
      };
      template auto A::f(int t) -> decltype(t + g());
    

    end example] end note]

  3. Change 7.6.1.5 [expr.ref] paragraph 2 as follows, splitting the paragraph into two paragraphs as indicated:

  4. For the first option (dot) the first expression shall be a glvalue having complete class type. For the second option (arrow) the first expression shall be a prvalue having pointer to complete class type. In both cases, the class type shall be complete unless the class member access appears in the definition of that class. [Note: If the class is incomplete, lookup in the complete class type is required to refer to the same declaration (6.4.6 [basic.scope.class]). —end note]

    The expression E1->E2 is converted to the equivalent form (*(E1)).E2; the remainder...

Date: 2017-02-06.00:00:00

According to _N4567_.5.1.1 [expr.prim.general] paragraph 3,

Unlike the object expression in other contexts, *this is not required to be of complete type for purposes of class member access (7.6.1.5 [expr.ref]) outside the member function body.

Is this special treatment of member access expressions intended to apply only to *this, or does it apply to other ways of specifying the class being defined in the object expression? For example,

  struct S {
    int i;
    auto f1() -> decltype((*this).i);      // okay
    auto f2(S& This) -> decltype(This.i);  // okay?
    auto f3() -> decltype(((S*)0)->i);     // okay?
  };

There is implementation divergence on this question.

If the intent is to allow object expressions other than *this to have the current class type, this specification should be moved from _N4567_.5.1.1 [expr.prim.general] to 7.6.1.5 [expr.ref] paragraph 2, which is where the general requirement for complete object expression types is found.

On a related point, the note immediately following the above-cited passage is not quite correct:

[Note: only class members declared prior to the declaration are visible. —end note]

This does not apply when the member is a “member of an unknown specialization,” per 13.8.3.2 [temp.dep.type] paragraph 5 bullet 3 sub-bullet 1; for example,

  template<typename T> struct S : T {
    auto f() -> decltype(this->x);
  };

Here x is presumed to be a member of the dependent base T and is not “declared prior to the declaration” that refers to it.

History
Date User Action Args
2020-12-15 00:00:00adminsetstatus: drwp -> cd5
2018-02-27 00:00:00adminsetmessages: + msg6127
2018-02-27 00:00:00adminsetmessages: + msg6126
2018-02-27 00:00:00adminsetstatus: drafting -> drwp
2014-03-03 00:00:00adminsetstatus: open -> drafting
2014-01-17 00:00:00admincreate