2017-01-10 9 views
2

以下のスニペットは、少なくとも私が考えた限り、専門化に適用されたSFINAEの可能な限り単純な例です。テンプレート:SFINAEの特殊化が適用されない

最後の行がメインポイントとなり、障害が発生しています。特殊化されたfooテンプレートの定義によって、barテンプレートの専門化が決まります。他のbar特殊化は他の場所で定義することもできますし、任意の型の使用をサポートしないままにすることもできます。

enable_ifと同じパターンが広く使用されていることがわかります。

template <typename T> 
struct foo; 

template <> 
struct foo<int> { 
    using type = int; 
}; 

template <typename T, typename use = void> 
struct bar; 

template <typename T> 
struct bar<T, typename foo<T>::type> { 
    using type = typename foo<T>::type; 
}; 

using good = typename foo<int>::type; 
using bad = typename bar<int>::type; 

g ++では、14または17標準で、結果を以下に示します。 barの特殊化は適用されておらず、コンパイラーは未定義(空の)定義を使用しているようです。どうして?

$ g++ --std=c++14 special.cpp -o special 
special.cpp:18:32: error: ‘type’ in ‘struct bar<int>’ does not name a type 
using bad = typename bar<int>::type; 
+1

'バー ::タイプ><==>バー' 'バー!=バー' – 0x499602D2

+0

あなたは 'バーをインスタンス化しています'。あなたはなぜコンパイラが "空の"定義以外の何かを使うことを期待していますか? "bar"の "空でない"特殊化は、 ''引数と遠隔で一致しません。 – AnT

答えて

4
template <typename T> 
struct bar<T, typename foo<T>::type> { 
    using type = typename foo<T>::type; 
}; 

常にvoidでなければなりませんuseとして

template <typename T> 
struct bar<T, std::void_t<typename foo<T>::type>> { 
    using type = typename foo<T>::type; 
}; 

でなければなりません。

だからこそ、AlwaysVoidという名前の方が良いでしょう。 (またはEnablerのようなものとしての役割を使用)

template <typename T, typename AlwaysVoid = void> 
struct bar; 
関連する問題