The following code can be compiled without error:
template <typename T> struct A {
void f() { this->whatever; } // whatever is not declared before
};
int main() {
A<int> a;
}
And I know it's because this
is a type-dependent expression, which makes name lookup for whatever
is postponed until the actual template argument is known. Since member function f()
is never used in this case, so that no instantiation of A<T>::f
exists, and name lookup for whatever
is never performed.
I can understand that this
is type-dependent if the class template has a type-dependent base like:
template <typename T> struct B { T whatever; };
template <typename T> struct A : B<T> {
void f() { this->whatever; }
};
int main() {
A<int> a;
}
When parsing the definition of template class A
, it's impossible to know what's type of its base, which makes this->whatever
potentially legal (B<T>
could has a member named whatever
). On the contrary, I haven't see any potential that this->whatever
would be legal in the first example as soon as member function f
is used somewhere.
So, could this->whatever
be legal at some points in the first example? If not, is there any other reason that this
should be treated as type-dependent expression in that case?
Your code is "ill-formed, no diagnostic required", because there is never a valid specialization for A::f
. In fact, the spec says that this->whatever
is neither a member of an unknown specialization (because there is no dependent base class), nor a member of the current instantiation (because it's not declared in a non-dependent base class, nor in the class template itself). This in addition renders your code invalid, and again no diagnostic is required (but allowed). This is explained in more details at https://stackoverflow.com/a/17579889/34509
this
is type-dependent because you don't know the template parameter values yet in the definition. So for instance SomeOtherTemplate<decltype(*this)>
cannot be resolved immediately, but needs to wait till the class template of this
is instantiated (so you need a typename
before SomeOtherTemplate<decltype(*this)>::type
).
However, just because this
is type dependent, doesn't mean that this->whatever
is aswell. As described above, the spec has tools to correctly categorize this as invalid, and in fact also does not make this->whatever
type dependent. It says
A class member access expression ([expr.ref]) is type-dependent if the expression refers to a member of the current instantiation and the type of the referenced member is dependent, or the class member access expression refers to a member of an unknown specialization.