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

Template specialization static initialization icc+vc vs gcc+clang

本文关键字:icc+vc vs gcc+clang 初始化 静态 专用      更新时间:2023-10-16

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

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<> 来初始化这个静态的,我不明白为什么编译器需要这些信息。

这两种语法都是有效的,但它们的含义不同。带有 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;

是的,它似乎符合标准。

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

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

通过const int TBase<double>::j=0;您正在访问(不专用化(TBase<double>的静态成员j,因此如果尚不存在TBase<double>应创建专用化。

没有模板的代码示例,证明您只是在访问结构成员:

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