2016-10-02 7 views
5

私は本を読んでいます.C++の特徴を説明しています.C++のtype_traitsヘッダーの例は、奇妙な?:の使用例です。ここに対応する/ usr/include/C++/...ファイル:strange operator?:decltypeの使用法:

template<typename _Tp, typename _Up> 
    static __success_type<typename decay<decltype 
         (true ? std::declval<_Tp>() 
         : std::declval<_Up>())>::type> _S_test(int); 

が与えられた宣言の目的はさておき、?:オペレータの使用量は、このコードで私を困惑します。最初のオペランドがtrueの場合、評価の結果として常にstd::declval<_Tp>()が選択されます。 そのオペランドの選択は実際にどのように機能しますか?

編集:もともとNicolai M. Josuttisの「The C++標準ライブラリ:チュートリアルとリファレンス、第2版」、p.125を読んでください。しかし、GCCヘッダファイルに比べてやや簡略化した形で与えられています。

+1

書籍btwについて教えてください。 – manatttta

+0

ここで重要なのは、式の型であり、どの部分が評価されるかではありません。 – Mat

+0

マットは言った。この式は、三項条件演算子型減算メカニズムを使用するために使用されます([ここ](http://en.cppreference.com/w/cpp/language/operator_other)参照)。 – StoryTeller

答えて

9

true ? std::declval<_Tp>() : std::declval<_Up>()では、最初の選択肢が常に選択されますが、式全体が有効な式でなければなりません。したがって、std::declval<_Up>()は有効でなければならず、つまり、_Upはゼロ引数を受け入れる呼び出し可能でなければなりません。それ以外には、_Tp()_Up()は同じ型を返す必要があります(または型の1つを暗黙的に別の型に変換する必要があります)。そうでなければ、3進イテレータは戻り値を選択できません。

この手法はSFINAEと呼ばれています(置換エラーはエラーではありません)。テンプレートのインスタンス化が失敗した場合、それはエラーではなく、このテンプレートは無視され、コンパイラーは別のテンプレートを検索します。

+1

暗黙的な変換シーケンスが利用可能である限り、それらは正確に同じ型を返す必要はありません。 – StoryTeller

+0

@StoryTeller、ありがとう、私は答えを修正しました。 –

3

ここでの考え方は、?:では、第2および第3オペランドが同じ型であるか、または一方が他方に変換可能であることが必要であるということです。

それ以外の場合、関数のインスタンス化は失敗し、その他のオーバーロードが選択されます。