基本模板对方法的调用无法编译

问题描述

我有一个模板结构,它继承了另一个模板结构。它无法在不同的编译器中进行编译(在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;
}