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?
答案 0 :(得分:4)
您的代码“格式错误,无需诊断”,因为A::f
永远不会有有效的专业化。事实上,规范说this->whatever
既不是未知专门化的成员(因为没有依赖基类),也不是当前实例化的成员(因为它没有在非依赖基类中声明,也不在课堂模板本身)。此外,这会使您的代码无效,并且不再需要诊断(但允许)。这在https://stackoverflow.com/a/17579889/34509
this
与类型有关,因为您还不知道定义中的模板参数值。因此,例如SomeOtherTemplate<decltype(*this)>
无法立即解决,但需要等到this
的类模板被实例化(因此在typename
之前需要SomeOtherTemplate<decltype(*this)>::type
)。
但是,仅仅因为this
依赖于类型,并不意味着this->whatever
也是如此。如上所述,规范具有将其正确归类为无效的工具,实际上不使this->whatever
类型依赖。它说
如果表达式引用当前实例化的成员并且引用的成员的类型是依赖的,或者类成员访问表达式引用成员,则类成员访问表达式([expr.ref])依赖于类型一个未知的专业化。
答案 1 :(得分:0)
您的示例可以进一步简化:
template <typename T> struct A {
void f() { this = 1; }
};
int main() {
A<int> a;
}
语句this = 1;
永远不应该编译,即使A<T>
具有类型相关的基类,也无法修复。但是,在实例化函数A<T>::f()
之前,编译器不会抱怨。
由于Johannes Schaub - litb已经answered,这可能是“无需诊断”的情况。
答案 2 :(得分:0)
这是关于从属名称的名称查找规则。
$14.6/9 Name resolution [temp.res]:
在查找模板定义中使用的名称声明时,通常的查找规则([basic.lookup.unqual],[basic.lookup.argdep])用于非依赖名称。依赖于模板参数的名称查找被推迟,直到知道实际模板参数([temp.dep])。
意图是,如果名称取决于模板参数,则信息不足,直到知道实际模板参数。编译器不会区分依赖名称&#39;类型(由this
或其他人形成),不会检查详细信息,例如类是否具有依赖基类。结果可能不会像您展示的示例代码那样改变,但它只是推迟名称查找,直到知道类型,才能做出最准确的决定。