将内联关键字与模板一起使用是否有意义?

doc*_*doc 110 c++ templates inline

由于模板是在头文件中定义的,编译器能够确定内联函数是否有利,它是否有意义?我听说现代编译器更好地知道何时内联函数并忽略inline提示.


编辑:我想接受这两个答案,但这是不可能的.为了解决这个问题,我接受了菲涅耳的回答,因为它收到了大多数选票并且他是正式的,但正如我在评论中所提到的,我从不同的角度考虑Puppy组件10的答案也是正确的. .

问题出在C++语义中,在inline关键字和内联的情况下并不严格.Phresnel说"如果你的意思是写内联",但实际意义inline并不明确,因为它从原来的意义演变为"阻止编译人员讨论ODR违规"的指令,正如Puppy所说.

Seb*_*ach 93

这不是无关紧要的.不,不是每个功能模板都是inline默认的.该标准在显式专业化([temp.expl.spec])中甚至是明确的

有以下内容:

a.cc

#include "tpl.h"
Run Code Online (Sandbox Code Playgroud)

b.cc

#include "tpl.h"
Run Code Online (Sandbox Code Playgroud)

tpl.h(取自显式专业化):

#ifndef TPL_H
#define TPL_H
template<class T> void f(T) {}
template<class T> inline T g(T) {}

template<> inline void f<>(int) {} // OK: inline
template<> int g<>(int) {} // error: not inline
#endif
Run Code Online (Sandbox Code Playgroud)

编译这个,等等:

g++ a.cc b.cc
/tmp/ccfWLeDX.o: In function `int g<int>(int)':
inlinexx2.cc:(.text+0x0): multiple definition of `int g<int>(int)'
/tmp/ccUa4K20.o:inlinexx.cc:(.text+0x0): first defined here
collect2: ld returned 1 exit status
Run Code Online (Sandbox Code Playgroud)

inline在进行显式实例化时不说明也可能导致问题.

总而言之:对于非完全专业化的功能模板,即带有至少一种未知类型的功能模板,您可以省略inline,而不是接收错误,但实际上它们不是inline.对于完全专业化,即仅使用已知类型的专业化,您不能省略它.

建议的经验法则:inline如果你的意思是写,只是保持一致.它会让你更少考虑是否因为你可以.(这个经验法则符合Vandevoorde的/ Josuttis的C++模板:完整指南).

  • 显式专业化不是模板. (37认同)
  • 这个答案是不正确的.模板的显式特化是函数,而不是模板.该函数不会成为"内联",因为专用的模板标有`inline`.因此,模板上的"内联"完全无关紧要.该函数是否应该是"inline"与它通过模板特化生成无关(并且有更好的答案可以解决何时使用`inline`).@Puppy的回答如下是正确的,这个不是.在模板上添加"inline"是无关紧要的,`clang-tidy`实际上会删除它. (5认同)
  • 此外,该示例仅显示正常功能的ODR问题(与模板无关的行为).为了尝试显示`inline`不相关,该示例应该涵盖明确专门化`template <> void f <>(int){}`_without_`inline`关键字的情况.但即便如此,更改模板上的`inline`说明符也没有任何区别,因为你是否标记模板`inline`是无关紧要的. (3认同)
  • 一个人可以写,真的.但这并不意味着内联,即使它看起来像那样.Vandevoorde和Josuttis也在_C++模板中说明了这一点:完整的指南_ (2认同)
  • @DeadMG:在查找时,普通函数优于完全特化,因此如果它们不是模板,也不是非模板,那么它们是什么? (2认同)

Pup*_*ppy 29

这是无关紧要的.所有模板都已经inline- 更不用说从2012年开始,inline关键字的唯一用途就是阻止编译器对ODR违规行为提出质疑.你是绝对正确的 - 你当前的编译器将知道它自己内嵌的内容,甚至可以在翻译单元之间这样做.

  • @phresnel:但是模板与`inline`标记的函数具有相同的语义(也就是说,可以将多个等效定义传递给链接器,它将选择一个).那不是内联,是`inline`关键字的真正功能. (15认同)
  • 该标准未声明所有模板都是内联的. (10认同)
  • 你对明确的专业化不是一个模板的接受答案的评论(在被告知之后很明显*,当然......)也许是这个页面上最有用的东西.你还介意把它添加到你的答案中吗? (5认同)
  • @DeadMG:C++中没有要求必须在头文件中实现函数模板; 它可以在任何地方实施.为了反映这一点,我倾向于建议标记`inline`应该是内联的.它通常没有区别,但在标准中,它们并不相同,并且它们不是全部内联的.我接受你的立场说"这是无关紧要的",但根据标准,并非所有模板都是内联的,只有你作为C++ - 用户看起来好像. (3认同)
  • @BenVoigt:我知道inline的ODR含义。也许是我下面(或上面,取决于选择的排序)的答案。对于非专业模板,您当然是正确的,但是从形式上来说并不相同。 (2认同)

Com*_* 10 6

正如您所建议的,inline是对编译器的提示,仅此而已。它可以选择忽略它,或者实际上是内联未标记为内联的函数。

使用inline与曾经是变圆了这个问题,每个编译单元将创建一个单独的对象为同一模板类的(差)的方式模板,然后会导致在链接时重复的问题。通过使用inline(我认为)名称修改可以解决链接时的名称冲突问题,但代价是大大膨胀的代码。  

Marshall Cline在这里解释得比我好。

  • @Xeo:你能指出标准中指出函数模板总是内联的部分吗?因为,他们不是。 (2认同)