在共享对象/ DLL中使用模板化的类和函数

时间:2010-01-21 15:02:06

标签: c++ visual-c++ dll templates

我正在开发一个跨越很多共享库的相当大的项目。我们也非常依赖STL,Boost和我们自己的模板类和函数。许多导出的类包含模板成员,导出的函数包含模板参数。

以下是我如何进行图书馆导出的精简示例:

#if defined(_MSC_VER) && defined(_DLL)
    //    Microsoft 
    #define EXPORT __declspec(dllexport)
    #define IMPORT __declspec(dllimport)
#elif defined(_GCC)
    //    GCC
    #define EXPORT __attribute__((visibility("default")))
    #define IMPORT
#else
    //    do nothing and hope for the best at link time
    #define EXPORT
    #define IMPORT
#endif

#ifdef _CORE_COMPILATION
#define PUBLIC_CORE EXPORT
#define EXTERNAL_CORE
#else
#define PUBLIC_CORE IMPORT
#define EXTERNAL_CORE extern
#endif

#include <deque>

//    force exporting of templates
EXTERNAL_CORE template class PUBLIC_CORE std::allocator<int>;
EXTERNAL_CORE template class PUBLIC_CORE std::deque<int, std::allocator<int> >;

class PUBLIC_CORE MyObject
{
private:
    std::deque<int> m_deque;
};

SO ,我的问题是,当我在Visual Studio中编译时(2008年和2010年),我收到以下警告:

  

警告C4251:   '的std :: _ Deque_val&LT; _Ty,_Alloc&GT; :: _ Almap'   :class'std :: allocator&lt; _Ty&gt;'需要   有dll接口可供使用   班级的客户   '的std :: _ Deque_val&LT; _Ty,_Alloc&GT;'

这似乎意味着我没有导出std::allocator<int>,我有。并且它不像我的导出不正确,因为不包括

EXTERNAL_CORE template class PUBLIC_CORE std::allocator<int>;
EXTERNAL_CORE template class PUBLIC_CORE std::deque<int, std::allocator<int> >;

产生警告:

  

警告C4251:'MyObject :: m_deque':   class'std :: deque&lt; _Ty&gt;'需要有   dll-interface供客户使用   class'MyObject'

我唯一能想到的是_Ty关于std::allocator的警告正在谈论的不是int,但我似乎无法找到任何迹象表明否则,因为std::deque<int>将在逻辑上分配std::allocator<int>

消费应用程序可以很好地使用该类,但我有一种直觉,即不应忽略此警告。在Linux中使用g ++进行编译时,不会发出任何错误(尽管这并不意味着它正常工作)。 g ++会自动执行MSVC无法做到的事情吗?我一直瞄准Linux上的GCC,OSX上的LLVM和Windows上的MSVC,但是我可能会转向MinGW进行Windows开发,因此放弃MSVC并不是不可能的(如果这被证明是太大的不便)

1 个答案:

答案 0 :(得分:3)

您可能知道,导出文件中的模板实际上是“允许为编译器填写您认为必要的任何内容”。

这意味着如果使用编译器A编译头文件,它可能会实例化一个与编译器B完全不同的deque<int>。一些成员的顺序可能会改变,甚至某些成员的实际类型变量

这就是编译器警告你的内容。

编辑:给解释带来一些后果

因此,当您使用相同的编译器编译时,您的共享库只能很好地协同工作。如果您希望它们一起工作,您可以确保所有客户端代码“看到”相同的声明(通过使用相同的stl实现),或者从向API添加模板后退一步。