#include #include #include struct default_type { template operator T&() const ; }; struct A {}; struct B {}; struct C {}; struct D : C{}; template< int i, class T1, class T2, class T3, class T4, class T5 > class select_n; #define SELECT(i) \ template\ struct select_n {typedef T ## i type; }\ /**/ SELECT(1); SELECT(2); SELECT(3); SELECT(4); SELECT(5); typedef char true_[2]; typedef char false_[1]; static true_& match(...); // we need no stinking templates! static false_& match(default_type, ...); static false_& match(default_type, default_type); #define MATCH(a,b) (sizeof(true_) == sizeof(match(a, b))) template< class T1, class T2, class T3 = default_type, class T4 = default_type, class T5 = default_type > class common_type { static T1 & a1; static T2 & a2; static T3 & a3; static T4 & a4; static T5 & a5; // value ## max(n) will contain the index of the first type matching the common type. #define COMPUTE(i, j) \ enum {control ## i = !MATCH(a ## i, true?a1:true?a2:true?a3:true?a4:a5) && control ## j };\ enum {value ## i = control ## i ? value ## j + 1 : value ## j } \ enum { value0 = 1 }; enum { control0 = 1 }; COMPUTE(1,0); COMPUTE(2,1); COMPUTE(3,2); COMPUTE(4,3); COMPUTE(5,4); // boundary conditon: all types are default_type enum { index = value5 > 5 ? 5 : value5 }; typedef typename select_n::type type; }; template struct is_same { enum { value = 0 }; }; template struct is_same { enum { value = 1 }; }; int main() { BOOST_STATIC_ASSERT((is_same::type>::value)); BOOST_STATIC_ASSERT((is_same::type>::value)); BOOST_STATIC_ASSERT((is_same::type>::value)); BOOST_STATIC_ASSERT((is_same::type>::value)); BOOST_STATIC_ASSERT((is_same::type>::value)); //BOOST_STATIC_ASSERT((is_same::type>::value)); // error //BOOST_STATIC_ASSERT((is_same::type>::value)); // error BOOST_STATIC_ASSERT((is_same::type>::value)); // error }