为什么模板类的静态成员不是唯一的

Som*_*ken 5 c++ templates static-members c++14

看看下面的代码:

#include <iostream>

template <typename T>
class Foo
{
    public:
    static T bar;
};

template <typename T> typename T Foo<T>::bar;

int main() {
    std::cout << "Foo<int>::bar : " << &Foo<int>::bar << std::endl;
    std::cout << "Foo<double>::bar : " << &Foo<double>::bar << std::endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这将打印出2个不同的地址.我可以理解为什么在这种情况下,bar是类型的T,因此不同的T的实例化Foo<T>将获得不同的静态成员.但是,如果我们改变bar为我们已经知道的类型(例如static int bar),这仍然会发生.

为什么会这样?为什么不重复使用bar多个模板实例化?如何bar在不同的实例中只获得1个对象?

Nat*_*ica 11

这里没有什么令人惊讶的事情.

template <typename T>
class Foo
{
    //...
};
Run Code Online (Sandbox Code Playgroud)

不是一个类,它是一个模板来消除类.这意味着Foo<A>一个完全不同的类Foo<B>.因此,所有静态成员对于不同的实例化类是唯一的- 并且类模板相同的事实在此上下文中没有相关性,因为它毕竟是模板,实例化类的蓝图.

如果你想要所有不同类型的Foo共享状态,那么你可以让它们从同一个基类继承并将公共信息放在那里.这是一个非常简单的例子:

struct Foo_Base
{
    static int bar;
};

int Foo_Base::bar = 10;

template<typename T>
struct Foo : Foo_Base {};

int main()
{   
    Foo<int> foo_i;
    Foo<double> foo_d;
    std::cout << foo_i.bar << "\n";
    foo_i.bar += 10;
    std::cout << foo_d.bar;
}
Run Code Online (Sandbox Code Playgroud)

输出:

10
20
Run Code Online (Sandbox Code Playgroud)

Live Example


son*_*yao 9

从标准,$ 14.7/6模板实例化和专业化[temp.spec]

从模板实例化的每个类模板特化都有自己的任何静态成员的副本.

Foo<int>并且Foo<double>是不相关的类,即使它们是从同一模板实例化的,并且它们将拥有自己的静态成员bar,即使它们的类型相同(例如两者int).