Хитрость заключается в создании вспомогательного типа, который сообщит вам, является ли что-то C<Foo>
или нет:
template <typename T> struct C {};
template <typename T> struct is_C {
static bool const value = false;
};
template <typename T> struct is_C<C<T>> {
static bool const value = true;
};
Вы были на правильном пути с enable_if
, но is_same
, кажется,тупик:
#include <type_traits>
template <typename T1, typename T2, typename Enabled = void> struct Trait {
static char const test = 'D'; // default
};
template <typename T> struct Trait<
T,
T,
typename std::enable_if<!is_C<T>::value >::type
> {
static char const test = 'N'; // non-C
};
template <typename T1, typename T2> struct Trait<
T1,
T2,
typename std::enable_if< is_C<T1>::value && is_C<T2>::value >::type
> {
static char const test = 'C'; // some C
};
который вы можете легко протестировать сейчас:
#include <iostream>
int main() {
Trait< C<int>, C<float> > foo1a;
Trait< C<int>, C<int> > foo1b;
Trait< int, int > foo2;
Trait< int, float > foo3;
std::cout << "Trait<C<int>,C<float>> : " << foo1a.test << std::endl; // prints 'C'
std::cout << "Trait<C<int>,C<int>> : " << foo1b.test << std::endl; // prints 'C'
std::cout << "Trait<int,int> : " << foo2.test << std::endl; // prints 'N'
std::cout << "Trait<int,float> : " << foo3.test << std::endl; // prints 'D'
return 0;
}
Вы можете легко изменить это, если хотите, чтобы ваша специализация работала только с одним из параметров какC
или что угодно.