2013-10-28 13 views
54

これはちょうどanother questionという文脈の中で出てきました。「ODRを使用する」とは何を意味しますか?

明らかに、クラステンプレートのメンバー関数は、ODRが使用されている場合にのみインスタンス化されます。 誰かが正確に何を意味するのか説明できますか? wikipedia article on One Definition Rule (ODR)には「ODR-使用」は記載されていません。

標準は

名前が潜在的に評価された式 として表示されている変数として定義しかしながらODR-使用が定数式に現れる の要件を満たす目的でない限り (5.19)、左辺値と右辺値は 変換(4.1)が直ちに適用されます。 [basic.def.odr]の

編集:明らかにこれは間違った部分であり、段落全体にはさまざまな定義が含まれています。オーバーロードの解決ときで選択された場合、

名前が 潜在的に評価された式または候補 関数のセットのメンバーとして表示される非オーバーロードされた関数:これはクラステンプレートのメンバ関数に関連する1かもしれません純粋な 仮想関数で、その名前が明示的に修飾されていない場合は、 潜在的に評価される式から参照される、odr-usedです。

このルールは複数のコンパイル単位でどのように動作するのですか。クラステンプレートを明示的にインスタンス化すると、すべてのメンバー関数がインスタンス化されますか?

+1

[basic.def.odr]/6は、クラステンプレートのメンバー関数に適用されます。 "複数の定義があります[...]" – dyp

+2

* "すべてのメンバ関数がインスタンス化されていますか?クラステンプレートを明示的にインスタンス化するとどうなるでしょうか? "はい、[temp.explicit]/8 + 9を参照してください。 – dyp

答えて

48

これは標準で にエンティティの定義を指定する必要があるときに指定する(任意の宣言と反対の )という恣意的な定義です。この標準は、 コンテキストに応じて多様に解釈できるので、単に「 」とは言いません。 ODRを使用しているものは、実際には "use"に関連付けられているものと実際には対応していません。例えば、仮想 関数は、実際にはプログラム内のどこでも呼び出されていない場合でも、純粋でなければ常にODRが使用されます( )。

には の定義を完了するための参照が含まれていますが、完全な定義は§3.2の2番目の段落にあります。

テンプレートに関しては、ODRは質問の一部に過ぎません。 他の部分はインスタンス化です。特に、テンプレートがインスタンス化されるとき、§14.7は をカバーします。しかし、 §14.7.1(暗黙的なインスタンス化)のテキストはかなり長いですが、 の基本原則は、 が使用されている場合にのみテンプレートがインスタンス化されるということです。この文脈では、ODR-中古。したがって、 クラステンプレートのメンバー関数は、呼び出された場合、または仮想であり、クラス自体が である場合にのみインスタンス化されます( )。標準自体は、多くの の場所で、この上でカウント:std::list<>::sortは、個々の 要素に<を使用していますが、限り、あなたは にsortを呼び出さないよう、<をサポートしていない要素型 上のリストをインスタンス化することができますそれ。

+7

Upvoted:' std :: list <> :: sort'の例が気に入っています。 –

2

odr-usedは、その定義が存在する必要があるコンテキストで、何か(変数または関数)が使用されていることを意味します。

例えば、

struct F { 
    static const int g_x = 2; 
}; 

int g_x_plus_1 = F::g_x + 1; // in this context, only the value of g_x is needed. 
          // so it's OK without the definition of g_x 

vector<int> vi; 
vi.push_back(F::g_x);  // Error, this is odr-used, push_back(const int & t) expect 
          // a const lvalue, so it's definition must be present 

注意、MSVC 2013年に渡された上記一back、この動作は標準準拠ではない、GCC 4.8.2と打ち鳴らす3.8.0の両方が失敗し、エラーメッセージは次のとおりです。 未定義の参照[K :: g_x]

+0

C++で 'vi.push_back(F :: g_x);'のような静的データメンバをodr-useすることは可能ですか? –

+0

しかし、rvalueは 'const int&'に渡すこともできますか?静的constメンバーはrvalueとして扱われますか? – bigxiao

関連する問題