内联模板函数?

43

如果它们包含在多个cpp文件中,那我是否需要使用inline模板函数呢?谢谢。

template<bool> inline QString GetText();
template<> inline QString GetText<true>() {return "true";}
template<> inline QString GetText<false>() {return "false";}

你希望从inline模板函数中获得什么? - Oswald
1
可能是Does it make any sense to use inline keyword with templates?的重复问题。 - Mark Garcia
4个回答

46

你需要这么做,因为它们是完整的功能专业化程序,因此与普通函数一样受到一个定义规则的约束。


4
对于模板和未完全专门化的情况,我可以删除 inline 关键字。这样可以吗?比如 template<bool> QString GetText(); - user1899020
5
可以的。 - user541686

28

是的,你需要在那里使用 inline 指定符。

ODR(一次定义规则)规定变量、函数、类、枚举或模板必须有且仅有一个定义。与您问题相关的异常列在 §3.2/5(C++11)中(强调我的):

程序中可以有多个类类型(第9条)、枚举类型(7.2)、具有外部链接的内联函数(7.1.2)、类模板(第14条)、非静态函数模板(14.5.6)、类模板的静态数据成员(14.5.1.3)、类模板的成员函数(14.5.1.1)或者未指定某些模板参数的模板特化(14.7、14.5.5),只要每个定义出现在不同的翻译单元中,并且提供的定义满足以下要求。[...]

在其中未列出明确指定了所有参数(即显式特化)的模板特化,§14.7.3/12说:

An explicit specialization of a function template is inline only if it is declared with the inline specifier or defined as deleted, and independently of whether its function template is inline. [ Example:

template<class T> void f(T) { /∗ ... ∗/ }
template<class T> inline T g(T) { /∗ ... ∗/ }
template<> inline void f<>(int) { /∗ ... ∗/ }  // OK: inline
template<> int g<>(int) { /∗ ... ∗/ }          // OK: not inline

— end example ]


在我的测试中,似乎 template<> int g<>(int) { /∗ ... ∗/ } 需要关键字 inline - user1899020
@user1899020 你真的读过这个答案吗?如果你将它包含在多个链接在一起的cpp文件中,那么是的,你需要使用inline。这就是例子(来自标准)所说的。 - jogojapan

1
没有理由在模板的完全特化中使用inline,但在第二和第三行需要添加inline关键字,第一行不需要。但是每个使用该模板的翻译单元都需要包含模板定义,因此最好的方法是将其包含在头文件中,并在其他使用它的cpp中包含它。
在C++标准n3376的3.2/6中,整个应用程序可以有多个类模板定义,只要定义相同即可。

===============

根据Jesse Good的评论更新答案(需要模板全特化内联)。感谢Jesse Good指出这一点。


1
你需要使用 inline 关键字。这些是模板的 特化,如果包含在多个源文件中将会违反 ODR。 - Jesse Good
2
请参见 [temp.expl.spec]/12,"函数模板的显式特化仅在使用内联说明符声明或定义为已删除时才是内联的,而不管其函数模板是否内联。" - Mankarse
@ZijingWu,您所提到的是C++14的草案。在当前的C++11中,相关章节为3.2/5。此外,如果您包含了完整的引用,您会注意到在该章节中(无论是C++11还是C++14),显式模板特化并未被提及为例外情况。 - jogojapan
@jogojapan 我没有注意到完全显式模板特化未包含在3.2/5的异常列表中。标准对待完全特化和模板函数不同,有什么原因吗?我认为应该有某些原因,但我无法想出来。 - ZijingWu
3
@ZijingWu 原因是完全(即明确)专门化的函数模板不再是模板。它们是函数,并且表现出与函数相同的行为。 (这也反映在您不需要为明确专门化的函数模板进行显式实例化。显式特化意味着实例化为函数。) - jogojapan

0

看起来模板方法必须在构建的同一文件中定义,您不需要使用“inline”关键字,因为它们已经在包含它的每个cpp文件中构建。


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