看起来编译器接受不同的语法来初始化模板中的静态。
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==1
和TBase<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<>
来初始化这个静态,我不明白为什么编译器需要这些信息。
答案 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;