这样的代码可以由GCC编译,但是clang 3.5失败。
#include <iostream>
using namespace std;
template<typename T>
class C{
public:
const static int x;
};
int main(){
cout << C<int>::x;
}
template<>
const int C<int>::x = 4;
Clang返回消息:
hello.cpp:15:19: error: explicit specialization of 'x' after instantiation
const int C<int>::x = 4;
^
hello.cpp:11:19: note: implicit instantiation first required here
cout << C<int>::x;
^
代码或clang编译器中的错误是什么?它是否符合标准,或者GCC是否更宽松并编译非标准代码?
答案 0 :(得分:3)
程序错了。 C ++ 11 14.7.3 / 6说:
如果模板[...]是明确专用的,则应在首次使用该特化之前声明该特化,这将导致隐式实例化 发生
您的代码在main
中使用它,导致在那里进行隐式实例化,然后在错误消息描述的情况下稍后声明特化。
答案 1 :(得分:1)
如果我没记错的话
必须在第一次使用之前声明专业化,这将导致隐式实例化,在每个发生此类使用的翻译单元中。
(取自http://en.cppreference.com/w/cpp/language/template_specialization)所以看起来GCC比铿锵更宽松......
答案 2 :(得分:1)
int main(){
cout << C<int>::x; // 1
}
template<>
const int C<int>::x = 4; // 2
当编译器编译1时,它会尝试从C<int>
专门化template <typename T> class C
。由于您的模板专业化尚未被编译器读取,因此编译器会隐式地专门化C<int>
。因此,C<int>::x
也是编译器专用的。
编译2,C<int>::x
已由编译器专用。你正在尝试专攻它两次,所以它失败了。
live example这是正确的。代码:
#include <iostream>
using namespace std;
template<typename T>
class C{
public:
const static int x;
};
template<>
const int C<int>::x = 4;
int main(){
cout << C<int>::x;
}
答案 3 :(得分:0)
标准告诉您在使用之前需要声明专业化。
因此标准行为是在主函数之前声明模板初始化。
某些编译器在某些情况下允许更多自由,并且似乎在这种情况下gcc允许非标准声明。