在clang中实例化后的静态成员初始化

时间:2014-08-08 09:53:21

标签: c++ gcc clang

这样的代码可以由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是否更宽松并编译非标准代码?

4 个答案:

答案 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允许非标准声明。

相关问题