1 //----------------------------------------------------------------------------- 2 // boost variant/detail/initializer.hpp header file 3 // See http://www.boost.org for updates, documentation, and revision history. 4 //----------------------------------------------------------------------------- 5 // 6 // Copyright (c) 2002-2003 7 // Eric Friedman, Itay Maman 8 // 9 // Distributed under the Boost Software License, Version 1.0. (See 10 // accompanying file LICENSE_1_0.txt or copy at 11 // http://www.boost.org/LICENSE_1_0.txt) 12 13 #ifndef BOOST_VARIANT_DETAIL_INITIALIZER_HPP 14 #define BOOST_VARIANT_DETAIL_INITIALIZER_HPP 15 16 #include <new> // for placement new 17 18 #include <boost/config.hpp> 19 20 #include <boost/call_traits.hpp> 21 #include <boost/detail/reference_content.hpp> 22 #include <boost/variant/recursive_wrapper_fwd.hpp> 23 #include <boost/variant/detail/move.hpp> 24 25 #if !defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE) 26 # include <boost/mpl/aux_/value_wknd.hpp> 27 # include <boost/mpl/int.hpp> 28 # include <boost/mpl/iter_fold.hpp> 29 # include <boost/mpl/next.hpp> 30 # include <boost/mpl/deref.hpp> 31 # include <boost/mpl/pair.hpp> 32 # include <boost/mpl/protect.hpp> 33 #else 34 # include <boost/variant/variant_fwd.hpp> 35 # include <boost/preprocessor/cat.hpp> 36 # include <boost/preprocessor/enum.hpp> 37 # include <boost/preprocessor/repeat.hpp> 38 #endif 39 40 namespace boost { 41 namespace detail { namespace variant { 42 43 /////////////////////////////////////////////////////////////////////////////// 44 // (detail) support to simulate standard overload resolution rules 45 // 46 // The below initializers allows variant to follow standard overload 47 // resolution rules over the specified set of bounded types. 48 // 49 // On compilers where using declarations in class templates can correctly 50 // avoid name hiding, use an optimal solution based on the variant's typelist. 51 // 52 // Otherwise, use a preprocessor workaround based on knowledge of the fixed 53 // size of the variant's psuedo-variadic template parameter list. 54 // 55 56 #if !defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE) 57 58 // (detail) quoted metafunction make_initializer_node 59 // 60 // Exposes a pair whose first type is a node in the initializer hierarchy. 61 // 62 struct make_initializer_node 63 { 64 template <typename BaseIndexPair, typename Iterator> 65 struct apply 66 { 67 private: // helpers, for metafunction result (below) 68 69 typedef typename BaseIndexPair::first 70 base; 71 typedef typename BaseIndexPair::second 72 index; 73 74 class initializer_node 75 : public base 76 { 77 private: // helpers, for static functions (below) 78 79 typedef typename mpl::deref<Iterator>::type 80 recursive_enabled_T; 81 typedef typename unwrap_recursive<recursive_enabled_T>::type 82 public_T; 83 84 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES 85 typedef boost::is_reference<public_T> 86 is_reference_content_t; 87 88 typedef typename boost::mpl::if_<is_reference_content_t, public_T, const public_T& >::type 89 param_T; 90 91 template <class T> struct disable_overload{}; 92 93 typedef typename boost::mpl::if_<is_reference_content_t, disable_overload<public_T>, public_T&& >::type 94 param2_T; 95 #else 96 typedef typename call_traits<public_T>::param_type 97 param_T; 98 #endif 99 100 public: // static functions 101 102 using base::initialize; 103 initialize(void * dest,param_T operand)104 static int initialize(void* dest, param_T operand) 105 { 106 typedef typename boost::detail::make_reference_content< 107 recursive_enabled_T 108 >::type internal_T; 109 110 new(dest) internal_T(operand); 111 return BOOST_MPL_AUX_VALUE_WKND(index)::value; // which 112 } 113 114 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES initialize(void * dest,param2_T operand)115 static int initialize(void* dest, param2_T operand) 116 { 117 // This assert must newer trigger, because all the reference contents are 118 // handled by the initilize(void* dest, param_T operand) function above 119 BOOST_ASSERT(!is_reference_content_t::value); 120 121 typedef typename boost::mpl::if_<is_reference_content_t, param2_T, recursive_enabled_T>::type value_T; 122 new(dest) value_T( boost::detail::variant::move(operand) ); 123 return BOOST_MPL_AUX_VALUE_WKND(index)::value; // which 124 } 125 #endif 126 }; 127 128 friend class initializer_node; 129 130 public: // metafunction result 131 132 typedef mpl::pair< 133 initializer_node 134 , typename mpl::next< index >::type 135 > type; 136 137 }; 138 }; 139 140 // (detail) class initializer_root 141 // 142 // Every level of the initializer hierarchy must expose the name 143 // "initialize," so initializer_root provides a dummy function: 144 // 145 class initializer_root 146 { 147 public: // static functions 148 149 static void initialize(); 150 151 }; 152 153 #else // defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE) 154 155 // Obsolete. Remove. 156 #define BOOST_VARIANT_AUX_PP_INITIALIZER_TEMPLATE_PARAMS \ 157 BOOST_VARIANT_ENUM_PARAMS(typename recursive_enabled_T) \ 158 /**/ 159 160 // Obsolete. Remove. 161 #define BOOST_VARIANT_AUX_PP_INITIALIZER_DEFINE_PARAM_T(N) \ 162 typedef typename unwrap_recursive< \ 163 BOOST_PP_CAT(recursive_enabled_T,N) \ 164 >::type BOOST_PP_CAT(public_T,N); \ 165 typedef typename call_traits< \ 166 BOOST_PP_CAT(public_T,N) \ 167 >::param_type BOOST_PP_CAT(param_T,N); \ 168 /**/ 169 170 template < BOOST_VARIANT_ENUM_PARAMS(typename recursive_enabled_T) > 171 struct preprocessor_list_initializer 172 { 173 public: // static functions 174 175 #define BOOST_VARIANT_AUX_PP_INITIALIZE_FUNCTION(z,N,_) \ 176 typedef typename unwrap_recursive< \ 177 BOOST_PP_CAT(recursive_enabled_T,N) \ 178 >::type BOOST_PP_CAT(public_T,N); \ 179 typedef typename call_traits< \ 180 BOOST_PP_CAT(public_T,N) \ 181 >::param_type BOOST_PP_CAT(param_T,N); \ 182 static int initialize( \ 183 void* dest \ 184 , BOOST_PP_CAT(param_T,N) operand \ 185 ) \ 186 { \ 187 typedef typename boost::detail::make_reference_content< \ 188 BOOST_PP_CAT(recursive_enabled_T,N) \ 189 >::type internal_T; \ 190 \ 191 new(dest) internal_T(operand); \ 192 return (N); /*which*/ \ 193 } \ 194 /**/ 195 196 BOOST_PP_REPEAT( 197 BOOST_VARIANT_LIMIT_TYPES 198 , BOOST_VARIANT_AUX_PP_INITIALIZE_FUNCTION 199 , _ 200 ) 201 202 #undef BOOST_VARIANT_AUX_PP_INITIALIZE_FUNCTION 203 204 }; 205 206 #endif // BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE workaround 207 208 }} // namespace detail::variant 209 } // namespace boost 210 211 /////////////////////////////////////////////////////////////////////////////// 212 // macro BOOST_VARIANT_AUX_INITIALIZER_T 213 // 214 // Given both the variant's typelist and a basename for forming the list of 215 // bounded types (i.e., T becomes T1, T2, etc.), exposes the initializer 216 // most appropriate to the current compiler. 217 // 218 219 #if !defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE) 220 221 #define BOOST_VARIANT_AUX_INITIALIZER_T( mpl_seq, typename_base ) \ 222 ::boost::mpl::iter_fold< \ 223 mpl_seq \ 224 , ::boost::mpl::pair< \ 225 ::boost::detail::variant::initializer_root \ 226 , ::boost::mpl::int_<0> \ 227 > \ 228 , ::boost::mpl::protect< \ 229 ::boost::detail::variant::make_initializer_node \ 230 > \ 231 >::type::first \ 232 /**/ 233 234 #else // defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE) 235 236 // Obsolete. Remove. 237 #define BOOST_VARIANT_AUX_PP_INITIALIZER_TEMPLATE_ARGS(typename_base) \ 238 BOOST_VARIANT_ENUM_PARAMS(typename_base) \ 239 /**/ 240 241 #define BOOST_VARIANT_AUX_INITIALIZER_T( mpl_seq, typename_base ) \ 242 ::boost::detail::variant::preprocessor_list_initializer< \ 243 BOOST_VARIANT_ENUM_PARAMS(typename_base) \ 244 > \ 245 /**/ 246 247 #endif // BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE workaround 248 249 #endif // BOOST_VARIANT_DETAIL_INITIALIZER_HPP 250