6

我试图弄清楚为什么这个例子不能编译。我的理解是,如果未明确设置静态变量,则默认为 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;
}

为什么不做与orint Bar<2>::i相同的事情?int Foo::istatic int i

编辑:我忘记将 template<> 添加到 Bar<2> 和 Bar<3> 声明中。(虽然没有解决问题,仍然出现链接器错误)

4

2 回答 2

5

在当前 C++ 标准的规则下,特化template <> int Bar<2>::i;只是一个声明,而不是一个定义。要成为定义,您必须指定一个初始化程序。(见第 14.7.3/15 条)

除此之外,您还遗漏了一个非常常见的情况:模板的非专业静态成员的定义:

template <int n> int Bar<n>::i;

Bar<N>::i这为 N 不等于 2 或 3提供了定义。

于 2010-09-08T08:17:50.477 回答
1

根据标准 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

——尾注]

因此,如果您的编译器支持它,那么您的要求是可能的。

于 2010-09-08T06:17:47.520 回答