1 /////////////////////////////////////////////////////////////////////////////// 2 /// \file deduce_domain.hpp 3 /// Contains definition of deduce_domain\<\> class templates 4 /// for finding the domain that is common among the specified 5 /// domains 6 // 7 // Copyright 2010 Daniel Wallin, Eric Niebler. Distributed under the Boost 8 // Software License, Version 1.0. (See accompanying file 9 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 10 // 11 // Many thanks to Daniel Wallin who first implemented this code. Thanks 12 // also to Jeremiah Willcock, John Bytheway and Krishna Achuthan who 13 // offered alternate solutions to this tricky programming problem. 14 15 #ifndef BOOST_PROTO_DEDUCE_DOMAIN_HPP_EAN_05_22_2010 16 #define BOOST_PROTO_DEDUCE_DOMAIN_HPP_EAN_05_22_2010 17 18 #include <boost/config.hpp> 19 #include <boost/preprocessor/cat.hpp> 20 #include <boost/preprocessor/facilities/intercept.hpp> 21 #include <boost/preprocessor/iteration/local.hpp> 22 #include <boost/preprocessor/iteration/iterate.hpp> 23 #include <boost/preprocessor/repetition/enum_params.hpp> 24 #include <boost/preprocessor/repetition/enum_binary_params.hpp> 25 #include <boost/preprocessor/repetition/repeat_from_to.hpp> 26 #include <boost/preprocessor/arithmetic/inc.hpp> 27 #include <boost/mpl/assert.hpp> 28 #include <boost/type_traits/is_same.hpp> 29 #include <boost/proto/proto_fwd.hpp> 30 31 #ifndef BOOST_PROTO_ASSERT_VALID_DOMAIN 32 # define BOOST_PROTO_ASSERT_VALID_DOMAIN(DOM) BOOST_MPL_ASSERT_NOT((boost::is_same<DOM, boost::proto::detail::not_a_domain>)) 33 #endif 34 35 namespace boost 36 { 37 namespace proto 38 { 39 namespace detail 40 { 41 template<typename Domain> 42 struct domain_ 43 : domain_<typename Domain::proto_super_domain> 44 { 45 typedef Domain type; 46 typedef domain_<typename Domain::proto_super_domain> base; 47 #ifdef BOOST_NO_CXX11_DECLTYPE 48 using base::deduce98; 49 static int const index = base::index + 1; 50 static typename sized_type<index>::type deduce98(domain_<Domain>*); 51 #else 52 using base::deduce0x; 53 static Domain deduce0x(domain_<Domain>*); 54 #endif 55 }; 56 57 template<> 58 struct domain_<not_a_domain> 59 { 60 typedef not_a_domain type; 61 #ifdef BOOST_NO_CXX11_DECLTYPE 62 static int const index = 1; 63 static sized_type<1>::type deduce98(void*); 64 #else 65 static not_a_domain deduce0x(void*); 66 #endif 67 }; 68 69 template<> 70 struct domain_<default_domain> 71 : domain_<not_a_domain> 72 {}; 73 74 template<> 75 struct domain_<basic_default_domain> 76 : domain_<not_a_domain> 77 {}; 78 79 sized_type<1>::type default_test(void*, void*); 80 sized_type<2>::type default_test(domain_<default_domain>*, void*); 81 sized_type<2>::type default_test(domain_<basic_default_domain>*, void*); 82 sized_type<3>::type default_test(void*, domain_<default_domain>*); 83 sized_type<3>::type default_test(void*, domain_<basic_default_domain>*); 84 sized_type<4>::type default_test(domain_<default_domain>*, domain_<default_domain>*); 85 sized_type<4>::type default_test(domain_<basic_default_domain>*, domain_<default_domain>*); 86 sized_type<4>::type default_test(domain_<default_domain>*, domain_<basic_default_domain>*); 87 sized_type<4>::type default_test(domain_<basic_default_domain>*, domain_<basic_default_domain>*); 88 89 #ifdef BOOST_NO_CXX11_DECLTYPE 90 template<int N, typename Domain> 91 struct nth_domain 92 : nth_domain<N - 1, typename Domain::base> 93 {}; 94 95 template<typename Domain> 96 struct nth_domain<0, Domain> 97 : Domain 98 {}; 99 #endif 100 101 template<typename D0> 102 struct common_domain1 103 { 104 typedef D0 type; 105 }; 106 107 template<typename E0> 108 struct deduce_domain1 109 : domain_of<E0> 110 {}; 111 112 template< 113 typename D0 114 , typename D1 115 , int DefaultCase = sizeof(proto::detail::default_test((domain_<D0>*)0, (domain_<D1>*)0)) 116 > 117 struct common_domain2 118 { 119 #ifdef BOOST_NO_CXX11_DECLTYPE 120 static int const index = domain_<D0>::index - sizeof(domain_<D0>::deduce98((domain_<D1>*)0)); 121 typedef typename nth_domain<index, domain_<D0> >::type type; 122 #else 123 typedef decltype(domain_<D0>::deduce0x((domain_<D1>*)0)) type; 124 #endif 125 }; 126 127 template<typename D0, typename D1> 128 struct common_domain2<D0, D1, 2> 129 { 130 typedef D1 type; 131 }; 132 133 template<typename D0, typename D1> 134 struct common_domain2<D0, D1, 3> 135 { 136 typedef D0 type; 137 }; 138 139 template<typename D0> 140 struct common_domain2<D0, default_domain, 4> 141 { 142 typedef D0 type; 143 }; 144 145 template<typename D0> 146 struct common_domain2<D0, basic_default_domain, 4> 147 { 148 typedef D0 type; 149 }; 150 151 template<typename D1> 152 struct common_domain2<default_domain, D1, 4> 153 { 154 typedef D1 type; 155 }; 156 157 template<typename D1> 158 struct common_domain2<basic_default_domain, D1, 4> 159 { 160 typedef D1 type; 161 }; 162 163 template<> 164 struct common_domain2<default_domain, default_domain, 4> 165 { 166 typedef default_domain type; 167 }; 168 169 template<> 170 struct common_domain2<basic_default_domain, default_domain, 4> 171 { 172 typedef default_domain type; 173 }; 174 175 template<> 176 struct common_domain2<default_domain, basic_default_domain, 4> 177 { 178 typedef default_domain type; 179 }; 180 181 template<> 182 struct common_domain2<basic_default_domain, basic_default_domain, 4> 183 { 184 typedef basic_default_domain type; 185 }; 186 187 template<typename E0, typename E1> 188 struct deduce_domain2 189 : common_domain2< 190 typename domain_of<E0>::type 191 , typename domain_of<E1>::type 192 > 193 {}; 194 195 #include <boost/proto/detail/deduce_domain_n.hpp> 196 } 197 } 198 } 199 200 #endif // BOOST_PROTO_DEDUCE_DOMAIN_HPP_EAN_05_22_2010 201