web-dev-qa-db-ja.com

テンプレートでインラインキーワードを使用するのは理にかなっていますか?

テンプレートはヘッダー内で定義され、コンパイラーは関数のインライン化が有利かどうかを判断できるため、意味がありますか?最近のコンパイラーは関数をインライン化するタイミングをよく知っており、inlineヒントを無視していると聞いています。


編集:両方の答えを受け入れたいのですが、これは不可能です。この問題を解決するため、私はphresnelの回答を受け入れています。ほとんどの票を獲得し、正式に正しいからです。しかし、コメントで述べたようにPuppyコンポーネント1の解答も、異なる観点から正しい解答として。

問題はC++のセマンティクスにあり、inlineキーワードとインライン化の場合は厳密ではありません。 phresnelは「あなたがそれを意味するならインラインで書く」と言うが、実際にinlineが意味するものは、元の意味から「ODRにむさぼるコンパイラを停止する」ディレクティブに進化したため明確ではない子犬のように違反します。

103
doc

関係ありません。いいえ、デフォルトではすべての関数テンプレートがinlineではありません。 Explicit specialization([temp.expl.spec])では、標準についても明示的です。

次のものを用意してください。

a.cc

#include "tpl.h"

b.cc

#include "tpl.h"

tpl.h(Explicit Specializationから取得):

#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

これをコンパイルします。

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

明示的なインスタンス化を行うときにinlineを指定しないことも問題につながる可能性があります。

したがって、要約では:完全に特殊化されていない関数テンプレート、つまり少なくとも1つの未知の型を保持するテンプレートの場合、inlineを省略できます。エラーを受信しませんが、それでもinlineではありません。完全な特殊化、つまり既知のタイプのみを使用する特殊化では、省略できません。

提案された経験則:意味があり、一貫性がある場合は、inlineと記述します。できるからといって、そうすべきかどうかについて考えることを少なくします。 (この経験則は Vandevoorde's/Josuttis'sC++ Template:The Complete Guide )に準拠しています。

87
Sebastian Mach

無関係です。すべてのテンプレートはすでにinline-です。2012年現在、inlineキーワードの唯一の使用は、コンパイラがODR違反について愚痴を言うのを止めることです。あなたは絶対に正しいです-あなたの現在の世代のコンパイラはそれ自身でインライン化するものを知っており、おそらく翻訳単位間でもそうすることができます。

27
Puppy

あなたが提案したように、inlineはコンパイラへのヒントであり、それ以上のものではありません。それを無視するか、実際、インラインとマークされていないインライン関数を選択することができます。

テンプレートでinlineを使用すると、各コンパイルユニットが同じテンプレートクラスに対して個別のオブジェクトを作成し、リンク時に重複の問題を引き起こすという問題を回避する(貧弱な)方法でした。 inline(と思う)を使用することで、名前のマングリングはリンク時に名前の衝突を回避しますが、コードが非常に肥大化します。

Marshall Cline ここで説明 私よりも良い。

1
Component 10