【问题标题】:Why are static members of template classes not unique为什么模板类的静态成员不是唯一的
【发布时间】:2016-05-20 11:47:27
【问题描述】:

看看下面的代码:

#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;
}

这将打印出 2 个不同的地址。我可以理解为什么在这种情况下,barT 类型,因此Foo&lt;T&gt; 中不同 T 的实例化将为您提供不同的静态成员。但是,如果我们将bar 更改为我们已经知道的类型(例如static int bar)这个still happens

为什么会这样?为什么不将bar 重新用于多个模板实例化?我如何才能在不同的实例化中只获得 1 个 bar 对象?

【问题讨论】:

    标签: c++ templates c++14 static-members


    【解决方案1】:

    这里没有什么真正令人惊讶的事情。

    template <typename T>
    class Foo
    {
        //...
    };
    

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

    如果您希望所有不同类型的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;
    }
    

    输出:

    10
    20
    

    Live Example

    【讨论】:

    • @Nawaz 没问题。我确实质疑以及类模板相同的事实是否应该是以及类模板相同的事实
    【解决方案2】:

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

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

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

    【讨论】:

    • @NathanOliver 我假设“他们的类型”是指bar 成员的类型;不过,它可以使用消歧义。
    • 哦,会员类型。我虽然你在谈论类类型。那就别管我了。
    • @NathanOliver 没关系。无论如何,我试图对其进行编辑以避免歧义。
    • @songyuanyao 看起来不错。谢谢。
    【解决方案3】:

    Foo&lt;int&gt;::barFoo&lt;double&gt;::bar 是两个不同的全局(静态可访问的类级别)变量。他们不一样。考虑这段代码:

    template <typename T>
    class Foo
    {
    public:
        static T var1;
        static int var2;
    };
    

    您认为var2 的相对位置是什么(假设编译器将var2 放在var1 之后)?在一种情况下,它可能相对仅提前 1 个字节 (foo&lt;char&gt;),但在其他数据类型的情况下提前 8 个字节。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-16
      • 2017-10-20
      • 2012-01-21
      • 1970-01-01
      • 1970-01-01
      • 2012-12-13
      相关资源
      最近更新 更多