模板基类的静态成员不会导出到共享库

时间:2015-03-07 15:44:45

标签: c++ shared-libraries ubuntu-14.04 nm template-classes

我有一个班级' ModelManager'它来自模板类' TModelManager'。他们的声明如下:

template<class TModel,class TModelMesh,class TModelSubMesh>
    class TModelManager
{
protected:
    static std::map<std::string,ModelHandle> m_models;
    static std::vector<std::map<std::string,ModelHandle>::iterator> m_marked;
    [...]
};

class DLLNETWORK ModelManager
    : public TModelManager<Model,ModelMesh,ModelSubMesh>
{
    [...]
};

有两个共享库,&#34;共享&#34;和&#34;服务器&#34;。

在&#34; shared&#34; -library中,DLLNETWORK相当于&#39; __属性__((可见性(&#34;默认&#34;)))&#39;在linux系统上,导出类。模板类的成员定义为(在cpp文件中):

template<class TModel,class TModelMesh,class TModelSubMesh>
    DLLNETWORK std::map<std::string,ModelHandle> TModelManager<TModel,TModelMesh,TModelSubMesh>::m_models;
template<class TModel,class TModelMesh,class TModelSubMesh>
    DLLNETWORK std::vector<std::map<std::string,ModelHandle>::iterator> TModelManager<TModel,TModelMesh,TModelSubMesh>::m_marked;

在&#34;服务器&#34; -library中,DLLNETWORK是一个空的定义,以确保导入该类。 &#34;服务器&#34; -library与&#34; shared&#34; -library链接。

编译得很好。

在运行时,&#34;服务器&#34; -library会动态加载,这也会导致加载&#34; shared&#34; -library。但是,这会导致以下错误:

Unable to load library 'lib/libserver_x64.so': lib/libserver_x64.so: undefined symbol: _ZN13TModelManagerI5Model9ModelMesh12ModelSubMeshE8m_markedE

我已经使用了&#34; ldd&#34; &#34;服务器&#34; -library上的实用程序,它确认它与&#34; shared&#34; -library相关联,并且可以找到它。

然后我使用了&#34; nm&#34;用于查找与TModelManager类相关的所有符号的实用程序。这是结果:

nm -D libshared_x64.so | grep ModelManager
0000000000b15610 u _ZGVN13TModelManagerI5Model9ModelMesh12ModelSubMeshE8m_modelsE
000000000072d1b0 T _ZN12ModelManager21CreateFromBrushMeshesERSt6vectorIP9BrushMeshSaIS2_EE
000000000072d10c T _ZN12ModelManager4LoadESs
000000000072d950 W _ZN13TModelManagerI5Model9ModelMesh12ModelSubMeshE21CreateFromBrushMeshesERSt6vectorIP9BrushMeshSaIS6_EE
000000000072d62c W _ZN13TModelManagerI5Model9ModelMesh12ModelSubMeshE4LoadESsPFP8MaterialPKcE
0000000000b155e0 u _ZN13TModelManagerI5Model9ModelMesh12ModelSubMeshE8m_modelsE

一切都在那里,除了&#34; m_marked&#34;会员。使用不同的地址找到&#34; m_models&#34; -member两次。

我根本不理解这一点,“m_marked&#39; -member的定义方式与”m_models&#39; -member相同,所以为什么不是&#39;它出口了吗?为什么&#39; m_models&#39;成员出现两次?

//编辑:

我没注意到&#39; U&#39;在'm_models&#39;的nm结果前面。这意味着他们未定义。

我定义它们有什么问题吗?

1 个答案:

答案 0 :(得分:2)

  

模板类的成员定义为(在cpp文件中):

您似乎假设这些定义将在cpp文件中实例化,但除非该cpp文件中的某些内容使用它们,否则成员将实例化,因此相应的符号将不会在编译的目标文件中发出。

服务器库中使用这些静态成员的代码无法隐式实例化它们,因为您已将这些定义隐藏在cpp文件中。

需要为您正在使用的所有特化项显式实例化静态成员定义,或者您需要将这些定义放在标题中。