The trick is to create a helper type that tells you if something is a C<Foo>
or not:
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;
};
You were on the right track with enable_if
but is_same
seems to be a dead end:
#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
};
Which you can test easily now:
#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;
}
You can easily change that if you want your specialisation to work only with one of the parameters to be a C
or whatever you like.