c++模板名称:在Visual Studio中编译错误,在gcc中工作正常

C++ Template names: compilation error in Visual Studio, works fine in gcc

本文关键字:错误 编译 gcc 工作 Studio Visual c++      更新时间:2023-10-16

使用Visual Studio Express 2012无法编译以下代码:

template< int d >
class MyVector
{
public:
    typedef double X;
};
class Base
{
public:
    int d;
    int m() {
        return 0;
    }
};
template<int d>
class Derived1 : Base
{
    typedef typename MyVector<d>::X X;
};
template<int m>
class Derived2 : Base
{
    typedef typename MyVector<m>::X X;
};

我得到"错误C2327: 'Base::d':不是类型名称,静态或枚举器"在Derived1和"错误C2975: 'd': 'MyVector'的无效模板参数,预期的编译时常量表达式"在Derived2。

当然,很容易看出问题出在模板实参名称与Base成员名称冲突上。如果我将派生模板名改为

template<int ddd>
class Derived1 : Base
{
    typedef typename MyVector<ddd>::X X;
};
template<int mmm>
class Derived2 : Base
{
    typedef typename MyVector<mmm>::X X;
};

代码编译得很好。

但是,原始代码在Linux下使用gcc 4.6.4编译没有任何问题。所以我的问题是:根据标准,哪个编译器是正确的?我认为自己是c++模板的新手,但我的直觉倾向于gcc的解释:毕竟,如果Derived1希望访问基成员'd',它将需要标记'Base::d'或'this->d',所以我想在这种情况下不应该有名称冲突。

这是谁的错?

gcc 4.6.4相对较老;接受代码片段是错误的。

Edit:在此编辑之前,声明4.6.4 "非常旧"。我错误地认为它是在2011年发布的,但实际上它是在2013年4月13日发布的。


《标准》怎么说?(n3337)

14.6.1p9 本地声明的名称 [temp.local]

如果的定义类模板或模板等成员的定义出现在模板定义之外,每个基类不依赖于一个模板参数 (14.6.2) [ Note: >> ]如果基类的名称或基类成员的名字是一样的名称模板参数,基类名称或成员名隐藏了模板参数名称[ << --end note ](3.3.10)。

注释: c++ 03的相关和语义等效的措辞可以在14882:2003中的[temp.local]p7中找到。


上面引用的部分的最后一句话说,如果模板参数的名称与非依赖基中的名称相同,则成员名将有效地隐藏模板参数

gcc的新版本中该错误已经修复。