MSVC中的模板静态定义和显式特化实例化错误

时间:2014-06-20 18:40:38

标签: c++ templates language-lawyer explicit-specialization explicit-instantiation

我想知道为什么下面的代码在gcc中运行得很好

#include <iostream>
using namespace std;

template<typename T>
struct F { 
  static T const value;
};

template<> 
struct F<int> { // Specialization
    static int const value; 
}; 

template struct F<int>;

template<typename T>
T const F<T>::value = sizeof(T);

template<>
int const F<int>::value = 42;

int main() {

    struct F<int> ma;
    cout << ma.value;

    return 0;
}

http://ideone.com/wvrurz

在MSVC 2012上我无法编译:

#include <iostream>
using namespace std;

template<typename T>
struct F {
  static T const value;
};

template<> 
struct F<int> { // Specialization
    static int const value; 
};

//template struct F<int>; // error C2950: 'F<int>' : cannot explicitly instantiate an explicit specialization

template<typename T>
T const F<T>::value = sizeof(T);

//template<>
//int const F<int>::value = 42; // error C2998: 'const int F<int>::value' : cannot be a template definition

int main() {

    struct F<int> ma;
    cout << ma.value;

    return 0;
}

从我在n3242§14.75中读到的

  

显式实例化和显式声明   除非明确,否则专业化不得出现在程序中   实例化遵循显式特化的声明。

我相信情况就是这样。我错过了什么吗?

1 个答案:

答案 0 :(得分:8)

太长了; DIDN&#39; T READ

  • msvc 2012 正确拒绝标记为// error C2998的行,

  • 以前的诊断是错误的,应该被接受;因为它在编译器的newer versions中。

注意:可以找到与C2950相关的错误报告here


关于C2950

msvc 2012 对相关行发出诊断是错误的。

template<class T> struct A;

template<>
struct A<int> { };

template struct A<int>; // legal

int main () { }

标准规定显式实例化应该包含 simple-template-id ,这正是A<int>的内容,并且说明了;它是合法 C ++

  

14.6.2p3 明确的实例化 [temp.explicit]

     
    

如果显式实例化是针对类或成员类的,声明中的 elaborated-type-specifier 应包含 simple-template-id < / em>的

  

  

14.2p1 模板专精的名称 [temp.names]

     
    

模板专业化(14.7)可以通过 template-id 引用:

simple-template-id:
         template-name < template-argument-list_opt >
  


更改措辞: C ++ 03 vs C ++ 11

14.7.2p5 C ++ 11 开始有一些新的措辞,它是在以下缺陷报告之后实现的:< / p>

  

14.7.2p5 明确的实例化 [temp.explicit]

     
    

对于给定的模板参数集,如果在声明该模板的显式特化之后出现模板的显式实例化,则显式实例化无效。

  

  

注意:感谢 @ dyp 关注以前关联的 DR


关于C2998

此错误是准确的;你没有提到依赖于模板参数的东西,这意味着你不应该对有问题的定义使用template<>

较新版本的gcc会对其发出诊断,而 clang 会正确拒绝此类定义。

template<class T> struct A;

template<>
struct A<int> { 
  static int const value;
};

template<> int const A<int>::value = 42; // ill-formed, `value` does not depend on
                                         //              any template parameter since it's
                                         //              explicitly a part of `A<int>`

int main () { }
gcc   => foo.cpp:8:22: warning: too many template headers for A<int>::value (should be 0)
clang => foo.cpp:8:1: error: extraneous 'template<>' in declaration of variable 'value'
msvc  => foo.cpp(8) : error C2998: 'const int A<int>::value' : cannot be a template definition

以上诊断是正确的。


有问题的行违反了标准的以下部分:

  

14.7.3p5 明确的专业化 [temp.expl.spec]

     
    

显式专用类模板的成员以与普通类成员相同的方式定义,而不是使用template<>语法。定义显式专用成员类的成员时也是如此。