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)
7 #ifndef BOOST_PARAMETER_AUX_PACK_MAKE_ARG_LIST_HPP
8 #define BOOST_PARAMETER_AUX_PACK_MAKE_ARG_LIST_HPP
10 namespace boost { namespace parameter { namespace aux {
14 , typename DeducedArgs
16 , typename IsPositional
18 , typename ArgumentPack
20 , typename EmitsErrors
22 struct make_arg_list_aux;
23 }}} // namespace boost::parameter::aux
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>
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>
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>
52 namespace boost { namespace parameter { namespace aux {
54 #if defined(BOOST_PARAMETER_CAN_USE_MP11)
55 template <typename ArgumentPack, typename TaggedArg, typename EmitsErrors>
56 struct append_to_make_arg_list
58 using type = ::boost::mp11::mp_push_front<
60 , ::boost::parameter::aux::flat_like_arg_tuple<
61 typename TaggedArg::key_type
69 // Borland needs the insane extra-indirection workaround below so that
70 // it doesn't magically drop the const qualifier from the argument type.
73 , typename DeducedArgs
75 , typename IsPositional
77 , typename ArgumentPack
78 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
82 , typename EmitsErrors
84 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
90 #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
91 typedef typename List::arg _argument;
93 #if defined(BOOST_PARAMETER_CAN_USE_MP11)
94 using _arg_type = typename ::std::remove_const<
95 typename ::std::remove_reference<_argument>::type
97 using _is_tagged = ::boost::parameter::aux
98 ::is_named_argument<_argument>;
100 typedef typename ::boost::remove_const<
101 typename ::boost::remove_reference<_argument>::type
103 typedef ::boost::parameter::aux
104 ::is_named_argument<_argument> _is_tagged;
106 typedef typename List::spec _parameter_spec;
107 typedef typename ::boost::parameter::aux
108 ::tag_type<_parameter_spec>::type _tag;
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<
115 , ::boost::mp11::mp_if<
116 ::boost::parameter::aux::is_deduced<_parameter_spec>
117 , ::boost::mp11::mp_false
118 , ::boost::mp11::mp_if<
120 , ::boost::mp11::mp_false
121 , ::boost::mp11::mp_true
124 , ::boost::mp11::mp_false
126 #else // !defined(BOOST_PARAMETER_CAN_USE_MP11)
127 typedef typename ::boost::mpl::eval_if<
129 , ::boost::mpl::eval_if<
130 ::boost::parameter::aux::is_deduced<_parameter_spec>
131 , ::boost::mpl::false_
134 , ::boost::mpl::false_
135 , ::boost::mpl::true_
138 , ::boost::mpl::false_
139 >::type _is_positional;
140 #endif // BOOST_PARAMETER_CAN_USE_MP11
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<
149 , ::boost::parameter::aux::insert_tagged<UsedArgs,_arg_type>
150 , ::boost::mp11::mp_identity<UsedArgs>
153 typedef typename ::boost::mpl::eval_if<
155 , ::boost::parameter::aux::insert_tagged<UsedArgs,_arg_type>
156 , ::boost::mpl::identity<UsedArgs>
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<
166 , ::boost::mp11::mp_true
169 , ::boost::mp11::mp_identity<
170 ::boost::mp11::mp_list< ::boost::parameter::void_,_used_args>
173 typedef typename ::boost::mpl::eval_if<
174 typename ::boost::mpl::if_<
176 , ::boost::mpl::true_
179 , ::boost::mpl::pair< ::boost::parameter::void_,_used_args>
181 , ::boost::parameter::aux::deduce_tag<
189 #if defined(BOOST_PARAMETER_CAN_USE_MP11)
192 >::type _deduced_data;
195 #if defined(BOOST_PARAMETER_CAN_USE_MP11)
196 // If this parameter is explicitly tagged ...
197 using _tagged = ::boost::mp11::mp_if<
202 , ::boost::mp11::mp_if<
203 // if positional matching is turned on ...
205 // ... tag it positionally
206 , ::boost::mp11::mp_apply_q<
208 , ::boost::mp11::mp_list<_tag,_argument>
210 // ... else, use the deduced tag
211 , ::boost::mp11::mp_at_c<_deduced_data,0>
214 #else // !defined(BOOST_PARAMETER_CAN_USE_MP11)
215 // If this parameter is explicitly tagged ...
216 typedef typename ::boost::mpl::eval_if<
219 , ::boost::mpl::identity<_arg_type>
221 , ::boost::mpl::eval_if<
222 // if positional matching is turned on ...
224 // ... tag it positionally
225 , ::boost::mpl::apply_wrap2<TagFn,_tag,_argument>
226 // ... else, use the deduced tag
227 , ::boost::mpl::first<_deduced_data>
230 #endif // BOOST_PARAMETER_CAN_USE_MP11
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
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_
248 , ::boost::parameter::aux::unmatched_argument<_argument>
249 , ::boost::parameter::void_
250 #if defined(BOOST_PARAMETER_CAN_USE_MP11)
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>
263 #else // !defined(BOOST_PARAMETER_CAN_USE_MP11)
264 typedef typename ::boost::mpl::if_<
265 ::boost::is_same<_tagged,::boost::parameter::void_>
267 #if defined(BOOST_NO_SFINAE) || BOOST_WORKAROUND(BOOST_MSVC, < 1800)
268 , ::boost::parameter::aux::arg_list<_tagged,ArgumentPack>
270 , ::boost::parameter::aux
271 ::arg_list<_tagged,ArgumentPack,EmitsErrors>
273 >::type _argument_pack;
274 #endif // BOOST_PARAMETER_CAN_USE_MP11
277 typedef typename ::boost::parameter::aux::make_arg_list_aux<
282 #if defined(BOOST_PARAMETER_CAN_USE_MP11)
283 , ::boost::mp11::mp_at_c<_deduced_data,1>
285 , typename _deduced_data::second
293 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
296 , typename DeducedArgs
298 , typename IsPositional
300 , typename ArgumentPack
302 , typename EmitsErrors
304 struct make_arg_list0
306 typedef typename ::boost::mpl::eval_if<
307 typename List::is_arg_const
308 , ::boost::parameter::aux::make_arg_list00<
315 , typename List::arg const
319 , ::boost::parameter::aux::make_arg_list00<
332 #endif // Borland workarounds needed.
334 // Returns an ArgumentPack where the list of arguments has been tagged
335 // with keyword tags.
337 // List: A specialization of item<> (see below). Contains both
338 // the ordered ParameterSpecs, and the given arguments.
340 // DeducedArgs: A specialization of deduced_item<> (see below).
341 // A list containing only the deduced ParameterSpecs.
343 // TagFn: A metafunction class used to tag positional or deduced
344 // arguments with a keyword tag.
346 // IsPositional: An mpl::bool_<> specialization indicating if positional
347 // matching is to be performed.
349 // DeducedSet: An mpl::set<> containing the keyword tags used so far.
351 // ArgumentPack: The ArgumentPack built so far. This is initially an
352 // empty_arg_list and is built incrementally.
355 , typename DeducedArgs
357 , typename IsPositional
358 , typename DeducedSet
359 , typename ArgumentPack
361 , typename EmitsErrors
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>
371 : ::boost::mpl::eval_if<
372 ::boost::is_same<List,::boost::parameter::void_>
373 , ::boost::mpl::identity< ::boost::mpl::pair<ArgumentPack,Error> >
375 , ::boost::parameter::aux::make_arg_list0<
388 }}} // namespace boost::parameter::aux
390 #include <boost/parameter/aux_/set.hpp>
392 namespace boost { namespace parameter { namespace aux {
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.
398 , typename DeducedArgs
400 #if defined(BOOST_PARAMETER_CAN_USE_MP11)
401 , typename EmitsErrors = ::boost::mp11::mp_true
403 , typename EmitsErrors = ::boost::mpl::true_
406 #if defined(BOOST_PARAMETER_CAN_USE_MP11)
407 using make_arg_list = ::boost::parameter::aux::make_arg_list_aux<
410 : ::boost::parameter::aux::make_arg_list_aux<
415 #if defined(BOOST_PARAMETER_CAN_USE_MP11)
416 , ::boost::mp11::mp_true
418 , ::boost::mpl::true_
420 , ::boost::parameter::aux::set0
421 #if defined(BOOST_PARAMETER_CAN_USE_MP11)
422 , ::boost::parameter::aux::flat_like_arg_list<>
424 , ::boost::parameter::aux::empty_arg_list
426 , ::boost::parameter::void_
428 #if defined(BOOST_PARAMETER_CAN_USE_MP11)
435 }}} // namespace boost::parameter::aux
437 #endif // include guard