在模板中使用内联关键字是否有意义?

时间:2021-07-13 06:56:23

Since templates are defined within headers and compiler is able to determine if inlining a function is advantageous, does it make any sense? I've heard that modern compilers know better when to inline a function and are ignoring inline hint.

由于模板是在头文件中定义的,并且编译器能够确定内联函数是否有利,这有意义吗?我听说现代编译器更清楚何时内联函数,而忽略了内联提示。


edit: I would like to accept both answers, but this is not possible. To close the issue I am accepting phresnel's answer, because it received most votes and he is formally right, but as I mentioned in comments I consider Puppy's and Component 10's answers as correct ones too, from different point of view.

编辑:我愿意接受两个答案,但这是不可能的。为了结束这个问题,我接受菲斯内尔的答案,因为它得到了大多数的选票,而且他在形式上是正确的,但是正如我在评论中提到的,我认为帕皮和第十部分的答案也是正确的,从不同的角度来看。

The problem is in C++ semantics, which is not strict in case of inline keyword and inlining. phresnel says "write inline if you mean it", but what is actually meant by inline is not clear as it evolved from its original meaning to a directive that "stops compilers bitching about ODR violations" as Puppy says.

问题在于c++的语义,在内联关键字和内联的情况下不严格。phresnel说“如果您是指它,就写内联”,但是内联实际上是什么意思还不清楚,因为它从最初的含义演变成了一个指令,如Puppy所说的“停止编译器对ODR违规的抱怨”。

3 个解决方案

#1


69  

It is not irrelevant. And no, not every function template is inline by default. The standard is even explicit about it in Explicit specialization ([temp.expl.spec])

这不是无关紧要的。不,并不是每个函数模板都是内联的。在显式专门化([temp.expl.spec])中,标准甚至对其进行了明确的说明。

Have the following:

有以下:

a.cc

a.cc

#include "tpl.h"

b.cc

b.cc

#include "tpl.h"

tpl.h (taken from Explicit Specialization):

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

Compile this, et voila:

编译这个等瞧:

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

Not stating inline when doing explicit instantiation may also lead to issues.

在执行显式实例化时不声明内联也可能导致问题。

So in summary: For non fully specialized function templates, i.e. ones that carry at least one unknown type, you can omit inline, and not receive errors, but still they are not inline. For full specializations, i.e. ones that use only known types, you cannot omit it.

因此,总结:对于非完全专门化的函数模板,即至少携带一个未知类型的函数模板,您可以忽略内联,而不会接收错误,但它们仍然不是内联的。对于完全专门化,例如那些只使用已知类型的,您不能忽略它。

Proposed rule of thumb: Write inline if you mean it and just be consistent. It makes you think less about whether to or not to just because you can. (This rule of thumb is conforming to Vandevoorde's/Josuttis's C++ Template: The Complete Guide).

建议的经验法则:如果你的意思是内联的,那就写吧,保持一致。它让你更少地考虑是否仅仅因为你可以。(这条经验法则符合Vandevoorde /Josuttis的c++模板:完整指南)。

#2


21  

It's irrelevant. All templates are already inline- not to mention that as of 2012, the only use of the inline keyword is to stop compilers bitching about ODR violations. You are absolutely correct- your current-generation compiler will know what to inline on it's own and can probably do so even between translation units.

这是无关紧要的。所有模板都是内联的——更不用说,到2012年为止,内联关键字的唯一用途是停止编译器对ODR违规的抱怨。您是绝对正确的——您的当前生成编译器将知道自己内联的内容,甚至可以在翻译单元之间进行内联。

#3


0  

As you suggested, inline is a hint to the compiler and nothing more. It can choose to ignore it or, indeed, to inline functions not marked inline.

正如您所建议的,内联是对编译器的提示,仅此而已。它可以选择忽略它,也可以选择不标记为内联的内联函数。

Using inline with templates used to be a (poor) way of getting round the issue that each compilation unit would create a separate object for the same templated class which would then cause duplication issues at link time. By using inline (I think) the name mangling works out different which gets round the name * at link time but at the expense of vastly bloated code.  

使用内联与模板曾经是一种(糟糕的)解决问题的方法,即每个编译单元将为同一个模板类创建一个单独的对象,然后在链接时引起复制问题。通过使用内联(我认为),名称管理产生了不同的效果,在链接时避免了名称冲突,但代价是代码过于臃肿。 

Marshall Cline explains it here better than I can.

马歇尔·克莱因(Marshall Cline)在这里的解释比我更好。

#1


69  

It is not irrelevant. And no, not every function template is inline by default. The standard is even explicit about it in Explicit specialization ([temp.expl.spec])

这不是无关紧要的。不,并不是每个函数模板都是内联的。在显式专门化([temp.expl.spec])中,标准甚至对其进行了明确的说明。

Have the following:

有以下:

a.cc

a.cc

#include "tpl.h"

b.cc

b.cc

#include "tpl.h"

tpl.h (taken from Explicit Specialization):

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

Compile this, et voila:

编译这个等瞧:

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

Not stating inline when doing explicit instantiation may also lead to issues.

在执行显式实例化时不声明内联也可能导致问题。

So in summary: For non fully specialized function templates, i.e. ones that carry at least one unknown type, you can omit inline, and not receive errors, but still they are not inline. For full specializations, i.e. ones that use only known types, you cannot omit it.

因此,总结:对于非完全专门化的函数模板,即至少携带一个未知类型的函数模板,您可以忽略内联,而不会接收错误,但它们仍然不是内联的。对于完全专门化,例如那些只使用已知类型的,您不能忽略它。

Proposed rule of thumb: Write inline if you mean it and just be consistent. It makes you think less about whether to or not to just because you can. (This rule of thumb is conforming to Vandevoorde's/Josuttis's C++ Template: The Complete Guide).

建议的经验法则:如果你的意思是内联的,那就写吧,保持一致。它让你更少地考虑是否仅仅因为你可以。(这条经验法则符合Vandevoorde /Josuttis的c++模板:完整指南)。

#2


21  

It's irrelevant. All templates are already inline- not to mention that as of 2012, the only use of the inline keyword is to stop compilers bitching about ODR violations. You are absolutely correct- your current-generation compiler will know what to inline on it's own and can probably do so even between translation units.

这是无关紧要的。所有模板都是内联的——更不用说,到2012年为止,内联关键字的唯一用途是停止编译器对ODR违规的抱怨。您是绝对正确的——您的当前生成编译器将知道自己内联的内容,甚至可以在翻译单元之间进行内联。

#3


0  

As you suggested, inline is a hint to the compiler and nothing more. It can choose to ignore it or, indeed, to inline functions not marked inline.

正如您所建议的,内联是对编译器的提示,仅此而已。它可以选择忽略它,也可以选择不标记为内联的内联函数。

Using inline with templates used to be a (poor) way of getting round the issue that each compilation unit would create a separate object for the same templated class which would then cause duplication issues at link time. By using inline (I think) the name mangling works out different which gets round the name * at link time but at the expense of vastly bloated code.  

使用内联与模板曾经是一种(糟糕的)解决问题的方法,即每个编译单元将为同一个模板类创建一个单独的对象,然后在链接时引起复制问题。通过使用内联(我认为),名称管理产生了不同的效果,在链接时避免了名称冲突,但代价是代码过于臃肿。 

Marshall Cline explains it here better than I can.

马歇尔·克莱因(Marshall Cline)在这里的解释比我更好。