模板类静态是否在最终二进制文件中一致的共享库中实例化不同?

时间:2017-04-15 20:32:49

标签: c++ templates

我有几个类充当唯一类型id生成器:​​

// <type_generator.hpp>
template<typename SK,typename T>
struct Component
{
    static uint const index;
};

template<typename SK>
class ComponentCount
{
    template<typename CSK,typename CT>
    friend struct Component;

private:
    template<typename T>
    static uint next() {
        return ComponentCount<SK>::get_counter();
    }

    static uint get_counter()
    {
        static uint counter = 0;
        return counter++;
    }
};

template<typename SK,typename T>
uint const Component<SK,T>::index(ComponentCount<SK>::template next<T>());

struct Key{};

现在说我在多个不同的库中以不同的方式实例化上述类模板:

// libsrc0
uint const x0 = Component<Key,int>::index;
uint const x1 = Component<Key,std::string>::index;
uint const x2 = Component<Key,double>::index;

// libsrc1
uint const x0 = Component<Key,std::string>::index;
uint const x1 = Component<Key,double>::index;
uint const x2 = Component<Key,int>::index;

// libsrc2
uint const x0 = Component<Key,int>::index;
uint const x1 = Component<Key,std::string>::index;

是否有任何保证链接libsrc0,libsrc1和libsrc2的二进制文件将具有Component :: index索引的一致定义,并且每个索引都设置为不同的值?

Component<Key,int>::index
Component<Key,std::string>::index
Component<Key,double>::index

1 个答案:

答案 0 :(得分:3)

  

是否可以保证链接libsrc0,libsrc1和libsrc2的二进制文件具有Component :: index索引的一致定义?

是。静态数据成员始终具有 external linkage ,这意味着相同的名称是指所有翻译单元中的同一对象。类模板的静态数据成员不是例外。毕竟,类模板实例的行为与所有其他类一样。

即使每个共享库文件都有自己的Component模板实例,特别是Component::index变量,但在加载这些库时,只会选择并初始化一个实例。例如,我发现Linux下的GNU加载程序在编译可执行文件时总是从命令行上指定的第一个库中选择一个对象-l选项,而其他库中遇到的所有其他具有相同名称的对象都会被忽略