为什么`this`是一个依赖于类型的表达式,即使模板类没有基类?

Car*_*sel 11 c++ templates dependent-name

可以编译以下代码而不会出现错误:

template <typename T> struct A {
    void f() { this->whatever; } // whatever is not declared before
};
int main() {
    A<int> a;
}
Run Code Online (Sandbox Code Playgroud)

我知道这是因为this是一个依赖于类型的表达式,它使名称查找whatever被推迟,直到知道实际的模板参数.由于f()在这种情况下从不使用成员函数,因此不A<T>::f存在实例化,并且whatever永远不会执行名称查找.

我可以理解,this如果类模板具有依赖于类型的基类,那么它是类型相关的:

template <typename T> struct B { T whatever; };
template <typename T> struct A : B<T> {
    void f() { this->whatever; }
};
int main() {
    A<int> a;
}
Run Code Online (Sandbox Code Playgroud)

在解析模板类的定义时A,不可能知道它的基类是什么,这使得this->whatever潜在合法(B<T>可能有一个成员命名whatever).相反,this->whatever一旦在f某个地方使用成员函数,我就没有看到任何在第一个例子中合法的可能性.

那么,this->whatever在第一个例子中的某些点可能合法吗?如果没有,this在这种情况下是否还有其他原因应该被视为依赖于类型的表达式?

Joh*_*itb 4

您的代码“格式错误,无需诊断”,因为A::f. 事实上,规范说它既this->whatever不是未知专业化的成员(因为没有依赖基类),也不是当前实例化的成员(因为它没有在非依赖基类中声明,也没有在类模板中声明)本身)。此外,这会使您的代码无效,并且同样不需要(但允许)诊断。/sf/answers/1230592261/对此进行了更详细的解释

this是类型相关的,因为您还不知道定义中的模板参数值。因此,例如SomeOtherTemplate<decltype(*this)>不能立即解析,而是需要等到 的类模板this被实例化(所以你需要一个typenamebefore SomeOtherTemplate<decltype(*this)>::type)。

然而,仅仅因为this依赖于类型,并不意味着this->whatever也是如此。如上所述,规范具有正确地将其分类为无效的工具,并且实际上也不具有类型this->whatever依赖性。它说

如果类成员访问表达式 ([expr.ref]) 引用当前实例化的成员并且引用的成员的类型是相关的,或者类成员访问表达式引用未知成员的成员,则该表达式是类型相关的专业化。