1// Copyright Daniel Wallin, David Abrahams 2005.
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_PARAMETER_AUX_ARG_LIST_HPP
8#define BOOST_PARAMETER_AUX_ARG_LIST_HPP
9
10namespace boost { namespace parameter { namespace aux {
11
12 //
13 // Structures used to build the tuple of actual arguments. The tuple is a
14 // nested cons-style list of arg_list specializations terminated by an
15 // empty_arg_list.
16 //
17 // Each specialization of arg_list is derived from its successor in the
18 // list type. This feature is used along with using declarations to build
19 // member function overload sets that can match against keywords.
20 //
21
22 // MPL sequence support
23 struct arg_list_tag;
24
25 template <typename T>
26 struct get_reference
27 {
28 typedef typename T::reference type;
29 };
30}}} // namespace boost::parameter::aux
31
32#include <boost/parameter/config.hpp>
33
34#if defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING)
35
36namespace boost { namespace parameter { namespace aux {
37
38 struct value_type_is_void
39 {
40 };
41
42 struct value_type_is_not_void
43 {
44 };
45}}} // namespace boost::parameter::aux
46
47#endif
48
49#include <boost/parameter/aux_/void.hpp>
50#include <boost/parameter/aux_/yesno.hpp>
51#include <boost/parameter/aux_/result_of0.hpp>
52#include <boost/parameter/aux_/default.hpp>
53
54#if defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING)
55#include <utility>
56
57#if defined(BOOST_PARAMETER_CAN_USE_MP11)
58#include <boost/mp11/integral.hpp>
59#include <boost/mp11/list.hpp>
60#include <boost/mp11/utility.hpp>
61#include <type_traits>
62#endif
63
64namespace boost { namespace parameter { namespace aux {
65
66 // Terminates arg_list<> and represents an empty list. Since this is just
67 // the terminating case, you might want to look at arg_list first to get a
68 // feel for what's really happening here.
69 struct empty_arg_list
70 {
71 struct tagged_arg
72 {
73 typedef ::boost::parameter::void_ value_type;
74 };
75
76 // Variadic constructor also serves as default constructor.
77 template <typename ...Args>
78 inline BOOST_CONSTEXPR empty_arg_list(Args&&...)
79 {
80 }
81
82 // A metafunction class that, given a keyword and a default type,
83 // returns the appropriate result type for a keyword lookup given
84 // that default.
85 struct binding
86 {
87 template <typename KW, typename Default, typename Reference>
88 struct apply
89 {
90 typedef Default type;
91 };
92
93#if defined(BOOST_PARAMETER_CAN_USE_MP11)
94 template <typename KW, typename Default, typename Reference>
95 using fn = Default;
96#endif
97 };
98
99 // Terminator for has_key, indicating that the keyword is unique.
100 template <typename KW>
101 static ::boost::parameter::aux::no_tag has_key(KW*);
102
103 // If either of these operators are called, it means there is no
104 // argument in the list that matches the supplied keyword. Just
105 // return the default value.
106 template <typename K, typename Default>
107 inline BOOST_CONSTEXPR Default&
108 operator[](::boost::parameter::aux::default_<K,Default> x) const
109 {
110 return x.value;
111 }
112
113 template <typename K, typename Default>
114 inline BOOST_CONSTEXPR Default&&
115 operator[](::boost::parameter::aux::default_r_<K,Default> x) const
116 {
117 return ::std::forward<Default>(x.value);
118 }
119
120 // If this operator is called, it means there is no argument in the
121 // list that matches the supplied keyword. Just evaluate and return
122 // the default value.
123 template <typename K, typename F>
124 inline BOOST_CONSTEXPR
125 typename ::boost::parameter::aux::result_of0<F>::type
126 operator[](BOOST_PARAMETER_lazy_default_fallback<K,F> x) const
127 {
128 return x.compute_default();
129 }
130
131 // No argument corresponding to ParameterRequirements::key_type
132 // was found if we match this overload, so unless that parameter
133 // has a default, we indicate that the actual arguments don't
134 // match the function's requirements.
135 template <typename ParameterRequirements, typename ArgPack>
136 static typename ParameterRequirements::has_default
137 satisfies(ParameterRequirements*, ArgPack*);
138
139 // MPL sequence support
140 typedef ::boost::parameter::aux::empty_arg_list type; // convenience
141 // For dispatching to sequence intrinsics
142 typedef ::boost::parameter::aux::arg_list_tag tag;
143 };
144}}} // namespace boost::parameter::aux
145
146#include <boost/parameter/aux_/preprocessor/nullptr.hpp>
147#include <boost/parameter/aux_/yesno.hpp>
148#include <boost/parameter/aux_/is_maybe.hpp>
149#include <boost/parameter/aux_/tagged_argument_fwd.hpp>
150#include <boost/parameter/aux_/parameter_requirements.hpp>
151#include <boost/parameter/aux_/augment_predicate.hpp>
152#include <boost/parameter/keyword_fwd.hpp>
153#include <boost/mpl/bool.hpp>
154#include <boost/mpl/if.hpp>
155#include <boost/mpl/eval_if.hpp>
156#include <boost/mpl/apply_wrap.hpp>
157#include <boost/mpl/assert.hpp>
158#include <boost/type_traits/is_same.hpp>
159#include <boost/core/enable_if.hpp>
160
161namespace boost { namespace parameter { namespace aux {
162
163 // A tuple of tagged arguments, terminated with empty_arg_list. Every
164 // TaggedArg is an instance of tagged_argument<> or
165 // tagged_argument_rref<>.
166 template <
167 typename TaggedArg
168 , typename Next = ::boost::parameter::aux::empty_arg_list
169#if defined(BOOST_PARAMETER_CAN_USE_MP11)
170 , typename EmitsErrors = ::boost::mp11::mp_true
171#else
172 , typename EmitsErrors = ::boost::mpl::true_
173#endif
174 >
175 class arg_list : public Next
176 {
177#if defined(BOOST_PARAMETER_CAN_USE_MP11)
178 using _holds_maybe = typename ::boost::parameter::aux
179 ::is_maybe<typename TaggedArg::value_type>::type;
180#else
181 typedef typename ::boost::parameter::aux
182 ::is_maybe<typename TaggedArg::value_type>::type _holds_maybe;
183#endif
184
185 TaggedArg arg; // Stores the argument
186
187 public:
188 typedef TaggedArg tagged_arg;
189 typedef ::boost::parameter::aux::arg_list<TaggedArg,Next> self;
190 typedef typename TaggedArg::key_type key_type;
191
192#if defined(BOOST_PARAMETER_CAN_USE_MP11)
193 using reference = typename ::boost::mp11::mp_if<
194 _holds_maybe
195 , ::boost::parameter::aux
196 ::get_reference<typename TaggedArg::value_type>
197 , ::boost::parameter::aux::get_reference<TaggedArg>
198 >::type;
199
200 using value_type = ::boost::mp11
201 ::mp_if<_holds_maybe,reference,typename TaggedArg::value_type>;
202#else // !defined(BOOST_PARAMETER_CAN_USE_MP11)
203 typedef typename ::boost::mpl::eval_if<
204 _holds_maybe
205 , ::boost::parameter::aux
206 ::get_reference<typename TaggedArg::value_type>
207 , ::boost::parameter::aux::get_reference<TaggedArg>
208 >::type reference;
209
210 typedef typename ::boost::mpl::if_<
211 _holds_maybe
212 , reference
213 , typename TaggedArg::value_type
214 >::type value_type;
215#endif // BOOST_PARAMETER_CAN_USE_MP11
216
217 // Create a new list by prepending arg to a copy of tail. Used when
218 // incrementally building this structure with the comma operator.
219 inline BOOST_CONSTEXPR arg_list(
220 TaggedArg const& head
221 , Next const& tail
222 ) : Next(tail), arg(head)
223 {
224 }
225
226 // Store the arguments in successive nodes of this list.
227 // Use tag dispatching to determine whether to forward all arguments
228 // to the Next constructor, or store the first argument and forward
229 // the rest. -- Cromwell D. Enage
230 template <typename A0>
231 inline BOOST_CONSTEXPR arg_list(
232 ::boost::parameter::aux::value_type_is_not_void
233 , A0&& a0
234 ) : Next(
235#if defined(BOOST_PARAMETER_CAN_USE_MP11)
236 ::boost::mp11::mp_if<
237 ::std::is_same<
238#else
239 typename ::boost::mpl::if_<
240 ::boost::is_same<
241#endif
242 typename Next::tagged_arg::value_type
243 , ::boost::parameter::void_
244 >
245 , ::boost::parameter::aux::value_type_is_void
246 , ::boost::parameter::aux::value_type_is_not_void
247#if defined(BOOST_PARAMETER_CAN_USE_MP11)
248 >()
249#else
250 >::type()
251#endif
252 )
253 , arg(::std::forward<A0>(a0))
254 {
255 }
256
257 template <typename ...Args>
258 inline BOOST_CONSTEXPR arg_list(
259 ::boost::parameter::aux::value_type_is_void
260 , Args&&... args
261 ) : Next(
262#if defined(BOOST_PARAMETER_CAN_USE_MP11)
263 ::boost::mp11::mp_if<
264 ::std::is_same<
265#else
266 typename ::boost::mpl::if_<
267 ::boost::is_same<
268#endif
269 typename Next::tagged_arg::value_type
270 , ::boost::parameter::void_
271 >
272 , ::boost::parameter::aux::value_type_is_void
273 , ::boost::parameter::aux::value_type_is_not_void
274#if defined(BOOST_PARAMETER_CAN_USE_MP11)
275 >()
276#else
277 >::type()
278#endif
279 , ::std::forward<Args>(args)...
280 )
281 , arg(::boost::parameter::aux::void_reference())
282 {
283 }
284
285 template <typename A0, typename A1, typename ...Args>
286 inline BOOST_CONSTEXPR arg_list(
287 ::boost::parameter::aux::value_type_is_not_void
288 , A0&& a0
289 , A1&& a1
290 , Args&&... args
291 ) : Next(
292#if defined(BOOST_PARAMETER_CAN_USE_MP11)
293 ::boost::mp11::mp_if<
294 ::std::is_same<
295#else
296 typename ::boost::mpl::if_<
297 ::boost::is_same<
298#endif
299 typename Next::tagged_arg::value_type
300 , ::boost::parameter::void_
301 >
302 , ::boost::parameter::aux::value_type_is_void
303 , ::boost::parameter::aux::value_type_is_not_void
304#if defined(BOOST_PARAMETER_CAN_USE_MP11)
305 >()
306#else
307 >::type()
308#endif
309 , ::std::forward<A1>(a1)
310 , ::std::forward<Args>(args)...
311 )
312 , arg(::std::forward<A0>(a0))
313 {
314 }
315
316 // A metafunction class that, given a keyword and a default type,
317 // returns the appropriate result type for a keyword lookup given
318 // that default.
319 struct binding
320 {
321 typedef typename Next::binding next_binding;
322
323 template <typename KW, typename Default, typename Reference>
324 struct apply
325 {
326 typedef typename ::boost::mpl::eval_if<
327 ::boost::is_same<KW,key_type>
328 , ::boost::mpl::if_<Reference,reference,value_type>
329 , ::boost::mpl
330 ::apply_wrap3<next_binding,KW,Default,Reference>
331 >::type type;
332 };
333
334#if defined(BOOST_PARAMETER_CAN_USE_MP11)
335 template <typename KW, typename Default, typename Reference>
336 using fn = ::boost::mp11::mp_if<
337 ::std::is_same<KW,key_type>
338 , ::boost::mp11::mp_if<Reference,reference,value_type>
339 , ::boost::mp11::mp_apply_q<
340 next_binding
341 , ::boost::mp11::mp_list<KW,Default,Reference>
342 >
343 >;
344#endif
345 };
346
347 // Overload for key_type, so the assert below will fire
348 // if the same keyword is used again.
349 static ::boost::parameter::aux::yes_tag has_key(key_type*);
350 using Next::has_key;
351
352 private:
353#if defined(BOOST_PARAMETER_CAN_USE_MP11)
354 using _has_unique_key = ::boost::mp11::mp_bool<
355#else
356 typedef ::boost::mpl::bool_<
357#endif
358 sizeof(
359 Next::has_key(
360 static_cast<key_type*>(BOOST_PARAMETER_AUX_PP_NULLPTR)
361 )
362 ) == sizeof(::boost::parameter::aux::no_tag)
363#if defined(BOOST_PARAMETER_CAN_USE_MP11)
364 >;
365#else
366 > _has_unique_key;
367#endif
368
369#if defined(BOOST_PARAMETER_CAN_USE_MP11)
370 static_assert(
371 !(EmitsErrors::value) || (_has_unique_key::value)
372 , "duplicate keyword"
373 );
374#else
375 BOOST_MPL_ASSERT_MSG(
376 !(EmitsErrors::value) || (_has_unique_key::value)
377 , duplicate_keyword
378 , (key_type)
379 );
380#endif
381
382 //
383 // Begin implementation of indexing operators
384 // for looking up specific arguments by name.
385 //
386
387 // Helpers that handle the case when TaggedArg is empty<T>.
388 template <typename D>
389 inline BOOST_CONSTEXPR reference
390#if defined(BOOST_PARAMETER_CAN_USE_MP11)
391 get_default(D const&, ::boost::mp11::mp_false) const
392#else
393 get_default(D const&, ::boost::mpl::false_) const
394#endif
395 {
396 return this->arg.get_value();
397 }
398
399 template <typename D>
400 inline BOOST_CONSTEXPR reference
401#if defined(BOOST_PARAMETER_CAN_USE_MP11)
402 get_default(D const& d, ::boost::mp11::mp_true) const
403#else
404 get_default(D const& d, ::boost::mpl::true_) const
405#endif
406 {
407 return (
408 this->arg.get_value()
409 ? this->arg.get_value().get()
410 : this->arg.get_value().construct(d.value)
411 );
412 }
413
414 public:
415 inline BOOST_CONSTEXPR reference
416 operator[](::boost::parameter::keyword<key_type> const&) const
417 {
418#if !defined(BOOST_NO_CXX14_CONSTEXPR)
419#if defined(BOOST_PARAMETER_CAN_USE_MP11)
420 static_assert(!_holds_maybe::value, "must not hold maybe");
421#elif !( \
422 BOOST_WORKAROUND(BOOST_GCC, >= 40700) && \
423 BOOST_WORKAROUND(BOOST_GCC, < 40900) \
424 ) && !BOOST_WORKAROUND(BOOST_GCC, >= 50000) && \
425 !BOOST_WORKAROUND(BOOST_MSVC, < 1910)
426 BOOST_MPL_ASSERT_NOT((_holds_maybe));
427#endif
428#endif
429 return this->arg.get_value();
430 }
431
432 template <typename Default>
433 inline BOOST_CONSTEXPR reference
434 operator[](
435 ::boost::parameter::aux::default_<key_type,Default> const& d
436 ) const
437 {
438 return this->get_default(d, _holds_maybe());
439 }
440
441 template <typename Default>
442 inline BOOST_CONSTEXPR reference
443 operator[](
444 ::boost::parameter::aux::default_r_<key_type,Default> const& d
445 ) const
446 {
447 return this->get_default(d, _holds_maybe());
448 }
449
450 template <typename Default>
451 inline BOOST_CONSTEXPR reference
452 operator[](
453 BOOST_PARAMETER_lazy_default_fallback<key_type,Default> const&
454 ) const
455 {
456#if !defined(BOOST_NO_CXX14_CONSTEXPR)
457#if defined(BOOST_PARAMETER_CAN_USE_MP11)
458 static_assert(!_holds_maybe::value, "must not hold maybe");
459#elif !( \
460 BOOST_WORKAROUND(BOOST_GCC, >= 40700) && \
461 BOOST_WORKAROUND(BOOST_GCC, < 40900) \
462 ) && !BOOST_WORKAROUND(BOOST_GCC, >= 50000) && \
463 !BOOST_WORKAROUND(BOOST_MSVC, < 1910)
464 BOOST_MPL_ASSERT_NOT((_holds_maybe));
465#endif
466#endif
467 return this->arg.get_value();
468 }
469
470 // Builds an overload set including operator[]s defined
471 // in base classes.
472 using Next::operator[];
473
474 //
475 // End of indexing support
476 //
477
478 // For parameter_requirements matching this node's key_type, return
479 // a bool constant wrapper indicating whether the requirements are
480 // satisfied by TaggedArg. Used only for compile-time computation
481 // and never really called, so a declaration is enough.
482 template <typename HasDefault, typename Predicate, typename ArgPack>
483 static typename ::boost::lazy_enable_if<
484#if defined(BOOST_PARAMETER_CAN_USE_MP11)
485 ::boost::mp11::mp_if<
486 EmitsErrors
487 , ::boost::mp11::mp_true
488 , _has_unique_key
489 >
490 , ::boost::parameter::aux::augment_predicate_mp11<
491#else
492 typename ::boost::mpl::if_<
493 EmitsErrors
494 , ::boost::mpl::true_
495 , _has_unique_key
496 >::type
497 , ::boost::parameter::aux::augment_predicate<
498#endif
499 Predicate
500 , reference
501 , key_type
502 , value_type
503 , ArgPack
504 >
505 >::type
506 satisfies(
507 ::boost::parameter::aux::parameter_requirements<
508 key_type
509 , Predicate
510 , HasDefault
511 >*
512 , ArgPack*
513 );
514
515 // Builds an overload set including satisfies functions defined
516 // in base classes.
517 using Next::satisfies;
518
519 // Comma operator to compose argument list without using parameters<>.
520 // Useful for argument lists with undetermined length.
521 template <typename KW, typename T2>
522 inline BOOST_CONSTEXPR ::boost::parameter::aux::arg_list<
523 ::boost::parameter::aux::tagged_argument<KW,T2>
524 , self
525 >
526 operator,(
527 ::boost::parameter::aux::tagged_argument<KW,T2> const& x
528 ) const
529 {
530 return ::boost::parameter::aux::arg_list<
531 ::boost::parameter::aux::tagged_argument<KW,T2>
532 , self
533 >(x, *this);
534 }
535
536 template <typename KW, typename T2>
537 inline BOOST_CONSTEXPR ::boost::parameter::aux::arg_list<
538 ::boost::parameter::aux::tagged_argument_rref<KW,T2>
539 , self
540 >
541 operator,(
542 ::boost::parameter::aux::tagged_argument_rref<KW,T2> const& x
543 ) const
544 {
545 return ::boost::parameter::aux::arg_list<
546 ::boost::parameter::aux::tagged_argument_rref<KW,T2>
547 , self
548 >(x, *this);
549 }
550
551 // MPL sequence support
552 typedef self type; // Convenience for users
553 typedef Next tail_type; // For the benefit of iterators
554 // For dispatching to sequence intrinsics
555 typedef ::boost::parameter::aux::arg_list_tag tag;
556 };
557}}} // namespace boost::parameter::aux
558
559#else // !defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING)
560
561#include <boost/preprocessor/repetition/enum_params.hpp>
562#include <boost/preprocessor/facilities/intercept.hpp>
563
564namespace boost { namespace parameter { namespace aux {
565
566 // Terminates arg_list<> and represents an empty list. Since this is just
567 // the terminating case, you might want to look at arg_list first to get a
568 // feel for what's really happening here.
569 struct empty_arg_list
570 {
571 inline BOOST_CONSTEXPR empty_arg_list()
572 {
573 }
574
575 // Constructor taking BOOST_PARAMETER_COMPOSE_MAX_ARITY empty_arg_list
576 // arguments; this makes initialization.
577 inline BOOST_CONSTEXPR empty_arg_list(
578 BOOST_PP_ENUM_PARAMS(
579 BOOST_PARAMETER_COMPOSE_MAX_ARITY
580 , ::boost::parameter::void_ BOOST_PP_INTERCEPT
581 )
582 )
583 {
584 }
585
586 // A metafunction class that, given a keyword and a default type,
587 // returns the appropriate result type for a keyword lookup given
588 // that default.
589 struct binding
590 {
591 template <typename KW, typename Default, typename Reference>
592 struct apply
593 {
594 typedef Default type;
595 };
596 };
597
598 // Terminator for has_key, indicating that the keyword is unique.
599 template <typename KW>
600 static ::boost::parameter::aux::no_tag has_key(KW*);
601
602#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
603 // The overload set technique doesn't work with these older compilers,
604 // so they need some explicit handholding.
605
606 // A metafunction class that, given a keyword, returns the type of the
607 // base sublist whose get() function can produce the value for that key.
608 struct key_owner
609 {
610 template <typename KW>
611 struct apply
612 {
613 typedef ::boost::parameter::aux::empty_arg_list type;
614 };
615 };
616#endif // Borland workarounds needed
617
618 // If either of these operators are called, it means there is no
619 // argument in the list that matches the supplied keyword. Just
620 // return the default value.
621 template <typename K, typename Default>
622 inline BOOST_CONSTEXPR Default&
623 operator[](::boost::parameter::aux::default_<K,Default> x) const
624 {
625 return x.value;
626 }
627
628 // If this operator is called, it means there is no argument in the
629 // list that matches the supplied keyword. Just evaluate and return
630 // the default value.
631 template <typename K, typename F>
632 inline BOOST_CONSTEXPR
633 typename ::boost::parameter::aux::result_of0<F>::type
634 operator[](BOOST_PARAMETER_lazy_default_fallback<K,F> x) const
635 {
636 return x.compute_default();
637 }
638
639 // No argument corresponding to ParameterRequirements::key_type
640 // was found if we match this overload, so unless that parameter
641 // has a default, we indicate that the actual arguments don't
642 // match the function's requirements.
643 template <typename ParameterRequirements, typename ArgPack>
644 static typename ParameterRequirements::has_default
645 satisfies(ParameterRequirements*, ArgPack*);
646
647 // MPL sequence support
648 typedef ::boost::parameter::aux::empty_arg_list type; // convenience
649 // For dispatching to sequence intrinsics
650 typedef ::boost::parameter::aux::arg_list_tag tag;
651 };
652}}} // namespace boost::parameter::aux
653
654#include <boost/parameter/aux_/yesno.hpp>
655#include <boost/parameter/aux_/is_maybe.hpp>
656#include <boost/parameter/aux_/tagged_argument_fwd.hpp>
657#include <boost/parameter/aux_/parameter_requirements.hpp>
658#include <boost/parameter/aux_/augment_predicate.hpp>
659#include <boost/parameter/keyword_fwd.hpp>
660#include <boost/mpl/bool.hpp>
661#include <boost/mpl/if.hpp>
662#include <boost/mpl/eval_if.hpp>
663#include <boost/mpl/apply_wrap.hpp>
664#include <boost/mpl/assert.hpp>
665#include <boost/type_traits/is_same.hpp>
666#include <boost/preprocessor/repetition/enum_binary_params.hpp>
667#include <boost/preprocessor/repetition/enum_shifted_params.hpp>
668
669#if !defined(BOOST_NO_SFINAE) && !BOOST_WORKAROUND(BOOST_MSVC, < 1800)
670#include <boost/core/enable_if.hpp>
671#endif
672
673#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
674#include <boost/parameter/aux_/preprocessor/nullptr.hpp>
675#endif
676
677namespace boost { namespace parameter { namespace aux {
678
679 // A tuple of tagged arguments, terminated with empty_arg_list. Every
680 // TaggedArg is an instance of tagged_argument<>.
681 template <
682 typename TaggedArg
683 , typename Next = ::boost::parameter::aux::empty_arg_list
684 , typename EmitsErrors = ::boost::mpl::true_
685 >
686 class arg_list : public Next
687 {
688 typedef typename ::boost::parameter::aux
689 ::is_maybe<typename TaggedArg::value_type>::type _holds_maybe;
690
691 TaggedArg arg; // Stores the argument
692
693 public:
694 typedef TaggedArg tagged_arg;
695 typedef ::boost::parameter::aux::arg_list<TaggedArg,Next> self;
696 typedef typename TaggedArg::key_type key_type;
697
698 typedef typename ::boost::mpl::eval_if<
699 _holds_maybe
700 , ::boost::parameter::aux
701 ::get_reference<typename TaggedArg::value_type>
702 , ::boost::parameter::aux::get_reference<TaggedArg>
703 >::type reference;
704
705 typedef typename ::boost::mpl::if_<
706 _holds_maybe
707 , reference
708 , typename TaggedArg::value_type
709 >::type value_type;
710
711 // Create a new list by prepending arg to a copy of tail. Used when
712 // incrementally building this structure with the comma operator.
713 inline BOOST_CONSTEXPR arg_list(
714 TaggedArg const& head
715 , Next const& tail
716 ) : Next(tail), arg(head)
717 {
718 }
719
720 // Store the arguments in successive nodes of this list.
721 template <
722 // typename A0, typename A1, ...
723 BOOST_PP_ENUM_PARAMS(
724 BOOST_PARAMETER_COMPOSE_MAX_ARITY
725 , typename A
726 )
727 >
728 inline BOOST_CONSTEXPR arg_list(
729 // A0& a0, A1& a1, ...
730 BOOST_PP_ENUM_BINARY_PARAMS(
731 BOOST_PARAMETER_COMPOSE_MAX_ARITY
732 , A
733 , & a
734 )
735 ) : Next(
736 // a1, a2, ...
737 BOOST_PP_ENUM_SHIFTED_PARAMS(
738 BOOST_PARAMETER_COMPOSE_MAX_ARITY
739 , a
740 )
741 , ::boost::parameter::aux::void_reference()
742 )
743 , arg(a0)
744 {
745 }
746
747 // A metafunction class that, given a keyword and a default type,
748 // returns the appropriate result type for a keyword lookup given
749 // that default.
750 struct binding
751 {
752 typedef typename Next::binding next_binding;
753
754 template <typename KW, typename Default, typename Reference>
755 struct apply
756 {
757 typedef typename ::boost::mpl::eval_if<
758 ::boost::is_same<KW,key_type>
759 , ::boost::mpl::if_<Reference,reference,value_type>
760 , ::boost::mpl::apply_wrap3<
761 next_binding
762 , KW
763 , Default
764 , Reference
765 >
766 >::type type;
767 };
768 };
769
770#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
771 // Overload for key_type, so the assert below will fire
772 // if the same keyword is used again.
773 static ::boost::parameter::aux::yes_tag has_key(key_type*);
774 using Next::has_key;
775
776 private:
777#if defined(BOOST_NO_SFINAE) || BOOST_WORKAROUND(BOOST_MSVC, < 1800)
778 BOOST_MPL_ASSERT_MSG(
779 sizeof(
780 Next::has_key(
781 static_cast<key_type*>(BOOST_PARAMETER_AUX_PP_NULLPTR)
782 )
783 ) == sizeof(::boost::parameter::aux::no_tag)
784 , duplicate_keyword
785 , (key_type)
786 );
787#else
788 typedef ::boost::mpl::bool_<
789 sizeof(
790 Next::has_key(
791 static_cast<key_type*>(BOOST_PARAMETER_AUX_PP_NULLPTR)
792 )
793 ) == sizeof(::boost::parameter::aux::no_tag)
794 > _has_unique_key;
795
796 BOOST_MPL_ASSERT_MSG(
797 !(EmitsErrors::value) || (_has_unique_key::value)
798 , duplicate_keyword
799 , (key_type)
800 );
801#endif // SFINAE/MSVC workarounds needed
802#endif // Borland workarounds not needed
803
804 private:
805 //
806 // Begin implementation of indexing operators
807 // for looking up specific arguments by name.
808 //
809
810 // Helpers that handle the case when TaggedArg is empty<T>.
811 template <typename D>
812 inline BOOST_CONSTEXPR reference
813 get_default(D const&, ::boost::mpl::false_) const
814 {
815 return this->arg.get_value();
816 }
817
818 template <typename D>
819 inline BOOST_CONSTEXPR reference
820 get_default(D const& d, ::boost::mpl::true_) const
821 {
822 return (
823 this->arg.get_value()
824 ? this->arg.get_value().get()
825 : this->arg.get_value().construct(d.value)
826 );
827 }
828
829 public:
830#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
831 // These older compilers don't support the overload set creation
832 // idiom well, so we need to do all the return type calculation
833 // for the compiler and dispatch through an outer function template.
834
835 // A metafunction class that, given a keyword, returns the base
836 // sublist whose get() function can produce the value for that key.
837 struct key_owner
838 {
839 typedef typename Next::key_owner next_key_owner;
840
841 template <typename KW>
842 struct apply
843 {
844 typedef typename ::boost::mpl::eval_if<
845 ::boost::is_same<KW,key_type>
846 , ::boost::mpl::identity<
847 ::boost::parameter::aux::arg_list<TaggedArg,Next>
848 >
849 , ::boost::mpl::apply_wrap1<next_key_owner,KW>
850 >::type type;
851 };
852 };
853
854 // Outer indexing operators that dispatch to the right node's
855 // get() function.
856 template <typename KW>
857 inline BOOST_CONSTEXPR typename ::boost::mpl::apply_wrap3<
858 binding
859 , KW
860 , ::boost::parameter::void_
861 , ::boost::mpl::true_
862 >::type
863 operator[](::boost::parameter::keyword<KW> const& x) const
864 {
865 typename ::boost::mpl::apply_wrap1<key_owner,KW>::type const&
866 sublist = *this;
867 return sublist.get(x);
868 }
869
870 template <typename KW, typename Default>
871 inline BOOST_CONSTEXPR typename ::boost::mpl::apply_wrap3<
872 binding
873 , KW
874 , Default&
875 , ::boost::mpl::true_
876 >::type
877 operator[](
878 ::boost::parameter::aux::default_<KW,Default> const& x
879 ) const
880 {
881 typename ::boost::mpl::apply_wrap1<key_owner,KW>::type const&
882 sublist = *this;
883 return sublist.get(x);
884 }
885
886 template <typename KW, typename F>
887 inline BOOST_CONSTEXPR typename ::boost::mpl::apply_wrap3<
888 binding
889 , KW
890 , typename ::boost::parameter::aux::result_of0<F>::type
891 , ::boost::mpl::true_
892 >::type
893 operator[](
894 BOOST_PARAMETER_lazy_default_fallback<KW,F> const& x
895 ) const
896 {
897 typename ::boost::mpl::apply_wrap1<key_owner,KW>::type const&
898 sublist = *this;
899 return sublist.get(x);
900 }
901
902 // These just return the stored value; when empty_arg_list is reached,
903 // indicating no matching argument was passed, the default is
904 // returned, or if no default_ or lazy_default was passed, compilation
905 // fails.
906 inline BOOST_CONSTEXPR reference
907 get(::boost::parameter::keyword<key_type> const&) const
908 {
909 BOOST_MPL_ASSERT_NOT((_holds_maybe));
910 return this->arg.get_value();
911 }
912
913 template <typename Default>
914 inline BOOST_CONSTEXPR reference
915 get(
916 ::boost::parameter::aux::default_<key_type,Default> const& d
917 ) const
918 {
919 return this->get_default(d, _holds_maybe());
920 }
921
922 template <typename Default>
923 inline BOOST_CONSTEXPR reference
924 get(
925 BOOST_PARAMETER_lazy_default_fallback<key_type,Default> const&
926 ) const
927 {
928 return this->arg.get_value();
929 }
930#else // !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
931 inline BOOST_CONSTEXPR reference
932 operator[](::boost::parameter::keyword<key_type> const&) const
933 {
934 BOOST_MPL_ASSERT_NOT((_holds_maybe));
935 return this->arg.get_value();
936 }
937
938 template <typename Default>
939 inline BOOST_CONSTEXPR reference
940 operator[](
941 ::boost::parameter::aux::default_<key_type,Default> const& d
942 ) const
943 {
944 return this->get_default(d, _holds_maybe());
945 }
946
947 template <typename Default>
948 inline BOOST_CONSTEXPR reference
949 operator[](
950 BOOST_PARAMETER_lazy_default_fallback<key_type,Default> const&
951 ) const
952 {
953 BOOST_MPL_ASSERT_NOT((_holds_maybe));
954 return this->arg.get_value();
955 }
956
957 // Builds an overload set including operator[]s defined
958 // in base classes.
959 using Next::operator[];
960
961 //
962 // End of indexing support
963 //
964
965 // For parameter_requirements matching this node's key_type, return
966 // a bool constant wrapper indicating whether the requirements are
967 // satisfied by TaggedArg. Used only for compile-time computation
968 // and never really called, so a declaration is enough.
969 template <typename HasDefault, typename Predicate, typename ArgPack>
970 static typename
971#if !defined(BOOST_NO_SFINAE) && !BOOST_WORKAROUND(BOOST_MSVC, < 1800)
972 ::boost::lazy_enable_if<
973 typename ::boost::mpl::if_<
974 EmitsErrors
975 , ::boost::mpl::true_
976 , _has_unique_key
977 >::type,
978#endif
979 ::boost::parameter::aux::augment_predicate<
980 Predicate
981 , reference
982 , key_type
983 , value_type
984 , ArgPack
985#if !defined(BOOST_NO_SFINAE) && !BOOST_WORKAROUND(BOOST_MSVC, < 1800)
986 >
987#endif
988 >::type
989 satisfies(
990 ::boost::parameter::aux::parameter_requirements<
991 key_type
992 , Predicate
993 , HasDefault
994 >*
995 , ArgPack*
996 );
997
998 // Builds an overload set including satisfies functions defined
999 // in base classes.
1000 using Next::satisfies;
1001#endif // Borland workarounds needed
1002
1003 // Comma operator to compose argument list without using parameters<>.
1004 // Useful for argument lists with undetermined length.
1005 template <typename KW, typename T2>
1006 inline BOOST_CONSTEXPR ::boost::parameter::aux::arg_list<
1007 ::boost::parameter::aux::tagged_argument<KW,T2>
1008 , self
1009 >
1010 operator,(
1011 ::boost::parameter::aux::tagged_argument<KW,T2> const& x
1012 ) const
1013 {
1014 return ::boost::parameter::aux::arg_list<
1015 ::boost::parameter::aux::tagged_argument<KW,T2>
1016 , self
1017 >(x, *this);
1018 }
1019
1020 // MPL sequence support
1021 typedef self type; // Convenience for users
1022 typedef Next tail_type; // For the benefit of iterators
1023 // For dispatching to sequence intrinsics
1024 typedef ::boost::parameter::aux::arg_list_tag tag;
1025 };
1026}}} // namespace boost::parameter::aux
1027
1028#endif // BOOST_PARAMETER_HAS_PERFECT_FORWARDING
1029
1030#if defined(BOOST_PARAMETER_CAN_USE_MP11)
1031
1032namespace boost { namespace parameter { namespace aux {
1033
1034 template <typename ...ArgTuples>
1035 struct arg_list_cons;
1036
1037 template <>
1038 struct arg_list_cons<>
1039 {
1040 using type = ::boost::parameter::aux::empty_arg_list;
1041 };
1042
1043 template <typename ArgTuple0, typename ...Tuples>
1044 struct arg_list_cons<ArgTuple0,Tuples...>
1045 {
1046 using type = ::boost::parameter::aux::arg_list<
1047 typename ArgTuple0::tagged_arg
1048 , typename ::boost::parameter::aux::arg_list_cons<Tuples...>::type
1049 , typename ArgTuple0::emits_errors
1050 >;
1051 };
1052
1053 template <
1054 typename Keyword
1055 , typename TaggedArg
1056 , typename EmitsErrors = ::boost::mp11::mp_true
1057 >
1058 struct flat_like_arg_tuple
1059 {
1060 using tagged_arg = TaggedArg;
1061 using emits_errors = EmitsErrors;
1062 };
1063
1064 template <typename ...ArgTuples>
1065 class flat_like_arg_list
1066 : public ::boost::parameter::aux::arg_list_cons<ArgTuples...>::type
1067 {
1068 using _base_type = typename ::boost::parameter::aux
1069 ::arg_list_cons<ArgTuples...>::type;
1070
1071 public:
1072 inline BOOST_CONSTEXPR flat_like_arg_list(
1073 typename _base_type::tagged_arg const& head
1074 , typename _base_type::tail_type const& tail
1075 ) : _base_type(head, tail)
1076 {
1077 }
1078
1079 template <typename ...Args>
1080 inline BOOST_CONSTEXPR flat_like_arg_list(Args&&... args)
1081 : _base_type(::std::forward<Args>(args)...)
1082 {
1083 }
1084
1085 using _base_type::operator[];
1086 using _base_type::satisfies;
1087
1088 // Comma operator to compose argument list without using parameters<>.
1089 // Useful for argument lists with undetermined length.
1090 template <typename TaggedArg>
1091 inline BOOST_CONSTEXPR ::boost::parameter::aux::flat_like_arg_list<
1092 ::boost::parameter::aux::flat_like_arg_tuple<
1093 typename TaggedArg::base_type::key_type
1094 , typename TaggedArg::base_type
1095 >
1096 , ArgTuples...
1097 >
1098 operator,(TaggedArg const& x) const
1099 {
1100 return ::boost::parameter::aux::flat_like_arg_list<
1101 ::boost::parameter::aux::flat_like_arg_tuple<
1102 typename TaggedArg::base_type::key_type
1103 , typename TaggedArg::base_type
1104 >
1105 , ArgTuples...
1106 >(
1107 static_cast<typename TaggedArg::base_type const&>(x)
1108 , static_cast<_base_type const&>(*this)
1109 );
1110 }
1111 };
1112
1113 template <>
1114 class flat_like_arg_list<>
1115 : public ::boost::parameter::aux::empty_arg_list
1116 {
1117 using _base_type = ::boost::parameter::aux::empty_arg_list;
1118
1119 public:
1120 template <typename ...Args>
1121 inline BOOST_CONSTEXPR flat_like_arg_list(Args&&... args)
1122 : _base_type(::std::forward<Args>(args)...)
1123 {
1124 }
1125
1126 using _base_type::operator[];
1127 using _base_type::satisfies;
1128
1129 // Comma operator to compose argument list without using parameters<>.
1130 // Useful for argument lists with undetermined length.
1131 template <typename TaggedArg>
1132 inline BOOST_CONSTEXPR ::boost::parameter::aux::flat_like_arg_list<
1133 ::boost::parameter::aux::flat_like_arg_tuple<
1134 typename TaggedArg::base_type::key_type
1135 , typename TaggedArg::base_type
1136 >
1137 >
1138 operator,(TaggedArg const& x) const
1139 {
1140 return ::boost::parameter::aux::flat_like_arg_list<
1141 ::boost::parameter::aux::flat_like_arg_tuple<
1142 typename TaggedArg::base_type::key_type
1143 , typename TaggedArg::base_type
1144 >
1145 >(
1146 static_cast<typename TaggedArg::base_type const&>(x)
1147 , static_cast<_base_type const&>(*this)
1148 );
1149 }
1150 };
1151}}} // namespace boost::parameter::aux
1152
1153#endif // BOOST_PARAMETER_CAN_USE_MP11
1154
1155#include <boost/mpl/iterator_tags.hpp>
1156
1157namespace boost { namespace parameter { namespace aux {
1158
1159 // MPL sequence support
1160 template <typename ArgumentPack>
1161 struct arg_list_iterator
1162 {
1163 typedef ::boost::mpl::forward_iterator_tag category;
1164
1165 // The incremented iterator
1166 typedef ::boost::parameter::aux
1167 ::arg_list_iterator<typename ArgumentPack::tail_type> next;
1168
1169 // dereferencing yields the key type
1170 typedef typename ArgumentPack::key_type type;
1171 };
1172
1173 template <>
1174 struct arg_list_iterator< ::boost::parameter::aux::empty_arg_list>
1175 {
1176 };
1177}}} // namespace boost::parameter::aux
1178
1179#include <boost/mpl/begin_end_fwd.hpp>
1180
1181// MPL sequence support
1182namespace boost { namespace mpl {
1183
1184 template <>
1185 struct begin_impl< ::boost::parameter::aux::arg_list_tag>
1186 {
1187 template <typename S>
1188 struct apply
1189 {
1190 typedef ::boost::parameter::aux::arg_list_iterator<S> type;
1191 };
1192 };
1193
1194 template <>
1195 struct end_impl< ::boost::parameter::aux::arg_list_tag>
1196 {
1197 template <typename>
1198 struct apply
1199 {
1200 typedef ::boost::parameter::aux::arg_list_iterator<
1201 ::boost::parameter::aux::empty_arg_list
1202 > type;
1203 };
1204 };
1205}} // namespace boost::mpl
1206
1207#include <boost/parameter/value_type.hpp>
1208#include <boost/mpl/has_key_fwd.hpp>
1209#include <boost/type_traits/is_void.hpp>
1210
1211namespace boost { namespace mpl {
1212
1213 template <>
1214 struct has_key_impl< ::boost::parameter::aux::arg_list_tag>
1215 {
1216 template <typename ArgList, typename Keyword>
1217 struct apply
1218 {
1219 typedef typename ::boost::mpl::if_<
1220 ::boost::is_void<
1221 typename ::boost::parameter
1222 ::value_type<ArgList,Keyword,void>::type
1223 >
1224 , ::boost::mpl::false_
1225 , ::boost::mpl::true_
1226 >::type type;
1227 };
1228 };
1229}} // namespace boost::mpl
1230
1231#include <boost/mpl/count_fwd.hpp>
1232#include <boost/mpl/int.hpp>
1233
1234namespace boost { namespace mpl {
1235
1236 template <>
1237 struct count_impl< ::boost::parameter::aux::arg_list_tag>
1238 {
1239 template <typename ArgList, typename Keyword>
1240 struct apply
1241 {
1242 typedef typename ::boost::mpl::if_<
1243 ::boost::is_void<
1244 typename ::boost::parameter
1245 ::value_type<ArgList,Keyword,void>::type
1246 >
1247 , ::boost::mpl::int_<0>
1248 , ::boost::mpl::int_<1>
1249 >::type type;
1250 };
1251 };
1252}} // namespace boost::mpl
1253
1254#include <boost/mpl/key_type_fwd.hpp>
1255#include <boost/mpl/identity.hpp>
1256
1257namespace boost { namespace mpl {
1258
1259 template <>
1260 struct key_type_impl< ::boost::parameter::aux::arg_list_tag>
1261 {
1262 template <typename ArgList, typename Keyword>
1263 struct apply
1264 {
1265 typedef typename ::boost::mpl::eval_if<
1266 ::boost::is_void<
1267 typename ::boost::parameter
1268 ::value_type<ArgList,Keyword,void>::type
1269 >
1270 , void
1271 , ::boost::mpl::identity<Keyword>
1272 >::type type;
1273 };
1274 };
1275}} // namespace boost::mpl
1276
1277#include <boost/mpl/value_type_fwd.hpp>
1278
1279namespace boost { namespace mpl {
1280
1281 template <>
1282 struct value_type_impl< ::boost::parameter::aux::arg_list_tag>
1283 : ::boost::mpl::key_type_impl< ::boost::parameter::aux::arg_list_tag>
1284 {
1285 };
1286}} // namespace boost::mpl
1287
1288#include <boost/mpl/at_fwd.hpp>
1289
1290namespace boost { namespace mpl {
1291
1292 template <>
1293 struct at_impl< ::boost::parameter::aux::arg_list_tag>
1294 : ::boost::mpl::key_type_impl< ::boost::parameter::aux::arg_list_tag>
1295 {
1296 };
1297}} // namespace boost::mpl
1298
1299#include <boost/mpl/order_fwd.hpp>
1300#include <boost/mpl/void.hpp>
1301#include <boost/mpl/find.hpp>
1302#include <boost/mpl/distance.hpp>
1303
1304namespace boost { namespace mpl {
1305
1306 template <>
1307 struct order_impl< ::boost::parameter::aux::arg_list_tag>
1308 {
1309 template <typename ArgList, typename Keyword>
1310 struct apply
1311 {
1312 typedef typename ::boost::mpl::find<ArgList,Keyword>::type Itr;
1313 typedef typename ::boost::mpl::eval_if<
1314 ::boost::is_void<
1315 typename ::boost::parameter
1316 ::value_type<ArgList,Keyword,void>::type
1317 >
1318 , ::boost::mpl::identity< ::boost::mpl::void_>
1319 , ::boost::mpl::distance<
1320 Itr
1321 , ::boost::parameter::aux::arg_list_iterator<
1322 ::boost::parameter::aux::empty_arg_list
1323 >
1324 >
1325 >::type type;
1326 };
1327 };
1328}} // namespace boost::mpl
1329
1330#endif // include guard
1331
1332

source code of include/boost/parameter/aux_/arg_list.hpp