template<typename T>
class Base
{
protected:
Base() {}
T& get() { return t; }
T t;
};
template<typename T>
class Derived : public Base<T>
{
public:
Base<T>::get; // Line A
Base<T>::t; // Line B
void foo() { t = 4; get(); }
};
int main() { return 0; }
如果我注释掉 A 行和 B 行,这段代码在 Visual Studio 2008 下编译得很好。但是当我在 GCC 4.1 下编译并注释行 A 和 B 时,我得到了这些错误:
In member function ‘void Derived::foo()’:
error: ‘t’ was not declared in this scope
error: there are no arguments to ‘get’ that depend on a template parameter, so a declaration of ‘get’ must be available
为什么一个编译器需要 A 行和 B 行,而另一个不需要?有没有办法简化这个?换句话说,如果派生类使用来自基类的 20 个东西,我必须为从 Base 派生的每个类放置 20 行声明!有没有不需要这么多声明的方法?
最佳答案
GCC 在这种情况下是正确的,Visual Studio 错误地接受了格式错误的程序。看看 Name lookup 上的部分在 GCC 手册中。释义:
[T]he call to [
get()
] is not dependent on template arguments (there are no arguments that depend on the type T, and it is also not otherwise specified that the call should be in a [template-]dependent context). Thus a global declaration of such a function must be available, since the one in the base class is not visible until instantiation time.
您可以通过以下三种方式之一解决此问题:
- 您已经在使用的声明。
-
Base<T>::get()
-
this->get()
(还有第四种方式,如果你想屈服于黑暗面:
Using the
-fpermissive
flag will also let the compiler accept the code, by marking all function calls for which no declaration is visible at the time of definition of the template for later lookup at instantiation time, as if it were a dependent call. We do not recommend using-fpermissive
to work around invalid code, and it will also only catch cases where functions in base classes are called, not where variables in base classes are used (as in the example above).
但我不建议这样做,因为手册中提到的原因,以及您的代码仍然是无效的 C++ 的原因。)
关于c++ - 为什么 GCC 需要在模板中额外声明而 VS 不需要?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2812470/