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)
6
7#ifndef BOOST_PARAMETERS_031014_HPP
8#define BOOST_PARAMETERS_031014_HPP
9
10#include <boost/parameter/config.hpp>
11
12#if defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING)
13
14namespace boost { namespace parameter { namespace aux {
15
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
21
22#include <boost/parameter/aux_/arg_list.hpp>
23#include <utility>
24
25#if defined(BOOST_PARAMETER_CAN_USE_MP11)
26#include <boost/mp11/utility.hpp>
27#include <type_traits>
28#else
29#include <boost/mpl/if.hpp>
30#include <boost/type_traits/is_same.hpp>
31#endif
32
33namespace boost { namespace parameter { namespace aux {
34
35 // TODO: Reduce template code bloat. -- Cromwell D. Enage
36 template <typename ArgList>
37 struct arg_list_factory<ArgList>
38 {
39 template <typename ...ReversedArgs>
40 static inline BOOST_CONSTEXPR ArgList
41 reverse(ReversedArgs&&... reversed_args)
42 {
43 return ArgList(
44#if defined(BOOST_PARAMETER_CAN_USE_MP11)
45 ::boost::mp11::mp_if<
46 ::std::is_same<
47#else
48 typename ::boost::mpl::if_<
49 ::boost::is_same<
50#endif
51 typename ArgList::tagged_arg::value_type
52 , ::boost::parameter::void_
53 >
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)
57 >()
58#else
59 >::type()
60#endif
61 , ::std::forward<ReversedArgs>(reversed_args)...
62 );
63 }
64 };
65
66 template <typename ArgList, typename A0, typename ...Args>
67 struct arg_list_factory<ArgList,A0,Args...>
68 {
69 template <typename ...ReversedArgs>
70 static inline BOOST_CONSTEXPR ArgList
71 reverse(A0&& a0, Args&&... args, ReversedArgs&&... reversed_args)
72 {
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)...
78 );
79 }
80 };
81}}} // namespace boost::parameter::aux
82
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>
88
89#if defined(BOOST_PARAMETER_CAN_USE_MP11)
90#include <boost/mp11/integral.hpp>
91#include <boost/mp11/list.hpp>
92#else
93#include <boost/mpl/bool.hpp>
94#include <boost/mpl/pair.hpp>
95#include <boost/mpl/identity.hpp>
96#endif
97
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
102#else
103#include <boost/fusion/container/list/list_fwd.hpp>
104
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) \
111 )
112#include <boost/fusion/container/list.hpp>
113#include <boost/fusion/mpl.hpp>
114#define BOOST_PARAMETER_VARIADIC_MPL_SEQUENCE ::boost::fusion::list
115#else
116#include <boost/fusion/container/deque/deque_fwd.hpp>
117
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
122#else
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
129
130namespace boost { namespace parameter {
131
132 template <typename ...Spec>
133 struct parameters
134 {
135 typedef BOOST_PARAMETER_VARIADIC_MPL_SEQUENCE<Spec...> parameter_spec;
136
137 typedef typename ::boost::parameter::aux
138 ::make_deduced_list<parameter_spec>::type deduced_list;
139
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>
145 struct match_base
146#if !defined(BOOST_PARAMETER_CAN_USE_MP11)
147 : ::boost::mpl::if_<
148 typename ::boost::parameter::aux::match_parameters_base_cond<
149 ArgumentPackAndError
150 , parameter_spec
151 >::type
152 , ::boost::mpl::identity<
153 ::boost::parameter::parameters<Spec...>
154 >
155 , ::boost::parameter::void_
156 >
157#endif
158 {
159#if defined(BOOST_PARAMETER_CAN_USE_MP11)
160 using type = ::boost::mp11::mp_if<
161 typename ::boost::parameter::aux::match_parameters_base_cond<
162 ArgumentPackAndError
163 , parameter_spec
164 >::type
165 , ::boost::mp11::mp_identity<
166 ::boost::parameter::parameters<Spec...>
167 >
168 , ::boost::parameter::void_
169 >;
170#endif
171 };
172
173 // Specializations are to be used as an optional argument
174 // to eliminate overloads via SFINAE.
175 template <typename ...Args>
176 struct match
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
182 , deduced_list
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
187#else
188 , ::boost::mpl::false_
189#endif
190 >::type
191 >::type
192 {
193 };
194
195 // Metafunction that returns an ArgumentPack.
196 template <typename ...Args>
197 struct bind
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
203 , deduced_list
204 , ::boost::parameter::aux::tag_template_keyword_arg
205 >::type
206 >
207#endif
208 {
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
214 , deduced_list
215 , ::boost::parameter::aux::tag_template_keyword_arg
216 >::type
217 , 0
218 >;
219#endif
220 };
221
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
226 {
227 return ::boost::parameter::aux::empty_arg_list();
228 }
229
230 template <typename A0, typename ...Args>
231#if defined(BOOST_PARAMETER_CAN_USE_MP11)
232 inline ::boost::mp11::mp_at_c<
233#else
234 inline typename ::boost::mpl::first<
235#endif
236 typename ::boost::parameter::aux::make_arg_list<
237 typename ::boost::parameter::aux
238 ::make_parameter_spec_items<parameter_spec,A0,Args...>::type
239 , deduced_list
240 , ::boost::parameter::aux::tag_keyword_arg
241 >::type
242#if defined(BOOST_PARAMETER_CAN_USE_MP11)
243 , 0
244 >
245#else
246 >::type
247#endif
248 operator()(A0&& a0, Args&& ...args) const
249 {
250 typedef typename ::boost::parameter::aux::make_arg_list<
251 typename ::boost::parameter::aux
252 ::make_parameter_spec_items<parameter_spec,A0,Args...>::type
253 , deduced_list
254 , ::boost::parameter::aux::tag_keyword_arg
255 >::type list_error_pair;
256
257#if defined(BOOST_PARAMETER_CAN_USE_MP11)
258 using result_type = ::boost::mp11::mp_at_c<list_error_pair,0>;
259
260 using error = ::boost::mp11::mp_at_c<list_error_pair,1>;
261#else
262 typedef typename ::boost::mpl
263 ::first<list_error_pair>::type result_type;
264
265 typedef typename ::boost::mpl
266 ::second<list_error_pair>::type error;
267#endif
268
269 error();
270
271 return ::boost::parameter::aux
272 ::arg_list_factory<result_type,A0,Args...>::reverse(
273 ::std::forward<A0>(a0)
274 , ::std::forward<Args>(args)...
275 );
276 }
277 };
278}} // namespace boost::parameter
279
280#else // !defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING)
281
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>
293
294#if ( \
295 BOOST_PARAMETER_EXPONENTIAL_OVERLOAD_THRESHOLD_ARITY < \
296 BOOST_PARAMETER_MAX_ARITY \
297 )
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>
306#endif
307
308#if !defined(BOOST_NO_SFINAE) && \
309 !BOOST_WORKAROUND(BOOST_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>
315#endif
316
317#if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564))
318#include <boost/preprocessor/repetition/enum_params.hpp>
319#else
320#include <boost/preprocessor/repetition/enum_binary_params.hpp>
321#endif
322
323#include <boost/parameter/aux_/preprocessor/no_perfect_forwarding_begin.hpp>
324
325namespace boost { namespace parameter {
326
327 template <
328 typename PS0
329 , BOOST_PP_ENUM_SHIFTED(
330 BOOST_PARAMETER_MAX_ARITY
331 , BOOST_PARAMETER_template_args
332 , PS
333 )
334 >
335 struct parameters
336 {
337 typedef typename BOOST_PARAMETER_build_deduced_list(
338 BOOST_PARAMETER_MAX_ARITY
339 , ::boost::parameter::aux::make_deduced_items
340 , PS
341 )::type deduced_list;
342
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(BOOST_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>
352 struct match_base
353 : ::boost::mpl::if_<
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_
359 // ...> >
360 typename BOOST_PP_REPEAT(
361 BOOST_PARAMETER_MAX_ARITY
362 , BOOST_PARAMETER_satisfies_begin
363 , PS
364 )
365 ::boost::is_same<
366 typename ::boost::mpl
367 ::second<ArgumentPackAndError>::type
368 , ::boost::parameter::void_
369 >
370 BOOST_PP_REPEAT(
371 BOOST_PARAMETER_MAX_ARITY
372 , BOOST_PARAMETER_satisfies_end
373 , ::boost::mpl::false_
374 )::type
375 , ::boost::mpl::identity<
376 ::boost::parameter::parameters<
377 BOOST_PP_ENUM_PARAMS(BOOST_PARAMETER_MAX_ARITY, PS)
378 >
379 >
380 , ::boost::parameter::void_
381 >
382 {
383 };
384#endif // SFINAE enabled, not Borland
385
386 // Specializations are to be used as an optional argument
387 // to eliminate overloads via SFINAE.
388 template <
389#if BOOST_WORKAROUND(BOOST_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)
394#else
395 BOOST_PP_ENUM_BINARY_PARAMS(
396 BOOST_PARAMETER_MAX_ARITY
397 , typename A
398 , = ::boost::parameter::void_ BOOST_PP_INTERCEPT
399 )
400#endif
401 >
402 struct match
403#if !defined(BOOST_NO_SFINAE) && \
404 !BOOST_WORKAROUND(BOOST_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
412 , PS
413 , A
414 )::type
415 , deduced_list
416 , ::boost::parameter::aux::tag_keyword_arg
417 // Don't emit errors when doing SFINAE.
418 , ::boost::mpl::false_
419 >::type
420 >::type
421 {
422 };
423#else
424 {
425 typedef ::boost::parameter::parameters<
426 BOOST_PP_ENUM_PARAMS(BOOST_PARAMETER_MAX_ARITY, PS)
427 > type;
428 };
429#endif // SFINAE enabled, not Borland
430
431 // Metafunction that returns an ArgumentPack.
432
433 // TODO, bind has to instantiate the error type in the result
434 // of make_arg_list.
435
436 template <
437#if BOOST_WORKAROUND(BOOST_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)
442#else
443 BOOST_PP_ENUM_BINARY_PARAMS(
444 BOOST_PARAMETER_MAX_ARITY
445 , typename A
446 , = ::boost::parameter::void_ BOOST_PP_INTERCEPT
447 )
448#endif
449 >
450 struct bind
451 {
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
456 , PS
457 , A
458 )::type
459 , deduced_list
460 , ::boost::parameter::aux::tag_template_keyword_arg
461 >::type result;
462
463 typedef typename ::boost::mpl::first<result>::type type;
464 };
465
466 BOOST_PP_REPEAT(
467 BOOST_PARAMETER_MAX_ARITY
468 , BOOST_PARAMETER_forward_typedef
469 , (PS)(parameter_spec)
470 )
471
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.
475 //
476 // !!!NOTE!!!
477 //
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
481 {
482 return ::boost::parameter::aux::empty_arg_list();
483 }
484
485#if (0 < BOOST_PARAMETER_EXPONENTIAL_OVERLOAD_THRESHOLD_ARITY)
486 BOOST_PP_REPEAT(
487 BOOST_PP_MIN(
488 BOOST_PP_INC(BOOST_PARAMETER_MAX_ARITY)
489 , BOOST_PARAMETER_EXPONENTIAL_OVERLOAD_THRESHOLD_ARITY
490 )
491 , BOOST_PARAMETER_AUX_PP_BINARY_SEQ_FOR_EACH_Z
492 , (BOOST_PARAMETER_function_call_op_overload_R)(_)
493 )
494#if ( \
495 BOOST_PARAMETER_EXPONENTIAL_OVERLOAD_THRESHOLD_ARITY < \
496 BOOST_PARAMETER_MAX_ARITY \
497 )
498#define BOOST_PP_ITERATION_PARAMS_1 \
499 (3,( \
500 BOOST_PARAMETER_EXPONENTIAL_OVERLOAD_THRESHOLD_ARITY \
501 , BOOST_PARAMETER_MAX_ARITY \
502 , <boost/parameter/aux_/preprocessor/overloads.hpp> \
503 ))
504#include BOOST_PP_ITERATE()
505#endif
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<
511 PS0,A0
512 >
513 , deduced_list
514 , ::boost::parameter::aux::tag_keyword_arg_ref
515 >::type
516 >::type
517 operator()(A0& a0) const
518 {
519 typedef typename ::boost::parameter::aux::make_arg_list<
520 ::boost::parameter::aux::item<
521 PS0,A0
522 >
523 , deduced_list
524 , ::boost::parameter::aux::tag_keyword_arg_ref
525 >::type result;
526
527 typedef typename ::boost::mpl::first<result>::type result_type;
528 typedef typename ::boost::mpl::second<result>::type error;
529 error();
530
531 return result_type(
532 a0
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
537 )
538 );
539 }
540
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<
545 PS0,A0
546 , ::boost::parameter::aux::item<
547 PS1,A1
548 >
549 >
550 , deduced_list
551 , ::boost::parameter::aux::tag_keyword_arg_ref
552 >::type
553 >::type
554 operator()(A0& a0, A1& a1) const
555 {
556 typedef typename ::boost::parameter::aux::make_arg_list<
557 ::boost::parameter::aux::item<
558 PS0,A0
559 , ::boost::parameter::aux::item<
560 PS1,A1
561 >
562 >
563 , deduced_list
564 , ::boost::parameter::aux::tag_keyword_arg
565 >::type result;
566
567 typedef typename ::boost::mpl::first<result>::type result_type;
568 typedef typename ::boost::mpl::second<result>::type error;
569 error();
570
571 return result_type(
572 a1
573 , a0
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
578 )
579 );
580 }
581
582#if (2 < BOOST_PARAMETER_MAX_ARITY)
583 // Higher arities are handled by the preprocessor
584#define BOOST_PP_ITERATION_PARAMS_1 \
585 (3,( \
586 3 \
587 , BOOST_PARAMETER_MAX_ARITY \
588 , <boost/parameter/aux_/preprocessor/overloads.hpp> \
589 ))
590#include BOOST_PP_ITERATE()
591#endif
592#endif // exponential overloads
593 };
594}} // namespace boost::parameter
595
596#include <boost/parameter/aux_/preprocessor/no_perfect_forwarding_end.hpp>
597
598#endif // BOOST_PARAMETER_HAS_PERFECT_FORWARDING
599#endif // include guard
600
601

source code of boost/libs/parameter/include/boost/parameter/parameters.hpp