2013-07-24 11 views
11

私が知る限り、SFINAEは置換の失敗がコンパイルエラーにならず、起こりうるオーバーロードのリストからプロトタイプを削除するという意味です。私は理解していないことSFINAEの理解

:なぜこのSFINAEです:

template <bool C, typename T = void> struct enable_if{}; 
template <typename T> struct enable_if<true, T> { typedef T type; }; 

しかし、これではないでしょうか?

template <bool C> struct assert; 
template <> struct assert<true>{}; 

私の理解では、基本的なロジックはここでは同じです。この質問は、コメントからthis answerに出ました。 C++ 98では

+5

どちらコードなかでもSFINAEです。 – jrok

+0

SFINAEはコンパイル時エラーを引き起こさない(置換が失敗した場合)、静的なアサーション_is_の全目的がコンパイル時エラーを引き起こす(一部の条件が真ではない)のに対して、 –

+1

@ウィキペディアは 'enable_if'がSFINAEだと言っています、それは間違っていますか? – nijansen

答えて

12

、SFINAEは、ネストされたタイプtypeを取得するためには、戻り値の型または両方のケースでは、デフォルトのパラメータ

// SFINAE on return type for functions with fixed arguments (e.g. operator overloading) 
template<class T> 
typename std::enable_if< std::is_integral<T>::value, void>::type 
my_function(T const&); 

// SFINAE on dummy argument with default parameter for functions with no return type (e.g. constructors) 
template<class T> 
void my_function(T const&, std::enable_if< std::is_integral<T>::value, void>::type* = nullptr); 

と、関数の仮引数のいずれかでTのsubstutionに行われていますSFINAEの本質。 std::enable_ifとは対照的に、assertテンプレートのには、SFINAEの代替部分で使用できる入れ子タイプがありません。

詳細については、Jonathan Wakelyの優れたACCU 2013 presentationを参照してください。また、C++ 11の表現SFINAEも参照してください。 (コメントで@BartekBanachewiczで指摘したように)である関数テンプレートのデフォルト引数にSFINAEを使用することも可能になりました

// use C++11 default function arguments, no clutter in function's signature! 
template<class T, class dummy = typename std::enable_if< std::is_integral<T>::value, void>::type> 
void my_function(T const&); 
+0

また、テンプレート引数リストで行うこともできます。 –

+2

'enable_if' **は** SFINAEではありませんが、' typename enable_if :: type' **は** SFINAEです。なぜなら、テンプレートの置換に失敗してもエラーにならないからです一致)? – nijansen

+0

@nijansenが正しい! – TemplateRex