This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 115e. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.
2024-11-11
[Voted into the WP at the July, 2017 meeting.]
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] bullet 5.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.
Proposed resolution (May, 2017):
Change 7.5.3 [expr.prim.this] paragraph 2 as follows:
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]
Change 7.6.1.5 [expr.ref] paragraph 2 as follows, splitting the paragraph into two paragraphs as indicated:
For the first option (dot) the first expression shall be a glvalue having
completeclass type. For the second option (arrow) the first expression shall be a prvalue having pointer tocompleteclass 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.7 [basic.scope.class]). —end note]The expression E1->E2 is converted to the equivalent form (*(E1)).E2; the remainder...