如何防止特定模板的隐式模板实例化?

Posted

技术标签:

【中文标题】如何防止特定模板的隐式模板实例化?【英文标题】:How do I prevent implicit template instantiations for a specific template? 【发布时间】:2015-05-27 03:20:37 【问题描述】:

我想阻止特定模板类的所有隐式模板实例化,以防止它被实例化到每个翻译单元中。

看来我的选择是:

    在 gcc 的命令行上使用 -fno-implicit-templates。这 抑制所有隐式模板实例化,这不是我想要的。我只想为单个模板阻止它。 使用 C++11“外部模板”。但这只会抑制特定的 显式实例化。我不想输入“外部 每个潜在模板参数的模板”行列出此 模板可能会被实例化。

所以我需要一些介于两者之间的东西。最好有:

 extern template class Foo; // suppress all implicit instantiations of Foo

(注意缺少模板参数。)有什么想法吗?

【问题讨论】:

用例是什么?您是想完全阻止使用某些实例化,还是只是想节省一些目标文件空间和链接时间? 我正在努力节省编译时间。在这种情况下,它有很大的不同。尽管我偶尔可以梳理反汇编以找到任何需要显式外部实例化的新实例,但我更希望链接器在任何新的新隐式实例上出错,以便它们可以立即添加到显式列表中进行因果修改的人的实例化。 您可以像拆分非模板一样在头文件和源文件之间拆分模板定义。然后,除非您为源文件中允许的类型集显式实例化模板,否则链接将失败。 是的,我知道我遗漏了一些明显的东西。谢谢。另外,如果我需要将显式实例化分布到多个源文件中,我可以将模板实现细节放入一个 .tcc 文件中,该文件会包含在这些源文件中,类似于 gcc 标头的结构方式。 【参考方案1】:

您可以使用std::enable_if,它与std::is_same 的组合正是如此:

template <class T , typename = std::enable_if <!std::is_same<T,Foo>::value,T>::type >
class MyClass
//...
;

现在 myClass 不会为 Foo 类型编译。

【讨论】:

【参考方案2】:

我会说您的问题的答案是使用 C++ 新类型特征来断言构造函数中的实例化:

static_assert(std::is_same<TInstantiation, [your-predefined-type]> || std::is_same<TInstantiation, [your-predefined-type2]> /*And so on...*/, "Classname can not be instantiated using this type!");

这一切都保证在编译时解决:)

【讨论】:

【参考方案3】:

您可以像使用非模板类一样拆分类。只需将声明放入标头并将其包含在任何地方,然后将实现放入 .inl/.i 文件并仅将其包含在您希望模板实例化的位置。或者,使用编译时开关对单个文件执行此操作 - 但您必须将声明和实现分开。

【讨论】:

以上是关于如何防止特定模板的隐式模板实例化?的主要内容,如果未能解决你的问题,请参考以下文章

未定义模板的隐式实例化“std::__1::basic_istringstream<char, std::__1::char_traits<char>, std::__1::allo

MSVC:显式模板实例化失败,而隐式实例化成功

MSVC:隐式模板实例化,但未使用模板构造函数

使用Metal API与Imageblocks模板“隐式实例化”错误

C++初识模板

”更高级的宏“模板到底是怎么实例化的?