我试图弄清楚为什么这个例子不能编译。我的理解是,如果没有显式设置静态变量,那么它默认为0.在下面的五个示例中,其中四个行为与我期望的一样,但是被注释掉的那个将不会编译。
#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 Bar<2>::i
与int Foo::i
或static int i
做同样的事情?
编辑:我忘了添加模板&lt;&gt; Bar&lt; 2&gt;和Bar&lt; 3&gt;声明。 (虽然没有解决问题,仍然会遇到链接器错误)
答案 0 :(得分:5)
根据当前C ++标准的规则,专门化template <> int Bar<2>::i;
只是一个声明而不是定义。
要成为定义,您必须指定初始化程序。 (见第14.7.3 / 15条)
除此之外,您错过了一个非常常见的案例:模板的非专业静态成员的定义:
template <int n> int Bar<n>::i;
这为Bar<N>::i
提供了一个不等于2或3的定义。
答案 1 :(得分:1)
根据标准C ++的最新草案,它说
14.7.3 / 13如果声明包含初始化器,则模板的静态数据成员的显式特化是一个定义;否则,这是一个声明 [注意:需要默认初始化的模板的静态数据成员的定义必须使用braced-init-list:
template<> X Q<int>::x; //declaration
template<> X Q<int>::x (); // error: declares a function
template<> X Q<int>::x { }; // definition
- 结束说明]
如果您的编译器支持它,那么您所要求的是可能的。