2016-12-28 13 views
2
#include <vector> 
#include <list> 
#include <iostream> 

template 
< 
    typename T, 
    template<typename, typename = std::allocator<T>> class C, 
    typename = std::enable_if_t 
    < 
    std::is_same<std::vector<T>, C<T>>::value 
    > 
> 
void f(const C<T>& coll) 
{ 
    std::cout << "vector" << std::endl; 
} 

template 
< 
    typename T, 
    template<typename, typename = std::allocator<T>> class C, 
    typename = std::enable_if_t 
    < 
    std::is_same<std::list<T>, C<T>>::value 
    > 
> 
void f(const C<T>& coll) 
{ 
    std::cout << "list" << std::endl; 
} 

int main() 
{ 
     std::vector<int> c1{ 1, 2, 3 }; 
     std::list<int> c2{ 1, 2, 3 };  
     f(c1); 
     f(c2); 
} 

クラン3.8は文句:SFINAEがstd :: enable_if_tで動作しないのはなぜですか?

エラー:テンプレートパラメータがデフォルト引数を再定義:型名=のstd :: enable_if_t

は、コード内で何が悪いのでしょうか?

+0

代わりに、 'enable_if_t * = nullptr'のような非タイプのテンプレートパラメータを使用しようとしましたか? –

+0

私はそれを試みましたが、結果は同じです。 – xmllmx

+0

私はそれが非タイプのテンプレートパラメータで動作するはずだと思います。このコードは不正です –

答えて

1

なぜSFINAEが必要ですか?簡単な過負荷で十分です!

template <typename T> 
void f(const std::vector<T>& coll) 
{ 
    std::cout << "vector" << std::endl; 
} 

template < typename T> 
void f(const std::list<T>& coll) 
{ 
    std::cout << "list" << std::endl; 
} 

int main() 
{ 
    std::vector<int> c1{ 1, 2, 3 }; 
    std::list<int> c2{ 1, 2, 3 }; 
    f(c1); 
    f(c2); 
} 

そして、あなたは本当に(その場合には意味で)SFINAEを使用したい場合は、あなたとあなたの定義を修正することができます:

template 
< 
typename T, 
     template<typename, typename = std::allocator<T>> class C, 
     typename std::enable_if_t 
     < 
     std::is_same<std::list<T>, C<T>>::value 
     >* = nullptr 
    > 
void f(const C<T>& coll); 

そして、なぜあなたの定義は動作しませんでしたが、すでにここで見つけることができます: SFINAE working in return type but not as template parameter

+1

これは質問に答えません。なぜ動作しませんか?_ – skypjack

+0

@skypjack:これが修正されました。ありがとう!だから私はそれを重複としてもマークします。 – Klaus

2

デフォルトのテンプレートパラメータは、関数の一致には関与しません。それは、適切な機能を探すためにしようとしているとき、コンパイラの観点から
は、両方とも次のシグネチャがあります。そのための

template <typename T, template<typename, typename> class C, typename> 
void f(const C<T>& coll); 

を、fの2番目の定義は、実際に再定義です。

は、最小限の例を考えてみましょう:

template<typename = void> 
void f() {} 

template<typename = char> 
void f() {} 

// ... 

f<>(); 

は、どのように呼び出したいものをfコンパイラフィギュア出してもらえますか?
コードで多かれ少なかれ同じことが起こります。

enable_if_tを戻り値の型に移動すると、期待どおりに動作します。
この場合、置換はsfinae式から予期されるように、エラーのため2つの定義の1つを除外します。

+0

C++ 11ではデフォルトで非型のテンプレートパラメータを常に使用できるので、 'enable_if_t'を戻り値の型(コンストラクタ/変換演算子)に移動できるとは限りません。私はあなたの説明がとても好きです。+1 –

+1

@WFあなたの言ってる事がわかります。この場合、戻り値の型は実行可能な解決策であり、それが私がそれを言及した理由です。それで全部です。 ;-) – skypjack

関連する問題