我是开源库的开发人员.我们的一个类是模仿一堆不同的类型.目前,该定义位于头文件中,这会对编译时间产生负面影响,并且还会强制用户包含多于所需的标头.我的目标是:
为了减少编译时间,我想使用C++ 11引入的显式实例化声明.
类方法和成员的定义都是静态的,必须与实现文件中的声明分开.它们应该可以在库外部和内部使用,而无需用户进行显式实例化定义或类似的任何操作.
这必须在支持C++ 11的所有常见编译器上运行跨平台(Visual Studio 2013 +,GCC等)
C++ 11为类模板提供了新功能,特别是" 显式实例化声明 ".据我所知,这可以在这种情况下使用.以前的问题在类似的上下文中处理了这个问题,例如如何使用extern模板和分离模板类的定义/实例化而没有'extern'但是那些不处理库导出,如果客户端尝试使用共享库,它们的解决方案会导致链接器错误.
目前我已经设法以在Visual Studio 2015上编译,链接和运行的方式实现它,但我不确定我是否正确使用了关键字,尤其是在这种情况下的__declspec.这就是我得到的(简化):
// class.h
template<typename T>
class PropertyHelper;
template<typename T>
class PropertyHelper<const T>
{
public:
typedef typename PropertyHelper<T>::return_type return_type;
static inline return_type fromString(const String& str)
{
return PropertyHelper<T>::fromString(str);
}
static const int SomeValue;
};
template<>
class EXPORTDEF PropertyHelper<float>
{
public:
typedef float return_type;
static return_type fromString(const String& str);
static const int SomeValue;
};
extern template EXPORTDEF class PropertyHelper<float>;
Run Code Online (Sandbox Code Playgroud)
最后一行是显式实例化声明.据我所知,这意味着客户不必每次都自己申报.EXPORTDEF是Windows上的__declspec(dllexport)或__declspec(dllimport)的定义.我不确定是否需要将其放在上面的行中,因为以下内容还编译,链接和运行:
extern …Run Code Online (Sandbox Code Playgroud) 以下代码声明了一个模板,声明了一个显式的实例化定义,然后声明了一个显式的实例化声明:
template <typename T>
T Double(T number)
{
return number * 2;
}
extern template int Double<int>(int); // declaration
template int Double<int>(int t); // definition
int main(int argc, char* argv[])
{
int n = Double(10);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
给出错误:
error C2929: 'int Double<int>(int)' : explicit instantiation; cannot explicitly force and suppress instantiation of template-class member
Run Code Online (Sandbox Code Playgroud)
在Visual Studio 2012中.
我的印象来自http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1987.htm,这应该是有效的,因为定义遵循声明.
我错过了什么吗?