#include #include struct default_type { template operator T() {} }; struct A {} ; struct B : A {}; struct C {}; template struct class_tag{}; template class_tag class_of(T) { return class_tag();}; // class_of wrapper not to evalute 'x' #define CLASS_OF(x) (true? default_type() : class_of(x) ) #define CHOSE2(a, b) (true? a() : b() ) #define CHOSE3(a, b, c) (true? a() : true? b() : c() ) #define CHOSE4(a, b, c, d) (true? a() : true? b() : true? c() : d() ) template void print(class_tag) { std::cout << typeid(T).name() << std::endl; } template struct int_to_type; template<> struct int_to_type<1> { typedef A type; }; template<> struct int_to_type<2> { typedef B type; }; template<> struct int_to_type<3> { typedef C type; }; template struct result { typedef char type_x[I]; typedef type_x & type; }; result<1>::type select(A); result<2>::type select(B); result<3>::type select(C); template struct is_same { enum { value = 0}; }; template struct is_same { enum { value = 1 }; }; int main() { print(CLASS_OF(CHOSE2(A, A))); print(CLASS_OF(CHOSE2(A, B))); print(CLASS_OF(CHOSE2(B, B))); print(CLASS_OF(CHOSE2(B, default_type))); print(CLASS_OF(CHOSE2(A, default_type))); print(CLASS_OF(CHOSE3(A, A, default_type))); print(CLASS_OF(CHOSE3(A, B, default_type))); print(CLASS_OF(CHOSE3(A, default_type, default_type))); //print(CLASS_OF(CHOSE2(A, C))); // fail assert((is_same::type>::value)); assert((is_same::type>::value)); assert((is_same::type>::value)); assert((is_same::type>::value)); assert((is_same::type>::value)); }