无法强制实例化专用模板

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&lt;bool&gt; 的对象时,它仍然使用 unspecialized 方法。

有什么问题?在.cpp文件末尾使用“模板”是否正确?

如果重要的话,我会在 Kubuntu/Raspbian 上使用 gcc 4.8/4.9,并且我使用 C++11。

【问题讨论】:

您至少需要在头文件中声明特化(实现仍然可以进入源文件,或者在头文件中,标记为inline)。否则,您的程序违反了 ODR,因此格式不正确,不需要诊断。 换句话说,客户端代码#include-ing Class.h 看不到任何东西可以证明实例化它自己的非专业模板版本。你必须通过向它展示声明来禁止它。 “声明该类专门用于 bool” - template class Class&lt;bool&gt;; 没有做任何此类事情。另外,不要使用保留名称作为包含守卫。 与主题无关,但我建议不要使用带有双下划线或前导下划线后跟大写字母的名称。它们是为实现而保留的,可能会导致未定义的行为(请参阅 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&lt;bool&gt; 在您的代码中的其他任何地方使用,则这些特化在那里不可见。因此,泛型类模板用于实例化Class&lt;bool&gt;

如果您希望使用 Class&lt;bool&gt; 的所有文件都可以看到特化,请将它们移至 Class.h。到那时,Class.cpp 将不再是必需的,除非它具有上述行以外的代码。

【讨论】:

“将它们移至 Class.h。此时,不再需要 Class.cpp。” - 或者,您可以仅将声明移至.h,出于同样的原因,可能需要 .cpp 对于非模板类(即标头中的代码/依赖项较少,客户端只需要重新链接而不是重新编译)来获取更改的专业化行为。 ..). 谢谢!我在标题中添加了一个声明,现在可以从外界看到这些方法。该定义仍在源文件中,因此不会多次出现,也不会产生编译错误。【参考方案2】:

您需要使用外部模板才能使专业化有效。

在您的 cpp 中,您拥有专业化和这一行:

template struct MyClass<bool>;

然后添加到表头:

extern template struct MyClass<bool>;

现在编译器将被告知不要实例化模板,而是在你的 cpp 中选择实例化的模板。

【讨论】:

以上是关于无法强制实例化专用模板的主要内容,如果未能解决你的问题,请参考以下文章

正确使用函数的显式模板实例化?

有没有办法避免警告/错误模板实例化回溯?

在标头之间调用时,模板实例化无法匹配重载流运算符的参数列表

无法实例化 MatchXpath

使用 gcc 强制实例化对象

显式实例化模板类的显式实例化模板方法