最後の答えであなたを誤解させて申し訳ありませんが、私はそれがもっと簡単だろうと少しの間思いました。そこで、ここで完全なソリューションを提供しようと思います。このタイプの問題を解決するための一般的なアプローチは、トレイトenable_if
ヘルパーテンプレートを作成し、それを(C ++ 11、ブースト、または手動実装のいずれか)と一緒に使用して、クラスの特殊化を決定することです。
特性
単純なアプローチは、必ずしも最良ではありませんが、書くのは簡単です。
template <typename T>
struct has_nested_Vec {
typedef char yes;
typedef char (&no)[2];
template <typename U>
static yes test( typename U::Vec* p );
template <typename U>
static no test( ... );
static const bool value = sizeof( test<T>(0) ) == sizeof(yes);
};
アプローチは単純で、異なるサイズのタイプを返す2つのテンプレート関数を提供します。1つはネストされたVec
タイプを取り、もう1つは省略記号を取ります。ネストされたすべてのタイプの場合Vec
、最初のオーバーロードがより適切に一致します(省略記号は、どのタイプに対しても最悪の一致です)。Vec
ネストされたSFINAEがないタイプの場合、そのオーバーロードは破棄され、残っているオプションは省略記号のみになります。これで、どのタイプにもネストされたVec
タイプがあるかどうかを尋ねる特性ができました。
次の場合に有効にする
これはどのライブラリからでも使用できますが、独自のライブラリを使用することもできます。非常に簡単です。
template <bool state, typename T = void>
struct enable_if {};
template <typename T>
struct enable_if<true,T> {
typedef T type;
};
最初の引数がfalse
、の場合、ベーステンプレートが唯一のオプションであり、ネストされたものはありませんtype
。条件がの場合、true
SFINAEで使用できるenable_if
ネストされたものがあります。type
実装
次に、ネストされたタイプのみにSFINAEを使用するテンプレートと特殊化を提供する必要がありますVec
。
template<class T, class V = void>
struct Functor {
void operator()() const {
std::cerr << "general" << std::endl;
}
};
template<class T>
struct Functor<T, typename enable_if<has_nested_Vec<T>::value>::type > {
void operator()() const {
std::cerr << "special" << std::endl;
}
};
型を使用してインスタンス化するときは常にFunctor
、コンパイラーは特殊化を使用しようとします。これhas_nested_Vec
により、に渡される真理値がインスタンス化されて取得されenable_if
ます。値がであるタイプの場合false
、enable_if
ネストされたtype
タイプがないため、特殊化はSFINAEで破棄され、ベーステンプレートが使用されます。
あなたの特定のケース
タイプ全体を特殊化する必要はなく、演算子だけを特殊化する必要があると思われる特定のケースでは、3つの要素を1つの要素に混合できます。これはFunctor
、プレゼンスに基づいて2つの内部テンプレート関数の1つにディスパッチします。の必要性と特性クラスVec
を削除します。enable_if
template <typename T>
class Functor {
template <typename U>
void op_impl( typename U::Vec* p ) const {
std::cout << "specialized";
}
template <typename U>
void op_impl( ... ) const {
std::cout << "general";
}
public:
void operator()() const {
op_impl<T>(0);
}
};