#include <iostream>
#include <typeinfo>

struct D {}; // default type

template< typename T0, typename T1, typename T2 >
struct common_type
{
  template< typename T > static T x( D*, D*, T* );
  template< typename T > static T x( D*, T*, D* );
  template< typename T > static T x( D*, T*, T* );
  template< typename T > static T x( T*, D*, D* );
  template< typename T > static T x( T*, D*, T* );
  template< typename T > static T x( T*, T*, D* );
  template< typename T > static T x( T*, T*, T* );

  typedef __typeof__( x( (T0*)0, (T1*)0, (T2*)0 ) ) type;
};

template<>
struct common_type< D, D, D >
{
  typedef D type;
};

int main()
{
  std::cout << typeid( common_type< D, D, D >::type ).name() << std::endl;
  std::cout << typeid( common_type< D, int, D >::type ).name() << std::endl;
  std::cout << typeid( common_type< bool, bool, bool >::type ).name() << std::endl;
  // std::cout << typeid( common_type< D, char, double >::type ).name() << std::endl;
}
