1 // Copyright David Abrahams, Daniel Wallin 2003. 2 // Copyright Cromwell D. Enage 2018. 3 // Distributed under the Boost Software License, Version 1.0. 4 // (See accompanying file LICENSE_1_0.txt or copy at 5 // http://www.boost.org/LICENSE_1_0.txt) 6 7 #ifndef BOOST_PARAMETER_AUX_PACK_MAKE_ARG_LIST_HPP 8 #define BOOST_PARAMETER_AUX_PACK_MAKE_ARG_LIST_HPP 9 10 namespace boost { namespace parameter { namespace aux { 11 12 template < 13 typename List 14 , typename DeducedArgs 15 , typename TagFn 16 , typename IsPositional 17 , typename UsedArgs 18 , typename ArgumentPack 19 , typename Error 20 , typename EmitsErrors 21 > 22 struct make_arg_list_aux; 23 }}} // namespace boost::parameter::aux 24 25 #include <boost/parameter/aux_/arg_list.hpp> 26 #include <boost/parameter/aux_/void.hpp> 27 #include <boost/parameter/aux_/pack/unmatched_argument.hpp> 28 #include <boost/parameter/aux_/pack/tag_type.hpp> 29 #include <boost/parameter/aux_/pack/is_named_argument.hpp> 30 #include <boost/parameter/aux_/pack/insert_tagged.hpp> 31 #include <boost/parameter/aux_/pack/deduce_tag.hpp> 32 #include <boost/parameter/deduced.hpp> 33 #include <boost/parameter/config.hpp> 34 35 #if defined(BOOST_PARAMETER_CAN_USE_MP11) 36 #include <boost/mp11/integral.hpp> 37 #include <boost/mp11/list.hpp> 38 #include <boost/mp11/utility.hpp> 39 #include <type_traits> 40 #else 41 #include <boost/mpl/bool.hpp> 42 #include <boost/mpl/pair.hpp> 43 #include <boost/mpl/if.hpp> 44 #include <boost/mpl/eval_if.hpp> 45 #include <boost/mpl/apply_wrap.hpp> 46 #include <boost/mpl/identity.hpp> 47 #include <boost/type_traits/is_same.hpp> 48 #include <boost/type_traits/remove_const.hpp> 49 #include <boost/type_traits/remove_reference.hpp> 50 #endif 51 52 namespace boost { namespace parameter { namespace aux { 53 54 #if defined(BOOST_PARAMETER_CAN_USE_MP11) 55 template <typename ArgumentPack, typename TaggedArg, typename EmitsErrors> 56 struct append_to_make_arg_list 57 { 58 using type = ::boost::mp11::mp_push_front< 59 ArgumentPack 60 , ::boost::parameter::aux::flat_like_arg_tuple< 61 typename TaggedArg::key_type 62 , TaggedArg 63 , EmitsErrors 64 > 65 >; 66 }; 67 #endif 68 69 // Borland needs the insane extra-indirection workaround below so that 70 // it doesn't magically drop the const qualifier from the argument type. 71 template < 72 typename List 73 , typename DeducedArgs 74 , typename TagFn 75 , typename IsPositional 76 , typename UsedArgs 77 , typename ArgumentPack 78 #if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564)) 79 , typename _argument 80 #endif 81 , typename Error 82 , typename EmitsErrors 83 > 84 #if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564)) 85 class make_arg_list00 86 #else 87 class make_arg_list0 88 #endif 89 { 90 #if !BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564)) 91 typedef typename List::arg _argument; 92 #endif 93 #if defined(BOOST_PARAMETER_CAN_USE_MP11) 94 using _arg_type = typename ::std::remove_const< 95 typename ::std::remove_reference<_argument>::type 96 >::type; 97 using _is_tagged = ::boost::parameter::aux 98 ::is_named_argument<_argument>; 99 #else 100 typedef typename ::boost::remove_const< 101 typename ::boost::remove_reference<_argument>::type 102 >::type _arg_type; 103 typedef ::boost::parameter::aux 104 ::is_named_argument<_argument> _is_tagged; 105 #endif 106 typedef typename List::spec _parameter_spec; 107 typedef typename ::boost::parameter::aux 108 ::tag_type<_parameter_spec>::type _tag; 109 110 // If this argument is either explicitly tagged or a deduced 111 // parameter, then turn off positional matching. 112 #if defined(BOOST_PARAMETER_CAN_USE_MP11) 113 using _is_positional = ::boost::mp11::mp_if< 114 IsPositional 115 , ::boost::mp11::mp_if< 116 ::boost::parameter::aux::is_deduced<_parameter_spec> 117 , ::boost::mp11::mp_false 118 , ::boost::mp11::mp_if< 119 _is_tagged 120 , ::boost::mp11::mp_false 121 , ::boost::mp11::mp_true 122 > 123 > 124 , ::boost::mp11::mp_false 125 >; 126 #else // !defined(BOOST_PARAMETER_CAN_USE_MP11) 127 typedef typename ::boost::mpl::eval_if< 128 IsPositional 129 , ::boost::mpl::eval_if< 130 ::boost::parameter::aux::is_deduced<_parameter_spec> 131 , ::boost::mpl::false_ 132 , ::boost::mpl::if_< 133 _is_tagged 134 , ::boost::mpl::false_ 135 , ::boost::mpl::true_ 136 > 137 > 138 , ::boost::mpl::false_ 139 >::type _is_positional; 140 #endif // BOOST_PARAMETER_CAN_USE_MP11 141 142 // If this parameter is explicitly tagged, then add it to the 143 // used-parmeters set. We only really need to add parameters 144 // that are deduced, but we would need a way to check if 145 // a given tag corresponds to a deduced parameter spec. 146 #if defined(BOOST_PARAMETER_CAN_USE_MP11) 147 using _used_args = typename ::boost::mp11::mp_if< 148 _is_tagged 149 , ::boost::parameter::aux::insert_tagged<UsedArgs,_arg_type> 150 , ::boost::mp11::mp_identity<UsedArgs> 151 >::type; 152 #else 153 typedef typename ::boost::mpl::eval_if< 154 _is_tagged 155 , ::boost::parameter::aux::insert_tagged<UsedArgs,_arg_type> 156 , ::boost::mpl::identity<UsedArgs> 157 >::type _used_args; 158 #endif 159 160 // If this parameter is neither explicitly tagged nor positionally 161 // matched, then deduce the tag from the deduced parameter specs. 162 #if defined(BOOST_PARAMETER_CAN_USE_MP11) 163 using _deduced_data = typename ::boost::mp11::mp_if< 164 ::boost::mp11::mp_if< 165 _is_tagged 166 , ::boost::mp11::mp_true 167 , _is_positional 168 > 169 , ::boost::mp11::mp_identity< 170 ::boost::mp11::mp_list< ::boost::parameter::void_,_used_args> 171 > 172 #else 173 typedef typename ::boost::mpl::eval_if< 174 typename ::boost::mpl::if_< 175 _is_tagged 176 , ::boost::mpl::true_ 177 , _is_positional 178 >::type 179 , ::boost::mpl::pair< ::boost::parameter::void_,_used_args> 180 #endif 181 , ::boost::parameter::aux::deduce_tag< 182 _argument 183 , ArgumentPack 184 , DeducedArgs 185 , _used_args 186 , TagFn 187 , EmitsErrors 188 > 189 #if defined(BOOST_PARAMETER_CAN_USE_MP11) 190 >::type; 191 #else 192 >::type _deduced_data; 193 #endif 194 195 #if defined(BOOST_PARAMETER_CAN_USE_MP11) 196 // If this parameter is explicitly tagged ... 197 using _tagged = ::boost::mp11::mp_if< 198 _is_tagged 199 // ... just use it 200 , _arg_type 201 // ... else ... 202 , ::boost::mp11::mp_if< 203 // if positional matching is turned on ... 204 _is_positional 205 // ... tag it positionally 206 , ::boost::mp11::mp_apply_q< 207 TagFn 208 , ::boost::mp11::mp_list<_tag,_argument> 209 > 210 // ... else, use the deduced tag 211 , ::boost::mp11::mp_at_c<_deduced_data,0> 212 > 213 >; 214 #else // !defined(BOOST_PARAMETER_CAN_USE_MP11) 215 // If this parameter is explicitly tagged ... 216 typedef typename ::boost::mpl::eval_if< 217 _is_tagged 218 // ... just use it 219 , ::boost::mpl::identity<_arg_type> 220 // ... else ... 221 , ::boost::mpl::eval_if< 222 // if positional matching is turned on ... 223 _is_positional 224 // ... tag it positionally 225 , ::boost::mpl::apply_wrap2<TagFn,_tag,_argument> 226 // ... else, use the deduced tag 227 , ::boost::mpl::first<_deduced_data> 228 > 229 >::type _tagged; 230 #endif // BOOST_PARAMETER_CAN_USE_MP11 231 232 // Build the arg_list incrementally, prepending new nodes. 233 #if defined(BOOST_PARAMETER_CAN_USE_MP11) 234 using _error = ::boost::mp11::mp_if< 235 ::boost::mp11::mp_if< 236 ::std::is_same<Error,::boost::parameter::void_> 237 , ::std::is_same<_tagged,::boost::parameter::void_> 238 , ::boost::mp11::mp_false 239 > 240 #else 241 typedef typename ::boost::mpl::if_< 242 typename ::boost::mpl::if_< 243 ::boost::is_same<Error,::boost::parameter::void_> 244 , ::boost::is_same<_tagged,::boost::parameter::void_> 245 , ::boost::mpl::false_ 246 >::type 247 #endif 248 , ::boost::parameter::aux::unmatched_argument<_argument> 249 , ::boost::parameter::void_ 250 #if defined(BOOST_PARAMETER_CAN_USE_MP11) 251 >; 252 #else 253 >::type _error; 254 #endif 255 256 #if defined(BOOST_PARAMETER_CAN_USE_MP11) 257 using _argument_pack = typename ::boost::mp11::mp_if< 258 ::std::is_same<_tagged,::boost::parameter::void_> 259 , ::boost::mp11::mp_identity<ArgumentPack> 260 , ::boost::parameter::aux 261 ::append_to_make_arg_list<ArgumentPack,_tagged,EmitsErrors> 262 >::type; 263 #else // !defined(BOOST_PARAMETER_CAN_USE_MP11) 264 typedef typename ::boost::mpl::if_< 265 ::boost::is_same<_tagged,::boost::parameter::void_> 266 , ArgumentPack 267 #if defined(BOOST_NO_SFINAE) || BOOST_WORKAROUND(BOOST_MSVC, < 1800) 268 , ::boost::parameter::aux::arg_list<_tagged,ArgumentPack> 269 #else 270 , ::boost::parameter::aux 271 ::arg_list<_tagged,ArgumentPack,EmitsErrors> 272 #endif 273 >::type _argument_pack; 274 #endif // BOOST_PARAMETER_CAN_USE_MP11 275 276 public: 277 typedef typename ::boost::parameter::aux::make_arg_list_aux< 278 typename List::tail 279 , DeducedArgs 280 , TagFn 281 , _is_positional 282 #if defined(BOOST_PARAMETER_CAN_USE_MP11) 283 , ::boost::mp11::mp_at_c<_deduced_data,1> 284 #else 285 , typename _deduced_data::second 286 #endif 287 , _argument_pack 288 , _error 289 , EmitsErrors 290 >::type type; 291 }; 292 293 #if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564)) 294 template < 295 typename List 296 , typename DeducedArgs 297 , typename TagFn 298 , typename IsPositional 299 , typename UsedArgs 300 , typename ArgumentPack 301 , typename Error 302 , typename EmitsErrors 303 > 304 struct make_arg_list0 305 { 306 typedef typename ::boost::mpl::eval_if< 307 typename List::is_arg_const 308 , ::boost::parameter::aux::make_arg_list00< 309 List 310 , DeducedArgs 311 , TagFn 312 , IsPositional 313 , UsedArgs 314 , ArgumentPack 315 , typename List::arg const 316 , Error 317 , EmitsErrors 318 > 319 , ::boost::parameter::aux::make_arg_list00< 320 List 321 , DeducedArgs 322 , TagFn 323 , IsPositional 324 , UsedArgs 325 , ArgumentPack 326 , typename List::arg 327 , Error 328 , EmitsErrors 329 > 330 >::type type; 331 }; 332 #endif // Borland workarounds needed. 333 334 // Returns an ArgumentPack where the list of arguments has been tagged 335 // with keyword tags. 336 // 337 // List: A specialization of item<> (see below). Contains both 338 // the ordered ParameterSpecs, and the given arguments. 339 // 340 // DeducedArgs: A specialization of deduced_item<> (see below). 341 // A list containing only the deduced ParameterSpecs. 342 // 343 // TagFn: A metafunction class used to tag positional or deduced 344 // arguments with a keyword tag. 345 // 346 // IsPositional: An mpl::bool_<> specialization indicating if positional 347 // matching is to be performed. 348 // 349 // DeducedSet: An mpl::set<> containing the keyword tags used so far. 350 // 351 // ArgumentPack: The ArgumentPack built so far. This is initially an 352 // empty_arg_list and is built incrementally. 353 template < 354 typename List 355 , typename DeducedArgs 356 , typename TagFn 357 , typename IsPositional 358 , typename DeducedSet 359 , typename ArgumentPack 360 , typename Error 361 , typename EmitsErrors 362 > 363 struct make_arg_list_aux 364 #if defined(BOOST_PARAMETER_CAN_USE_MP11) 365 : ::boost::mp11::mp_if< 366 ::std::is_same<List,::boost::parameter::void_> 367 , ::boost::mp11::mp_identity< 368 ::boost::mp11::mp_list<ArgumentPack,Error> 369 > 370 #else 371 : ::boost::mpl::eval_if< 372 ::boost::is_same<List,::boost::parameter::void_> 373 , ::boost::mpl::identity< ::boost::mpl::pair<ArgumentPack,Error> > 374 #endif 375 , ::boost::parameter::aux::make_arg_list0< 376 List 377 , DeducedArgs 378 , TagFn 379 , IsPositional 380 , DeducedSet 381 , ArgumentPack 382 , Error 383 , EmitsErrors 384 > 385 > 386 { 387 }; 388 }}} // namespace boost::parameter::aux 389 390 #include <boost/parameter/aux_/set.hpp> 391 392 namespace boost { namespace parameter { namespace aux { 393 394 // VC6.5 was choking on the default parameters for make_arg_list_aux, 395 // so this just forwards to that adding in the defaults. 396 template < 397 typename List 398 , typename DeducedArgs 399 , typename TagFn 400 #if defined(BOOST_PARAMETER_CAN_USE_MP11) 401 , typename EmitsErrors = ::boost::mp11::mp_true 402 #else 403 , typename EmitsErrors = ::boost::mpl::true_ 404 #endif 405 > 406 #if defined(BOOST_PARAMETER_CAN_USE_MP11) 407 using make_arg_list = ::boost::parameter::aux::make_arg_list_aux< 408 #else 409 struct make_arg_list 410 : ::boost::parameter::aux::make_arg_list_aux< 411 #endif 412 List 413 , DeducedArgs 414 , TagFn 415 #if defined(BOOST_PARAMETER_CAN_USE_MP11) 416 , ::boost::mp11::mp_true 417 #else 418 , ::boost::mpl::true_ 419 #endif 420 , ::boost::parameter::aux::set0 421 #if defined(BOOST_PARAMETER_CAN_USE_MP11) 422 , ::boost::parameter::aux::flat_like_arg_list<> 423 #else 424 , ::boost::parameter::aux::empty_arg_list 425 #endif 426 , ::boost::parameter::void_ 427 , EmitsErrors 428 #if defined(BOOST_PARAMETER_CAN_USE_MP11) 429 >; 430 #else 431 > 432 { 433 }; 434 #endif 435 }}} // namespace boost::parameter::aux 436 437 #endif // include guard 438 439