#include #include struct not_a_domain { static not_a_domain deduce(...); }; template struct domain : Domain { static Domain deduce(Domain*); using Domain::deduce; }; struct default_domain : domain<> {}; template <> struct domain : default_domain {}; template struct sized_type { char dummy[N]; }; sized_type<0> default_case(void*, void*); sized_type<1> default_case(default_domain*, void*); sized_type<2> default_case(void*, default_domain*); sized_type<3> default_case(default_domain*, default_domain*); template < class D0, class D1, int DefaultCase = sizeof(default_case((D0*)0, (D1*)0)) > struct deduce_common { typedef decltype(domain::deduce((D1*)0)) type; }; template struct deduce_common { typedef D1 type; }; template struct deduce_common { typedef D0 type; }; template <> struct deduce_common { typedef default_domain type; }; template struct deduce_common { typedef D0 type; }; template struct deduce_common { typedef D1 type; }; template struct deduce_domain3 { typedef typename deduce_common::type common0; typedef typename deduce_common::type type; }; struct D0 : domain<> { }; struct D1 : domain // a sub-domain of D0 { }; struct D2 : domain // a sub-domain of D0 { }; struct D3 : domain<> { }; struct DD0 : domain // a sub-domain of default_domain { }; struct DD1 : domain // a sub-domain of default_domain { }; struct DD2 : domain // a sub-domain of default_domain { }; struct DD3 : domain // a sub-domain of DD2 { }; int main() { using boost::is_same; BOOST_MPL_ASSERT((is_same::type, D0>)); BOOST_MPL_ASSERT((is_same::type, D0>)); BOOST_MPL_ASSERT((is_same::type, D0>)); BOOST_MPL_ASSERT((is_same::type, D0>)); BOOST_MPL_ASSERT((is_same::type, D0>)); BOOST_MPL_ASSERT((is_same::type, D0>)); BOOST_MPL_ASSERT((is_same::type, D0>)); BOOST_MPL_ASSERT((is_same::type, default_domain>)); BOOST_MPL_ASSERT((is_same::type, D0>)); BOOST_MPL_ASSERT((is_same::type, D0>)); BOOST_MPL_ASSERT((is_same::type, D0>)); BOOST_MPL_ASSERT((is_same::type, D0>)); BOOST_MPL_ASSERT((is_same::type, D0>)); BOOST_MPL_ASSERT((is_same::type, D0>)); BOOST_MPL_ASSERT((is_same::type, DD0>)); BOOST_MPL_ASSERT((is_same::type, DD0>)); BOOST_MPL_ASSERT((is_same::type, DD0>)); BOOST_MPL_ASSERT((is_same::type, DD0>)); BOOST_MPL_ASSERT((is_same::type, DD0>)); BOOST_MPL_ASSERT((is_same::type, DD0>)); BOOST_MPL_ASSERT((is_same::type, D0>)); BOOST_MPL_ASSERT((is_same::type, D0>)); BOOST_MPL_ASSERT((is_same::type, D0>)); BOOST_MPL_ASSERT((is_same::type, D0>)); BOOST_MPL_ASSERT((is_same::type, D0>)); BOOST_MPL_ASSERT((is_same::type, D0>)); BOOST_MPL_ASSERT((is_same::type, D1>)); // Very tricky to get right BOOST_MPL_ASSERT((is_same::type, D0>)); BOOST_MPL_ASSERT((is_same::type, D0>)); BOOST_MPL_ASSERT((is_same::type, D0>)); BOOST_MPL_ASSERT((is_same::type, D0>)); BOOST_MPL_ASSERT((is_same::type, D0>)); BOOST_MPL_ASSERT((is_same::type, D0>)); BOOST_MPL_ASSERT((is_same::type, D1>)); BOOST_MPL_ASSERT((is_same::type, not_a_domain>)); BOOST_MPL_ASSERT((is_same::type, not_a_domain>)); BOOST_MPL_ASSERT((is_same::type, not_a_domain>)); BOOST_MPL_ASSERT((is_same::type, not_a_domain>)); BOOST_MPL_ASSERT((is_same::type, not_a_domain>)); BOOST_MPL_ASSERT((is_same::type, not_a_domain>)); BOOST_MPL_ASSERT((is_same::type, not_a_domain>)); BOOST_MPL_ASSERT((is_same::type, not_a_domain>)); BOOST_MPL_ASSERT((is_same::type, not_a_domain>)); BOOST_MPL_ASSERT((is_same::type, not_a_domain>)); BOOST_MPL_ASSERT((is_same::type, not_a_domain>)); BOOST_MPL_ASSERT((is_same::type, not_a_domain>)); BOOST_MPL_ASSERT((is_same::type, not_a_domain>)); BOOST_MPL_ASSERT((is_same::type, not_a_domain>)); BOOST_MPL_ASSERT((is_same::type, not_a_domain>)); BOOST_MPL_ASSERT((is_same::type, DD2>)); BOOST_MPL_ASSERT((is_same::type, DD2>)); BOOST_MPL_ASSERT((is_same::type, DD2>)); // These should be ambiguous. BOOST_MPL_ASSERT((is_same::type, not_a_domain>)); BOOST_MPL_ASSERT((is_same::type, not_a_domain>)); BOOST_MPL_ASSERT((is_same::type, not_a_domain>)); }