2016-04-14 12 views
1

私はかなりコードを理解していませんが、テンプレートの2つのパラメータがあります。第2のパラメータはclass = xxxxです。これは私には奇妙に思えます。どうすればいいのですか? std::enable_ifの他に、このC++の他のユースケースがありますか機能クラスのデフォルト値を持つテンプレートパラメータ

template < class T, 
class = typename std::enable_if<std::is_integral<T>::value>::type> 
bool is_even (T i) {return !bool(i%2);} 
+0

デフォルトのテンプレートパラメータで、名前はありません。主な「その他のユースケース」はコンストラクタテンプレートにあります。コンストラクタには戻り値の型がないからです。 –

答えて

2

1語:SFINAE。

代替エラーはエラーではありません。

グーグルでその言葉を探して、まったく新しい世界があなたのために開きます。

あなたのコードの意味を見てみましょう。

std::is_integral<typename T>::value 

Tは、そうでない場合は、整数型、falseある場合は値trueを持つタイプTから依存ブール値、です。

std::enable_if<bool B, typename T = void>::type 

それはタイプTB == true、そうでない場合は何もないのです。だから、

、あなたのコード内

template < class T, 
class = typename std::enable_if<std::is_integral<T>::value>::type> 

Tが整数型であるとき、第二(無名の)テンプレート引数は、タイプ(デフォルトで置換されている:void;しかし、この場合では、正確な型無関係です)、機能が有効になります。逆に、Tが整数型でない場合、2番目のテンプレート引数の置換に失敗し、このバージョンのis_even()関数はアクティブ化されていません(タイプT)。これが重要な点です。エラーではありません(is_even()の別のバージョンを有効にすることができます)。

is_even()の代替バージョンを実装する方法をもっと興味深く見ることができます。あなたはstd::is_integral

template < class T, 
class = typename std::enable_if<false == std::is_integral<T>::value>::type> 

を否定するが、これは動作しません別のバージョンを実装することができますことを考えることができますが、引数がポイントのテンプレートから(異なっ2つのis_even()テンプレート機能を持っているので、(エラーであり、コンパイルされません)ビューのデフォルトの引数のみ)。

ソリューションを使用すると、非整数型の積分型であり、第2版(そのリターンさえfalse)のために有効にis_even()のバージョンを持っている。このようにして、戻り値

#include <type_traits> 
#include <iostream> 

template <typename T> 
typename std::enable_if<true == std::is_integral<T>::value, bool>::type 
is_even (T const & i) 
{ return ! (i%2); } 

template <typename T> 
typename std::enable_if<false == std::is_integral<T>::value, bool>::type 
is_even (T const &) 
{ return false; } 


int main() 
{ 
    std::cout << "-- is 7 even ?  " << is_even(7) << '\n'; 
    std::cout << "-- is 8UL even ? " << is_even(8LL) << '\n'; 
    std::cout << "-- is \"abc\" even ? " << is_even("abc") << '\n'; 

    return 0; 
} 

にSFINAEを適用することができます。

p.s .:申し訳ありませんが、私の悪い英語です。

関連する問題