Line data Source code
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 ARG_LIST_050329_HPP
8 : #define ARG_LIST_050329_HPP
9 :
10 : namespace 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 :
36 : namespace 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 :
64 : namespace 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 0 : 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 0 : operator[](BOOST_PARAMETER_lazy_default_fallback<K,F> x) const
127 : {
128 0 : 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 :
161 : namespace 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 0 : 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 0 : inline BOOST_CONSTEXPR arg_list(
220 : TaggedArg const& head
221 : , Next const& tail
222 0 : ) : 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 0 : get_default(D const&, ::boost::mp11::mp_false) const
392 : #else
393 : get_default(D const&, ::boost::mpl::false_) const
394 : #endif
395 : {
396 0 : 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 0 : operator[](
444 : ::boost::parameter::aux::default_r_<key_type,Default> const& d
445 : ) const
446 : {
447 0 : 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 :
564 : namespace 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 :
677 : namespace 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 :
1032 : namespace 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 :
1157 : namespace 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
1182 : namespace 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 :
1211 : namespace 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 :
1234 : namespace 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 :
1257 : namespace 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 :
1279 : namespace 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 :
1290 : namespace 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 :
1304 : namespace 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 :
|