模板专业化静态初始化icc + vc vs gcc + clang

时间:2016-08-10 23:09:01

标签: c++ gcc visual-c++ clang language-lawyer

看起来编译器接受不同的语法来初始化模板中的静态。

template <typename T> struct TBase
{   
    static const int i;
    static const int j;
};

// compile: gcc + clang + visual + icc
template <> const int TBase<double>::i=1;

// compile: vc + icc
// failed gcc, gcc -fpermissive, clang
const int TBase<double>::j=2;

标准是否接受没有template<>的语法,即使它目前显然不可移植?

编辑: 将此代码放在vc ++ TBase<double>::i==1TBase<double>::j==2上,就像没有模板的代码一样。

struct noTemplate 
{   
    static const int i;
    static const int j;
};
const int noTemplate::i=1; 
const int noTemplate::j=2;

gcc和clang似乎强制使用template<>来初始化这个静态,我不明白为什么编译器需要这些信息。

2 个答案:

答案 0 :(得分:3)

这两种语法都有效,但它们意味着不同的东西。 template<>的语法用于声明或定义隐式或显式实例化的成员:

template<class T> struct X { static int const i; };

template<> int const X<char>::i = 1; // Define member of an implicit instantiation

template struct X<long>;
template<> int const X<long>::i = 2; // Define member of an explicit instantiation

没有template<>的语法用于定义专业化的成员:

template<> struct X<float> { static int const j; }; // Class template specialization
int const X<float>::j = 3;

答案 1 :(得分:0)

是的,它似乎符合标准。

至少包含C ++ 14标准(希望它的最终版本包含它,我已经使用预发布版http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3797.pdf进行了检查。)

  

14.7.1隐式实例化   ...   除非已显式实例化或明确专门化类模板或成员模板的成员,否则在需要成员定义存在的上下文中引用特化时,将隐式实例化成员的特化;特别是,除非静态数据成员本身以需要静态数据成员的定义存在的方式使用,否则不会发生静态数据成员的初始化(以及任何相关的副作用)。   ...

const int TBase<double>::j=0;您正在访问(非专业化)j的静态成员TBase<double>,因此如果不存在,则应创建TBase<double>专门化。

没有模板的代码示例,证明您只是访问struct member:

struct WithoutTemplate {
    static const int i;
};
const int WithoutTemplate::i = 5;