1 // Copyright David Abrahams, Daniel Wallin 2003.
2 // Copyright Cromwell D. Enage 2017.
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_PARAMETERS_031014_HPP
8 #define BOOST_PARAMETERS_031014_HPP
10 #include <boost/parameter/config.hpp>
12 #if defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING)
14 namespace boost { namespace parameter { namespace aux {
16 // The make_arg_list<> metafunction produces a reversed arg_list,
17 // so pass the arguments to the arg_list constructor reversed in turn.
18 template <typename ArgList, typename ...Args>
19 struct arg_list_factory;
20 }}} // namespace boost::parameter::aux
22 #include <boost/parameter/aux_/arg_list.hpp>
25 #if defined(BOOST_PARAMETER_CAN_USE_MP11)
26 #include <boost/mp11/utility.hpp>
27 #include <type_traits>
29 #include <boost/mpl/if.hpp>
30 #include <boost/type_traits/is_same.hpp>
33 namespace boost { namespace parameter { namespace aux {
35 // TODO: Reduce template code bloat. -- Cromwell D. Enage
36 template <typename ArgList>
37 struct arg_list_factory<ArgList>
39 template <typename ...ReversedArgs>
40 static inline BOOST_CONSTEXPR ArgList
41 reverse(ReversedArgs&&... reversed_args)
44 #if defined(BOOST_PARAMETER_CAN_USE_MP11)
48 typename ::boost::mpl::if_<
51 typename ArgList::tagged_arg::value_type
52 , ::boost::parameter::void_
54 , ::boost::parameter::aux::value_type_is_void
55 , ::boost::parameter::aux::value_type_is_not_void
56 #if defined(BOOST_PARAMETER_CAN_USE_MP11)
61 , ::std::forward<ReversedArgs>(reversed_args)...
66 template <typename ArgList, typename A0, typename ...Args>
67 struct arg_list_factory<ArgList,A0,Args...>
69 template <typename ...ReversedArgs>
70 static inline BOOST_CONSTEXPR ArgList
71 reverse(A0&& a0, Args&&... args, ReversedArgs&&... reversed_args)
73 return ::boost::parameter::aux
74 ::arg_list_factory<ArgList,Args...>::reverse(
75 ::std::forward<Args>(args)...
76 , ::std::forward<A0>(a0)
77 , ::std::forward<ReversedArgs>(reversed_args)...
81 }}} // namespace boost::parameter::aux
83 #include <boost/parameter/aux_/void.hpp>
84 #include <boost/parameter/aux_/pack/make_arg_list.hpp>
85 #include <boost/parameter/aux_/pack/make_parameter_spec_items.hpp>
86 #include <boost/parameter/aux_/pack/tag_keyword_arg.hpp>
87 #include <boost/parameter/aux_/pack/tag_template_keyword_arg.hpp>
89 #if defined(BOOST_PARAMETER_CAN_USE_MP11)
90 #include <boost/mp11/integral.hpp>
91 #include <boost/mp11/list.hpp>
93 #include <boost/mpl/bool.hpp>
94 #include <boost/mpl/pair.hpp>
95 #include <boost/mpl/identity.hpp>
98 #if !defined(BOOST_PARAMETER_VARIADIC_MPL_SEQUENCE)
99 #if defined(BOOST_PARAMETER_CAN_USE_MP11)
100 //#include <boost/mp11/mpl.hpp>
101 #define BOOST_PARAMETER_VARIADIC_MPL_SEQUENCE ::boost::mp11::mp_list
103 #include <boost/fusion/container/list/list_fwd.hpp>
105 // Newer versions of MSVC fail on the evaluate_category and
106 // preprocessor_eval_category test programs when parameters uses
107 // boost::fusion::list.
108 // -- Cromwell D. Enage
109 #if defined(BOOST_FUSION_HAS_VARIADIC_LIST) && ( \
110 !defined(BOOST_MSVC) || (BOOST_MSVC < 1800) \
112 #include <boost/fusion/container/list.hpp>
113 #include <boost/fusion/mpl.hpp>
114 #define BOOST_PARAMETER_VARIADIC_MPL_SEQUENCE ::boost::fusion::list
116 #include <boost/fusion/container/deque/deque_fwd.hpp>
118 #if defined(BOOST_FUSION_HAS_VARIADIC_DEQUE)
119 #include <boost/fusion/container/deque.hpp>
120 #include <boost/fusion/mpl.hpp>
121 #define BOOST_PARAMETER_VARIADIC_MPL_SEQUENCE ::boost::fusion::deque
123 #include <boost/mpl/vector.hpp>
124 #define BOOST_PARAMETER_VARIADIC_MPL_SEQUENCE ::boost::mpl::vector
125 #endif // BOOST_FUSION_HAS_VARIADIC_DEQUE
126 #endif // BOOST_FUSION_HAS_VARIADIC_LIST
127 #endif // BOOST_PARAMETER_CAN_USE_MP11
128 #endif // BOOST_PARAMETER_VARIADIC_MPL_SEQUENCE
130 namespace boost { namespace parameter {
132 template <typename ...Spec>
135 typedef BOOST_PARAMETER_VARIADIC_MPL_SEQUENCE<Spec...> parameter_spec;
137 typedef typename ::boost::parameter::aux
138 ::make_deduced_list<parameter_spec>::type deduced_list;
140 // If the elements of NamedList match the criteria of overload
141 // resolution, returns a type which can be constructed from
142 // parameters. Otherwise, this is not a valid metafunction
143 // (no nested ::type).
144 template <typename ArgumentPackAndError>
146 #if !defined(BOOST_PARAMETER_CAN_USE_MP11)
148 typename ::boost::parameter::aux::match_parameters_base_cond<
152 , ::boost::mpl::identity<
153 ::boost::parameter::parameters<Spec...>
155 , ::boost::parameter::void_
159 #if defined(BOOST_PARAMETER_CAN_USE_MP11)
160 using type = ::boost::mp11::mp_if<
161 typename ::boost::parameter::aux::match_parameters_base_cond<
165 , ::boost::mp11::mp_identity<
166 ::boost::parameter::parameters<Spec...>
168 , ::boost::parameter::void_
173 // Specializations are to be used as an optional argument
174 // to eliminate overloads via SFINAE.
175 template <typename ...Args>
177 : ::boost::parameter::parameters<Spec...>
178 ::BOOST_NESTED_TEMPLATE match_base<
179 typename ::boost::parameter::aux::make_arg_list<
180 typename ::boost::parameter::aux
181 ::make_parameter_spec_items<parameter_spec,Args...>::type
183 , ::boost::parameter::aux::tag_keyword_arg
184 // Don't emit errors when doing SFINAE.
185 #if defined(BOOST_PARAMETER_CAN_USE_MP11)
186 , ::boost::mp11::mp_false
188 , ::boost::mpl::false_
195 // Metafunction that returns an ArgumentPack.
196 template <typename ...Args>
198 #if !defined(BOOST_PARAMETER_CAN_USE_MP11)
199 : ::boost::mpl::first<
200 typename ::boost::parameter::aux::make_arg_list<
201 typename ::boost::parameter::aux
202 ::make_parameter_spec_items<parameter_spec,Args...>::type
204 , ::boost::parameter::aux::tag_template_keyword_arg
209 #if defined(BOOST_PARAMETER_CAN_USE_MP11)
210 using type = ::boost::mp11::mp_at_c<
211 typename ::boost::parameter::aux::make_arg_list<
212 typename ::boost::parameter::aux
213 ::make_parameter_spec_items<parameter_spec,Args...>::type
215 , ::boost::parameter::aux::tag_template_keyword_arg
222 // The function call operator is used to build an arg_list that
223 // labels the positional parameters and maintains whatever other
224 // tags may have been specified by the caller.
225 inline ::boost::parameter::aux::empty_arg_list operator()() const
227 return ::boost::parameter::aux::empty_arg_list();
230 template <typename A0, typename ...Args>
231 #if defined(BOOST_PARAMETER_CAN_USE_MP11)
232 inline ::boost::mp11::mp_at_c<
234 inline typename ::boost::mpl::first<
236 typename ::boost::parameter::aux::make_arg_list<
237 typename ::boost::parameter::aux
238 ::make_parameter_spec_items<parameter_spec,A0,Args...>::type
240 , ::boost::parameter::aux::tag_keyword_arg
242 #if defined(BOOST_PARAMETER_CAN_USE_MP11)
248 operator()(A0&& a0, Args&& ...args) const
250 typedef typename ::boost::parameter::aux::make_arg_list<
251 typename ::boost::parameter::aux
252 ::make_parameter_spec_items<parameter_spec,A0,Args...>::type
254 , ::boost::parameter::aux::tag_keyword_arg
255 >::type list_error_pair;
257 #if defined(BOOST_PARAMETER_CAN_USE_MP11)
258 using result_type = ::boost::mp11::mp_at_c<list_error_pair,0>;
260 using error = ::boost::mp11::mp_at_c<list_error_pair,1>;
262 typedef typename ::boost::mpl
263 ::first<list_error_pair>::type result_type;
265 typedef typename ::boost::mpl
266 ::second<list_error_pair>::type error;
271 return ::boost::parameter::aux
272 ::arg_list_factory<result_type,A0,Args...>::reverse(
273 ::std::forward<A0>(a0)
274 , ::std::forward<Args>(args)...
278 }} // namespace boost::parameter
280 #else // !defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING)
282 #include <boost/parameter/aux_/void.hpp>
283 #include <boost/parameter/aux_/arg_list.hpp>
284 #include <boost/parameter/aux_/pack/make_arg_list.hpp>
285 #include <boost/parameter/aux_/pack/make_items.hpp>
286 #include <boost/parameter/aux_/pack/make_deduced_items.hpp>
287 #include <boost/parameter/aux_/pack/tag_template_keyword_arg.hpp>
288 #include <boost/parameter/aux_/preprocessor/binary_seq_for_each.hpp>
289 #include <boost/preprocessor/arithmetic/inc.hpp>
290 #include <boost/preprocessor/repetition/enum_shifted.hpp>
291 #include <boost/preprocessor/repetition/repeat.hpp>
292 #include <boost/preprocessor/selection/min.hpp>
295 BOOST_PARAMETER_EXPONENTIAL_OVERLOAD_THRESHOLD_ARITY < \
296 BOOST_PARAMETER_MAX_ARITY \
298 #include <boost/parameter/aux_/pack/tag_keyword_arg_ref.hpp>
299 #include <boost/mpl/pair.hpp>
300 #include <boost/preprocessor/arithmetic/dec.hpp>
301 #include <boost/preprocessor/arithmetic/sub.hpp>
302 #include <boost/preprocessor/facilities/intercept.hpp>
303 #include <boost/preprocessor/iteration/iterate.hpp>
304 #include <boost/preprocessor/repetition/enum.hpp>
305 #include <boost/preprocessor/repetition/enum_trailing_params.hpp>
308 #if !defined(BOOST_NO_SFINAE) && \
309 !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x592))
310 #include <boost/parameter/aux_/pack/tag_keyword_arg.hpp>
311 #include <boost/mpl/bool.hpp>
312 #include <boost/mpl/if.hpp>
313 #include <boost/mpl/identity.hpp>
314 #include <boost/type_traits/is_same.hpp>
317 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
318 #include <boost/preprocessor/repetition/enum_params.hpp>
320 #include <boost/preprocessor/repetition/enum_binary_params.hpp>
323 #include <boost/parameter/aux_/preprocessor/no_perfect_forwarding_begin.hpp>
325 namespace boost { namespace parameter {
329 , BOOST_PP_ENUM_SHIFTED(
330 BOOST_PARAMETER_MAX_ARITY
331 , BOOST_PARAMETER_template_args
337 typedef typename BOOST_PARAMETER_build_deduced_list(
338 BOOST_PARAMETER_MAX_ARITY
339 , ::boost::parameter::aux::make_deduced_items
341 )::type deduced_list;
343 // If the elements of NamedList match the criteria of overload
344 // resolution, returns a type which can be constructed from
345 // parameters. Otherwise, this is not a valid metafunction
346 // (no nested ::type).
347 #if !defined(BOOST_NO_SFINAE) && \
348 !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x592))
349 // If NamedList satisfies the PS0, PS1, ..., this is a metafunction
350 // returning parameters. Otherwise it has no nested ::type.
351 template <typename ArgumentPackAndError>
354 // ::boost::mpl::and_<
355 // aux::satisfies_requirements_of<NamedList,PS0>
356 // , ::boost::mpl::and_<
357 // aux::satisfies_requirements_of<NamedList,PS1>...
358 // ..., ::boost::mpl::true_
360 typename BOOST_PP_REPEAT(
361 BOOST_PARAMETER_MAX_ARITY
362 , BOOST_PARAMETER_satisfies_begin
366 typename ::boost::mpl
367 ::second<ArgumentPackAndError>::type
368 , ::boost::parameter::void_
371 BOOST_PARAMETER_MAX_ARITY
372 , BOOST_PARAMETER_satisfies_end
373 , ::boost::mpl::false_
375 , ::boost::mpl::identity<
376 ::boost::parameter::parameters<
377 BOOST_PP_ENUM_PARAMS(BOOST_PARAMETER_MAX_ARITY, PS)
380 , ::boost::parameter::void_
384 #endif // SFINAE enabled, not Borland
386 // Specializations are to be used as an optional argument
387 // to eliminate overloads via SFINAE.
389 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
390 // Borland simply can't handle default arguments in member
391 // class templates. People wishing to write portable code can
392 // explicitly specify BOOST_PARAMETER_MAX_ARITY arguments.
393 BOOST_PP_ENUM_PARAMS(BOOST_PARAMETER_MAX_ARITY, typename A)
395 BOOST_PP_ENUM_BINARY_PARAMS(
396 BOOST_PARAMETER_MAX_ARITY
398 , = ::boost::parameter::void_ BOOST_PP_INTERCEPT
403 #if !defined(BOOST_NO_SFINAE) && \
404 !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x592))
405 : ::boost::parameter::parameters<
406 BOOST_PP_ENUM_PARAMS(BOOST_PARAMETER_MAX_ARITY, PS)
407 >::BOOST_NESTED_TEMPLATE match_base<
408 typename ::boost::parameter::aux::make_arg_list<
409 typename BOOST_PARAMETER_build_arg_list(
410 BOOST_PARAMETER_MAX_ARITY
411 , ::boost::parameter::aux::make_items
416 , ::boost::parameter::aux::tag_keyword_arg
417 // Don't emit errors when doing SFINAE.
418 , ::boost::mpl::false_
425 typedef ::boost::parameter::parameters<
426 BOOST_PP_ENUM_PARAMS(BOOST_PARAMETER_MAX_ARITY, PS)
429 #endif // SFINAE enabled, not Borland
431 // Metafunction that returns an ArgumentPack.
433 // TODO, bind has to instantiate the error type in the result
437 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
438 // Borland simply can't handle default arguments in member
439 // class templates. People wishing to write portable code can
440 // explicitly specify BOOST_PARAMETER_MAX_ARITY arguments.
441 BOOST_PP_ENUM_PARAMS(BOOST_PARAMETER_MAX_ARITY, typename A)
443 BOOST_PP_ENUM_BINARY_PARAMS(
444 BOOST_PARAMETER_MAX_ARITY
446 , = ::boost::parameter::void_ BOOST_PP_INTERCEPT
452 typedef typename ::boost::parameter::aux::make_arg_list<
453 typename BOOST_PARAMETER_build_arg_list(
454 BOOST_PARAMETER_MAX_ARITY
455 , ::boost::parameter::aux::make_items
460 , ::boost::parameter::aux::tag_template_keyword_arg
463 typedef typename ::boost::mpl::first<result>::type type;
467 BOOST_PARAMETER_MAX_ARITY
468 , BOOST_PARAMETER_forward_typedef
469 , (PS)(parameter_spec)
472 // The function call operator is used to build an arg_list that
473 // labels the positional parameters and maintains whatever other
474 // tags may have been specified by the caller.
478 // The make_arg_list<> metafunction produces a reversed arg_list,
479 // so pass the arguments to the arg_list constructor reversed in turn.
480 inline ::boost::parameter::aux::empty_arg_list operator()() const
482 return ::boost::parameter::aux::empty_arg_list();
485 #if (0 < BOOST_PARAMETER_EXPONENTIAL_OVERLOAD_THRESHOLD_ARITY)
488 BOOST_PP_INC(BOOST_PARAMETER_MAX_ARITY)
489 , BOOST_PARAMETER_EXPONENTIAL_OVERLOAD_THRESHOLD_ARITY
491 , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_Z
492 , (BOOST_PARAMETER_function_call_op_overload_R)(_)
495 BOOST_PARAMETER_EXPONENTIAL_OVERLOAD_THRESHOLD_ARITY < \
496 BOOST_PARAMETER_MAX_ARITY \
498 #define BOOST_PP_ITERATION_PARAMS_1 \
500 BOOST_PARAMETER_EXPONENTIAL_OVERLOAD_THRESHOLD_ARITY \
501 , BOOST_PARAMETER_MAX_ARITY \
502 , <boost/parameter/aux_/preprocessor/overloads.hpp> \
504 #include BOOST_PP_ITERATE()
506 #else // (0 == BOOST_PARAMETER_EXPONENTIAL_OVERLOAD_THRESHOLD_ARITY)
507 template <typename A0>
508 inline typename ::boost::mpl::first<
509 typename ::boost::parameter::aux::make_arg_list<
510 ::boost::parameter::aux::item<
514 , ::boost::parameter::aux::tag_keyword_arg_ref
517 operator()(A0& a0) const
519 typedef typename ::boost::parameter::aux::make_arg_list<
520 ::boost::parameter::aux::item<
524 , ::boost::parameter::aux::tag_keyword_arg_ref
527 typedef typename ::boost::mpl::first<result>::type result_type;
528 typedef typename ::boost::mpl::second<result>::type error;
533 // , void_(), void_(), void_() ...
534 BOOST_PP_ENUM_TRAILING_PARAMS(
535 BOOST_PP_SUB(BOOST_PARAMETER_COMPOSE_MAX_ARITY, 1)
536 , ::boost::parameter::aux::void_reference() BOOST_PP_INTERCEPT
541 template <typename A0, typename A1>
542 inline typename ::boost::mpl::first<
543 typename ::boost::parameter::aux::make_arg_list<
544 ::boost::parameter::aux::item<
546 , ::boost::parameter::aux::item<
551 , ::boost::parameter::aux::tag_keyword_arg_ref
554 operator()(A0& a0, A1& a1) const
556 typedef typename ::boost::parameter::aux::make_arg_list<
557 ::boost::parameter::aux::item<
559 , ::boost::parameter::aux::item<
564 , ::boost::parameter::aux::tag_keyword_arg
567 typedef typename ::boost::mpl::first<result>::type result_type;
568 typedef typename ::boost::mpl::second<result>::type error;
574 // , void_(), void_() ...
575 BOOST_PP_ENUM_TRAILING_PARAMS(
576 BOOST_PP_SUB(BOOST_PARAMETER_COMPOSE_MAX_ARITY, 2)
577 , ::boost::parameter::aux::void_reference() BOOST_PP_INTERCEPT
582 #if (2 < BOOST_PARAMETER_MAX_ARITY)
583 // Higher arities are handled by the preprocessor
584 #define BOOST_PP_ITERATION_PARAMS_1 \
587 , BOOST_PARAMETER_MAX_ARITY \
588 , <boost/parameter/aux_/preprocessor/overloads.hpp> \
590 #include BOOST_PP_ITERATE()
592 #endif // exponential overloads
594 }} // namespace boost::parameter
596 #include <boost/parameter/aux_/preprocessor/no_perfect_forwarding_end.hpp>
598 #endif // BOOST_PARAMETER_HAS_PERFECT_FORWARDING
599 #endif // include guard