/////////////////////////////////////////////////////////////////////////////// /// \file deduce_domain.hpp /// Contains definition of deduce_domain\<\> class templates /// for finding the domain that is common among the specified /// domains // // Copyright 2010 Daniel Wallin, Eric Niebler. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // // Many thanks to Daniel Wallin who first implemented this code. Thanks // also to Jeremiah Willcock, John Bytheway and Krishna Achuthan who // offered alternate solutions to this tricky programming problem. #ifndef BOOST_PROTO_DEDUCE_DOMAIN_HPP_EAN_05_22_2010 #define BOOST_PROTO_DEDUCE_DOMAIN_HPP_EAN_05_22_2010 #include #include #include #include #include #include #include #include #include #include #include #ifndef BOOST_PROTO_ASSERT_VALID_DOMAIN # define BOOST_PROTO_ASSERT_VALID_DOMAIN(DOM) BOOST_MPL_ASSERT_NOT((boost::is_same)) #endif namespace boost { namespace proto { namespace detail { template struct sized_type { typedef char (&type)[N]; }; template struct domain_ : domain_ { typedef Domain type; typedef domain_ base; #ifdef BOOST_NO_DECLTYPE using base::deduce98; static int const index = base::index + 1; static typename sized_type::type deduce98(domain_*); #else using base::deduce0x; static Domain deduce0x(domain_*); #endif }; template<> struct domain_ { typedef not_a_domain type; #ifdef BOOST_NO_DECLTYPE static int const index = 1; static sized_type<1>::type deduce98(void*); #else static not_a_domain deduce0x(void*); #endif }; template<> struct domain_ : domain_ {}; sized_type<1>::type default_test(void*, void*); sized_type<2>::type default_test(domain_*, void*); sized_type<3>::type default_test(void*, domain_*); sized_type<4>::type default_test(domain_*, domain_*); #ifdef BOOST_NO_DECLTYPE template struct nth_domain : nth_domain {}; template struct nth_domain<0, Domain> : Domain {}; #endif template struct common_domain1 { typedef D0 type; }; template struct deduce_domain1 : domain_of {}; template< typename D0 , typename D1 , int DefaultCase = sizeof(proto::detail::default_test((domain_*)0, (domain_*)0)) > struct common_domain2 { #ifdef BOOST_NO_DECLTYPE static int const index = domain_::index - sizeof(domain_::deduce98((domain_*)0)); typedef typename nth_domain >::type type; #else typedef decltype(domain_::deduce0x((domain_*)0)) type; #endif }; template struct common_domain2 { typedef D1 type; }; template struct common_domain2 { typedef D0 type; }; template struct common_domain2 { typedef D0 type; }; template struct common_domain2 { typedef D1 type; }; template<> struct common_domain2 { typedef default_domain type; }; template struct deduce_domain2 : common_domain2< typename domain_of::type , typename domain_of::type > {}; #define M0(Z, N, DATA) \ typedef \ typename common_domain2::type \ BOOST_PP_CAT(common, BOOST_PP_INC(N)); \ /**/ #define BOOST_PP_LOCAL_MACRO(N) \ template \ struct BOOST_PP_CAT(common_domain, N) \ { \ typedef A0 common1; \ BOOST_PP_REPEAT_FROM_TO(1, N, M0, ~) \ typedef common ## N type; \ BOOST_PROTO_ASSERT_VALID_DOMAIN(type); \ }; \ \ template \ struct BOOST_PP_CAT(deduce_domain, N) \ : BOOST_PP_CAT(common_domain, N)< \ BOOST_PP_ENUM_BINARY_PARAMS( \ N \ , typename domain_of::type BOOST_PP_INTERCEPT \ ) \ > \ {}; \ /**/ #define BOOST_PP_LOCAL_LIMITS (3, BOOST_PROTO_MAX_ARITY) #include BOOST_PP_LOCAL_ITERATE() #undef M0 } } } #endif // BOOST_PROTO_DEDUCE_DOMAIN_HPP_EAN_05_22_2010