#include <iostream>
#include <typeinfo>

struct D {}; // default type

template< typename, typename > struct common_type_helper;
template<> struct common_type_helper< D, D > { typedef D type; };
template< typename T > struct common_type_helper< D, T > { typedef T type; };
template< typename T > struct common_type_helper< T, D > { typedef T type; };
template< typename T > struct common_type_helper< T, T > { typedef T type; };

template< typename T0, typename T1, typename T2, typename T3,
          typename T4, typename T5, typename T6, typename T7 >
struct common_type
{
  typedef typename common_type_helper<
    typename common_type_helper<
      typename common_type_helper< T0, T1 >::type,
      typename common_type_helper< T2, T3 >::type >::type,
    typename common_type_helper<
      typename common_type_helper< T4, T5 >::type,
      typename common_type_helper< T6, T7 >::type >::type >::type type;
};

int main()
{
  std::cout << typeid( common_type< D, D, D, D, D, D, D, D >::type ).name() << std::endl;
  std::cout << typeid( common_type< D, int, D, D, D, D, int, D >::type ).name() << std::endl;
  std::cout << typeid( common_type< bool, bool, bool, bool, bool, bool, bool, bool >::type ).name() << std::endl;
  // std::cout << typeid( common_type< D, char, double, D, D, D, D, D >::type ).name() << std::endl;
}
