我们正在设计一个新的C ++库,并决定采用基于模板的方法以及针对极端情况的一些特定的部分模板特化。特别是,这将是一个仅限标题的模板库。
现在,有人担心这会导致二进制文件中出现大量代码重复,因为此模板“库”将被编译到任何其他共享库或使用它的可执行文件中(可以说只是那些使用过的部分)。我仍然认为这不是一个问题(特别是,编译器甚至可以内联不能跨共享库边界的内容)。
但是,既然我们知道将要使用的有限类型集合,有没有办法将这个头编译成一个库,并提供一个只有声明而不是其他的不同的头?< / strong>请注意,库不仅必须包含通用实现,还必须包含部分特化..
答案 0 :(得分:6)
是。您可以做的是使用编译器的显式模板实例化语法显式实例化CPP文件中的模板。以下是如何在VC ++中使用显式实例化:http://msdn.microsoft.com/en-us/library/by56e477(v=VS.100).aspx。 G ++有一个类似的功能:http://gcc.gnu.org/onlinedocs/gcc/Template-Instantiation.html#Template-Instantiation。
请注意,C ++ 11引入了显式实例化的标准语法,如[14.7.2] FDIS的显式实例化所述:
显式实例化的语法是:
显式实例:
extern
opttemplate
声明
答案 1 :(得分:3)
C++ Shared Library with Templates: Undefined symbols error 有些答案涵盖了这个主题。总结简短:如果您强制显式地在共享库代码中实例化模板,则可能。但是,它需要对共享库侧所有使用的模板的所有使用类型进行明确规范。
答案 2 :(得分:1)
如果它只是模板,那么就没有共享库。有关具体示例,请参阅各种Boost项目。只有当你有非模板代码时才会有一个库。一个具体的例子是例如Boost Date_Time和日期格式化和解析;您可以使用具有或不具有该功能的库,因此可以使用或不使用链接。
没有共享库在依赖性较低的意义上是很好的。缺点是您的二进制文件可能会变得更大,并且您的编译时间成本会更高。但存储相当便宜(除非您在嵌入式系统中工作是其他特殊情况),编译通常是固定的一次性成本。
答案 3 :(得分:0)
虽然没有标准的方法,但通常可以使用特定于实现的技术。很久以前我和Borland的C ++ Builder一起做过。我们的想法是声明您的模板从需要驻留的共享库中导出,并将它们导入到使用它们的位置。我这样做的方式是:
// A.h
#ifdef GENERATE
# define DECL __declspec(dllexport)
#else
# define DECL __declspec(dllimport)
#endif
template <typename T> class DECL C {
};
// A.cpp
#define GENERATE
#include "A.h"
template class DECL A<int>;
请注意,我无法访问原始代码,因此可能包含错误。 This blog entry描述了一种非常类似的方法。
根据你的措辞我怀疑你不在Windows上,所以你必须找出你的编译器是否以及如何采用这种方法。我希望这足以让你朝着正确的方向前进。