Reputation: 68618
In 5.1.1/3 of C++ standard [expr.prim.general]
Unlike the object expression in other contexts, *this is not required to be of complete type for purposes of class member access outside the member function body. Only class members declared prior to the declaration are visible.
And then this 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());
Can you explain the quote and the example? What exactly is being demonstrated here?
Upvotes: 10
Views: 498
Reputation: 254431
It means that you can access members via this
, either explicitly or implicitly, outside function bodies within a class definition. At that point, the type is incomplete, and usually you can't access members of incomplete types.
But you can only do that within restricted parts of a member function declaration; the previous sentence says about this
:
It shall not appear before the optional cv-qualifier-seq
meaning that you can't use it in a parameter or leading return type specification. As far as I can see, the only place you can use it, outside a function body, is in a trailing return type.
You might need to do this when using decltype
in a trailing return type, to get the type of an expression involving a non-static member. The example demonstrates this by implicitly using this
to access g()
in the trailing return type. It would have been more clear what was being demonstrated if it were written as decltype(t + this->g())
.
Upvotes: 4
Reputation: 131789
First of all, all member access expressions are transformed by the compiler:
struct X{
int a;
void f(){}
void g(int b){
int x = a + b; // actually: int x = (*this).a + b
f(); // actually: (*this).f();
}
};
§9.3.1 [class.mfct.non-static] p3
[...] the id-expression is transformed into a class member access expression (5.2.5) using
(*this)
(9.3.2) as the postfix-expression to the left of the.
operator. [...]
Now, the example from the standard calls a member function outside of the body of another member function, in the trailing-return-type. And that call is transformed too:
template<class T> auto f(T t) -> decltype(t + (*this).g())
{ return t + (*this).g(); }
And outside of a member function body, *this
is obviously an incomplete type. This means that you can only access the names that have been declared prior to the usage - but that part does not apply only to the *this
usage:
struct X{
using typeA = int;
typeA f(); // OK, 'typeA' has been declared before
typeB g(); // Error: 'typeB' not declared before usage
using typeB = float;
};
Upvotes: 2
Reputation: 126432
What exactly is this an example of? Which statement is being demonstrated here?
The statement being demonstrated is that:
Unlike the object expression in other contexts, *this is not required to be of complete type for purposes of class member access (5.2.5) outside the member function body.
Outside the body of the member function there is an invocation to g()
, which means this->g()
. There, the type of *this
(i.e. A
) is not complete.
Per paragraph 9.2/2 of the C++11 Standard:
A class is considered a completely-defined object type (3.9) (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 brace-or-equal-initializers for non-static data members (including such things in nested classes). Otherwise it is regarded as incomplete within its own class member-specification.
Upvotes: 6