无法强制实例化专用模板
Posted
技术标签:
【中文标题】无法强制实例化专用模板【英文标题】:Cannot force instantiation of specialized template 【发布时间】:2016-01-12 05:15:30 【问题描述】:在一个静态库中,我在 Class.h 中声明了一个模板,然后我在 Class.cpp 中专门化了一些方法。我想在链接到这个库的项目中使用这个类。
我将特化放在一个 .cpp 文件中,以避免在同一个 .cpp 末尾出现类似“已声明”(???) 之类的错误,一旦该类的所有内容都知道,我就声明了特化的存在。代码如下:
Class.h
#ifndef __CLASS_H__
#define __CLASS_H__
template<class T>
class Class
public:
~Class()
Class()
//...
void method1()
/* unspecialized job here */
;
#endif
Class.cpp
#include "Class.h"
template<>
void Class<bool>::method1()
/* Specialized job for bool here */
// Declare that the class is specialized for bool
template class Class<bool>;
现在,在我使用该库的项目中,当我尝试实例化 class Class<bool>
的对象时,它仍然使用 unspecialized 方法。
有什么问题?在.cpp文件末尾使用“模板”是否正确?
如果重要的话,我会在 Kubuntu/Raspbian 上使用 gcc 4.8/4.9,并且我使用 C++11。
【问题讨论】:
您至少需要在头文件中声明特化(实现仍然可以进入源文件,或者在头文件中,标记为inline
)。否则,您的程序违反了 ODR,因此格式不正确,不需要诊断。
换句话说,客户端代码#include
-ing Class.h
看不到任何东西可以证明不实例化它自己的非专业模板版本。你必须通过向它展示声明来禁止它。
“声明该类专门用于 bool” - template class Class<bool>;
没有做任何此类事情。另外,不要使用保留名称作为包含守卫。
与主题无关,但我建议不要使用带有双下划线或前导下划线后跟大写字母的名称。它们是为实现而保留的,可能会导致未定义的行为(请参阅 C++11 标准的 17.6.4.3.2)。
感谢@Daniel Langr 关于__GUARD_H__
...
【参考方案1】:
模板特化
template<>
void Class<bool>::method1()
/* Specialized job for bool here */
// Declare that the class is specialized for bool
template class Class<bool>;
仅在 Class.cpp 中可见。如果 Class<bool>
在您的代码中的其他任何地方使用,则这些特化在那里不可见。因此,泛型类模板用于实例化Class<bool>
。
如果您希望使用 Class<bool>
的所有文件都可以看到特化,请将它们移至 Class.h。到那时,Class.cpp 将不再是必需的,除非它具有上述行以外的代码。
【讨论】:
“将它们移至 Class.h。此时,不再需要 Class.cpp。” - 或者,您可以仅将声明移至.h,出于同样的原因,可能需要 .cpp 对于非模板类(即标头中的代码/依赖项较少,客户端只需要重新链接而不是重新编译)来获取更改的专业化行为。 ..). 谢谢!我在标题中添加了一个声明,现在可以从外界看到这些方法。该定义仍在源文件中,因此不会多次出现,也不会产生编译错误。【参考方案2】:您需要使用外部模板才能使专业化有效。
在您的 cpp 中,您拥有专业化和这一行:
template struct MyClass<bool>;
然后添加到表头:
extern template struct MyClass<bool>;
现在编译器将被告知不要实例化模板,而是在你的 cpp 中选择实例化的模板。
【讨论】:
以上是关于无法强制实例化专用模板的主要内容,如果未能解决你的问题,请参考以下文章