为什么当VS不需要模板时GCC需要额外的声明? [英] Why does GCC need extra declarations in templates when VS does not?

查看:129
本文介绍了为什么当VS不需要模板时GCC需要额外的声明?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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行注释,我得到这些错误:

If I comment out lines A and B, this code compiles fine under Visual Studio 2008. Yet when I compile under GCC 4.1 with lines A and B commented, I get these errors:


在成员函数void Derived :: foo ':

错误:'t'未在此范围中声明

错误:没有依赖于模板参数的get参数,因此声明'get '必须可用

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行。

Why would one compiler require lines A and B while the other doesn't? Is there a way to simplify this? In other words, if derived classes use 20 things from the base class, I have to put 20 lines of declarations for every class deriving from Base! Is there a way around this that doesn't require so many declarations?

推荐答案

GCC在这种情况下是正确的,而Visual Studio错误地接受一个畸形的程序。请查看GCC手册中有关名称查找的部分。释义:

GCC is right in this case, and Visual Studio mistakenly accepts a malformed program. Have a look at the section on Name lookup in the GCC manual. Paraphrasing:


[T]他调用[ get()]依赖于模板参数(没有依赖于类型T的参数,并且没有另外规定调用应该在一个[template-]依赖的上下文中)。 因此,此类函数的全局声明必须可用,因为基类中的一个在实例化时间之前不可见。

[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.

您可以通过以下三种方式来解决此问题:

You can get around this in either of three ways:


  • 您已经在使用的声明。

  • Base< T> :: get()

  • this-> get()

  • The declarations you are already using.
  • Base<T>::get()
  • this->get()

(还有第四种方法,如果你想屈服于黑暗面:

(There is also a fourth way, if you want to succumb to the Dark Side:


使用 -fpermissive 标志还会让编译器接受代码,通过标记所有在定义模板时没有声明的函数调用,以便稍后在实例化时查找,就好像它是一个依赖调用我们不推荐使用 -fpermissive 来解决无效代码,它也将只捕获调用基类中的函数的情况,而不是使用基类中的变量(如上面的示例)。

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 ++。)

But I would recommend against that, both for the reason mentioned in the manual, and for the reason that your code will still be invalid C++.)

这篇关于为什么当VS不需要模板时GCC需要额外的声明?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆