显式模板实例化应该放在cpp文件还是头文件中?

27

显式模板实例化应放在cpp文件还是头文件中?

3个回答

23

假设你所说的“显式模板实例化”是指类似于以下的内容:

template class Foo<int>; // explicit type instantiation
// or
template void Foo<int>(); // explicit function instantiation

那么这些必须放在源文件中,因为它们被视为定义,因此受到ODR规则的约束。


不错的回答,但要挑剔一点:某些应该放在头文件中的模板定义仍然是技术上的定义。(关于所有定义具有相同内容和含义的ODR的“其他”部分也适用于它们。) - aschepler
3
但是,显式模板实例化不再是模板,并且不受到与模板相同的规则约束;相反,它们受到与普通类或函数定义相同的规则约束,这些规则(对于函数除外 inline)始终受到 ODR 的约束。 - ildjarn
对于大多数情况,如果这些内容必须放在源文件中。但是,在像FB的愚蠢库和有状态元编程等领域中,存在一个重要的格式良好的特殊情况。请参考此链接 - dfrib

17

我一直在cpp文件中完成这个。如果在头文件中这样做,至少会违反一个定义规则(one definition rule),特别是当该头文件被包含在多个cpp文件中时。(虽然有方法可以避免这种情况,在某些特定情况下非常有用)


1
如果您要声明一个类成员,该怎么办? - Jonathan Wood
1
在头文件中,它将违反一个定义规则,至少(通常情况下)当头文件被包含在多个cpp文件中时。对于大多数情况而言,是正确的,但是在像FB的folly库和有状态元编程这样的hack领域中,存在着一个重要的、良好形式的解决方法。 - dfrib
@dfrib:是的,我想这值得一提。已编辑。 - Jerry Coffin
@JerryCoffin 这次编辑没有达到目的:它不是关于将隐式实例化定义放置在未命名的命名空间中(这并没有什么区别,当包含在多个TU中时仍然会遇到ODR),而是要确保显式实例化定义定义了一个特化,其中至少有一个类型模板参数由同一头文件中未命名命名空间中定义的类型进行了特化:这样的类型在每个TU中都是唯一的,意味着被实例化的特化在每个TU中都是唯一的,我们可以避免违反ODR。 - dfrib
@dfrib:是的,我不想深入讨论某些事情,因为这通常只会分散大多数有可能阅读此内容的人的注意力。 - Jerry Coffin
@JerryCoffin 是的,那很合理,现在有了新的编辑和更少的细节,它不再是不准确的了。谢谢。 - dfrib

-3

任何一个都可以。

如果您要声明特定实例,可以在cpp文件中声明。但是,如果您要声明类成员或将从多个cpp文件引用的内容,则应将其放在头文件中。


1
没有解释的踩?这太糟糕了,伙计们。 - Jonathan Wood
4
可能是因为这是错误的吗?OP 询问显式实例化,而不是声明或 typedef。 - ildjarn
不是typedefs。但是,如果一个模板被声明为类成员,那么它的显式实例化在哪里? - Jonathan Wood
1
@Jonathan Wood:声明通常会放在头文件中,但显式实例化与任何非模板类或函数定义一样会放在源文件中。我不明白你的意思... - ildjarn
@ildjarn:如果它是一个类成员,那么你只能实例化这个类。类不能内联。算了吧。 - Jonathan Wood
1
@Jonathan Wood:作为成员函数模板的类成员可以被显式实例化。类不能是内联的,因此受到ODR的限制,这正是我的观点;那么,你的观点是什么? - ildjarn

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接