我想知道为什么下面的代码在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;
}
在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中读到的
显式实例化和显式声明 除非明确,否则专业化不得出现在程序中 实例化遵循显式特化的声明。
我相信情况就是这样。我错过了什么吗?
答案 0 :(得分:8)
msvc 2012 正确拒绝标记为// error C2998
的行,
以前的诊断是错误的,应该被接受;因为它在编译器的newer versions中。
注意:可以找到与C2950相关的错误报告here 。
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 。
此错误是准确的;你没有提到依赖于模板参数的东西,这意味着你不应该对有问题的定义使用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<>
语法。定义显式专用成员类的成员时也是如此。