问题描述
我有一个模板结构,它继承了另一个模板结构。它无法在不同的编译器中进行编译(在VS2017和Linux上的clang中)。代码中的一个简单更改即可解决。 代码是:
template<typename T>
struct base {
int GetValue2() { return 0; }
};
template<typename T>
struct derived : public base<T>
{
int GetValue() { return GetValue2(); }
};
int main() {
derived<int> a;
return 1;
}
如果我换行 int GetValue(){return GetValue2(); } 至: int GetValue(){返回this-> GetValue2(); } 一切都可以编译。
有人知道发生了什么吗?
解决方法
这里有两个阶段的名称查找。
在GetValue()中,GetValue2不在依赖上下文中使用,因此编译器将查找在封闭的名称空间范围(此处为全局范围)中声明的名称。
它不会考虑基类,因为它是依赖的,即使在声明Derived之后,您也可以声明Base的特化,因此编译器无法真正知道我要指的是什么。如果没有全局变量i,那么您将收到一条错误消息。
为了清楚表明您想要基类的成员,您需要将查找推迟到实例化时间为止,在该时间知道基类。为此,您需要通过使用this-> i(请记住,它的类型为Derived *,因此显然是依赖的)或使用Base :: i在依赖的上下文中访问i。或者,可以通过using-声明将Base :: i纳入范围。
template<typename T>
struct base {
int GetValue2() { return 0; }
};
template<typename T>
struct derived : public base<T>
{
int GetValue_using() {
using base<T>::GetValue2; // won't compile with gcc,place it outside the function (ok with clang and msvc)
return GetValue2();
}
int GetValue_this() { return this->GetValue2(); }
int GetValue_base() { return base<T>::GetValue2(); }
};
int main() {
derived<int> a;
return 1;
}