#include <iostream>
#include <typeinfo>

struct D {}; // default type

template< typename T0, typename T1, typename T2, typename T3,
          typename T4, typename T5, typename T6, typename T7 >
struct common_type
{
  static D* x( D*, D* );
  template< typename T > static T* x( D*, T* );
  template< typename T > static T* x( T*, D* );
  template< typename T > static T* x( T*, T* );

  typedef __typeof__( x( x( x( (T0*)0, (T1*)0 ),
                            x( (T2*)0, (T3*)0 ) ),
                         x( x( (T4*)0, (T5*)0 ),
                            x( (T6*)0, (T7*)0 ) ) ) ) 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;
}
