C++ 初始化模板化类的静态成员
我试图弄明白为什么这个例子不能编译。我的理解是,如果静态变量没有显式设置,那么它默认为0。在下面的五个示例中,其中四个的行为与我预期的一样,但是被注释掉的一个不会编译C++ 初始化模板化类的静态成员,c++,templates,initialization,static-members,C++,Templates,Initialization,Static Members,我试图弄明白为什么这个例子不能编译。我的理解是,如果静态变量没有显式设置,那么它默认为0。在下面的五个示例中,其中四个的行为与我预期的一样,但是被注释掉的一个不会编译 #include <iostream> class Foo { public: static int i; static int j; }; template <int n> class Bar { public: Bar(int) { } static int i; };
#include <iostream>
class Foo
{
public:
static int i;
static int j;
};
template <int n>
class Bar
{
public:
Bar(int) { }
static int i;
};
static int i;
int Foo::i;
int Foo::j = 1;
template <> int Bar<2>::i;
template <> int Bar<3>::i = 3;
int main(int argc, char** argv)
{
std::cout << "i " << i << std::endl;
std::cout << "Foo::i " << Foo::i << std::endl;
std::cout << "Foo::j " << Foo::j << std::endl;
//std::cout << "Bar<2>::i " << Bar<2>::i << std::endl; // Doesn't compile?
std::cout << "Bar<3>::i " << Bar<3>::i << std::endl;
return 0;
}
#包括
福班
{
公众:
静态int-i;
静态int j;
};
模板
分类栏
{
公众:
Bar(int){}
静态int-i;
};
静态int-i;
int Foo::i;
intfoo::j=1;
模板int-Bar::i;
模板整型条::i=3;
int main(int argc,字符**argv)
{
STD::CUT< P>根据标准C++最新草案,它表示
14.7.3/13如果声明包含初始值设定项,则模板静态数据成员的显式专门化为定义;否则为声明。
[注意:需要默认初始化的模板的静态数据成员的定义必须使用带括号的初始化列表:
template<> X Q<int>::x; //declaration
template<> X Q<int>::x (); // error: declares a function
template<> X Q<int>::x { }; // definition
模板xq::X;//声明
模板xq::X();//错误:声明函数
模板xq::X{};//定义
-[完注]
<> P>所以,如果你的编译器支持它,你所要求的是可能的。< P>在当前C++标准的规则下,专门化的代码>代码模板ItBar::i;只是一个声明,而不是一个定义。
要成为定义,必须指定初始值设定者。(见第14.7.3/15条)
除此之外,您还缺少一个非常常见的情况:模板的非专业静态成员的定义:
template <int n> int Bar<n>::i;
模板int-Bar::i;
这为N不等于2或3的Bar::i
提供了一个定义。的重复项。@Chubsdad:毫无疑问,这是“对Bar::i
的未定义引用”或其他含义。在OP的代码中,模板int Bar::i;
是一个非定义声明(请参阅链接的副本以获取litb的详细解释)我不太明白litb的答案,因为在另一种情况下,代码略有不同。他是说我必须显式设置Bar::I才能使用它吗?如果可能的话,我希望能够在不必显式设置的情况下声明它。14.7/1:类模板专门化的隐式实例化导致隐式实例化I在类成员函数、成员类、*静态数据成员*和成员模板的声明(而不是定义或默认参数)中,它会导致成员匿名联合定义的隐式实例化。这可能就是正在发生的情况。(我的重点。)@亚历克斯:对:你必须提供一个初始值设定项,它才能成为一个定义。否则,它只是一个声明。