2016-04-14 14 views
1

以下のコードでは、引数{1,2}を持つインスタンスbのメンバ関数Fを呼び出すと、B::F(std::initializer_list<int>)がコンパイルされ、呼び出されます。しかし、私はブレース-INIT-リストから1つの要素を削除し、コンパイラがbegin(int)を探している、とないbegin(initializer_list<int>)1つの要素を持つbraced-init-listの型が要素自体の型に切り替わるのはなぜですか?

されている理由だけで、{1}、私はエラー

9 : error: no matching function for call to 'begin(int)' using type = decltype(std::begin(std::declval<T>()));

を取得し、私は理解していない使用している場合

私はこれをhttps://godbolt.org/g/tMyYQsでプレイしていますが、clangとg ++の両方で同じ種類のエラーが発生します。私は何が欠けていますか?

#include <type_traits> 
#include <iterator> 

template< bool B, class T = void > 
using enable_if_t = typename std::enable_if<B,T>::type; 

template <typename T> 
struct mytrait { 
    using type = decltype(std::begin(std::declval<T>())); 
    }; 

template <typename T> 
class A { 
    public: 
    template <typename TA, typename = 
    enable_if_t<std::is_same<T, typename mytrait<TA>::type>::value>> 
     A(TA &&){} 
}; 

class B 
{ 
    public: 
    void F(A<int>); 
    void F(std::initializer_list<int>); 
}; 

int main() 
{ 
    B b; 

    b.F({1,2}); // compiles fine 
#if 0 
    b.F({1});  // causes mytrait<int>::type to be examined, 
       // not mytrait<std::initializer_list<int>>::type 
#endif 
} 
+1

"均一な初期化"のため:-) –

答えて

1

申し訳ありませんが、私はそれを理解したと思います。コンパイラがb.F({1})を見ると、Fのどのオーバーロードが呼び出されるかが分かります。 A<int>を受け取るオーバーロードがあることがわかります。copy-list-initializationを経由して、を構築できるかどうかを確認しようとします。A<int>{1}を使用しています。リテラル1の型はintです。だから、TAはintと推測されます。 mytrait<int>decltype(std::begin(declval<int>()))を決定しようとしますが、int型のstd :: beginはありません。コンパイラのエラーです。

b.F({1,2})の場合、2つの入力を受け入れるコンストラクタがA<int>であるため、リストの初期化も試行されません。

私はmytrait <のint> ::タイプは代替失敗することにするSFINAEを使用しているように見えること

template <typename T, typename = decltype(std::begin(std::declval<T>()))> 
struct mytraits {...}; 

に私のmytraitsテンプレート宣言を変更することで、この問題を解決することができますように見えます。

関連する問題