]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/spirit/home/support/attributes.hpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / boost / spirit / home / support / attributes.hpp
1 /*=============================================================================
2 Copyright (c) 2001-2011 Joel de Guzman
3 Copyright (c) 2001-2012 Hartmut Kaiser
4
5 Distributed under the Boost Software License, Version 1.0. (See accompanying
6 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 ==============================================================================*/
8 #if !defined(BOOST_SPIRIT_ATTRIBUTES_JANUARY_29_2007_0954AM)
9 #define BOOST_SPIRIT_ATTRIBUTES_JANUARY_29_2007_0954AM
10
11 #if defined(_MSC_VER)
12 #pragma once
13 #endif
14
15 #include <boost/spirit/home/support/unused.hpp>
16 #include <boost/spirit/home/support/has_semantic_action.hpp>
17 #include <boost/spirit/home/support/attributes_fwd.hpp>
18 #include <boost/spirit/home/support/container.hpp>
19 #include <boost/spirit/home/support/detail/hold_any.hpp>
20 #include <boost/spirit/home/support/detail/as_variant.hpp>
21 #include <boost/optional/optional.hpp>
22 #include <boost/fusion/include/transform.hpp>
23 #include <boost/fusion/include/filter_if.hpp>
24 #include <boost/fusion/include/as_vector.hpp>
25 #include <boost/fusion/include/push_front.hpp>
26 #include <boost/fusion/include/pop_front.hpp>
27 #include <boost/fusion/include/is_sequence.hpp>
28 #include <boost/fusion/include/for_each.hpp>
29 #include <boost/fusion/include/is_view.hpp>
30 #include <boost/fusion/include/mpl.hpp>
31 #include <boost/foreach.hpp>
32 #include <boost/utility/value_init.hpp>
33 #include <boost/type_traits/is_same.hpp>
34 #include <boost/type_traits/is_convertible.hpp>
35 #include <boost/mpl/eval_if.hpp>
36 #include <boost/mpl/end.hpp>
37 #include <boost/mpl/find_if.hpp>
38 #include <boost/mpl/identity.hpp>
39 #include <boost/mpl/deref.hpp>
40 #include <boost/mpl/distance.hpp>
41 #include <boost/mpl/or.hpp>
42 #include <boost/mpl/has_xxx.hpp>
43 #include <boost/mpl/equal.hpp>
44 #include <boost/proto/proto_fwd.hpp>
45 #include <boost/utility/enable_if.hpp>
46 #include <boost/variant.hpp>
47 #include <boost/range/iterator_range.hpp>
48 #include <boost/config.hpp>
49 #include <vector>
50 #include <utility>
51 #include <ios>
52
53 ///////////////////////////////////////////////////////////////////////////////
54 namespace boost { namespace spirit { namespace traits
55 {
56 ///////////////////////////////////////////////////////////////////////////
57 // This file deals with attribute related functions and meta-functions
58 // including generalized attribute transformation utilities for Spirit
59 // components.
60 ///////////////////////////////////////////////////////////////////////////
61
62 ///////////////////////////////////////////////////////////////////////////
63 // Find out if T can be a (strong) substitute for Expected attribute
64 namespace detail
65 {
66 template <typename T, typename Expected>
67 struct value_type_is_substitute
68 : is_substitute<
69 typename container_value<T>::type
70 , typename container_value<Expected>::type>
71 {};
72
73 template <typename T, typename Expected, typename Enable = void>
74 struct is_substitute_impl : is_same<T, Expected> {};
75
76 template <typename T, typename Expected>
77 struct is_substitute_impl<T, Expected,
78 typename enable_if<
79 mpl::and_<
80 fusion::traits::is_sequence<T>,
81 fusion::traits::is_sequence<Expected>,
82 mpl::equal<T, Expected, is_substitute<mpl::_1, mpl::_2> >
83 >
84 >::type>
85 : mpl::true_ {};
86
87 template <typename T, typename Expected>
88 struct is_substitute_impl<T, Expected,
89 typename enable_if<
90 mpl::and_<
91 is_container<T>,
92 is_container<Expected>,
93 detail::value_type_is_substitute<T, Expected>
94 >
95 >::type>
96 : mpl::true_ {};
97 }
98
99 template <typename T, typename Expected, typename Enable /*= void*/>
100 struct is_substitute
101 : detail::is_substitute_impl<T, Expected> {};
102
103 template <typename T, typename Expected>
104 struct is_substitute<optional<T>, optional<Expected> >
105 : is_substitute<T, Expected> {};
106
107 template <typename T>
108 struct is_substitute<T, T
109 , typename enable_if<not_is_optional<T> >::type>
110 : mpl::true_ {};
111
112 ///////////////////////////////////////////////////////////////////////////
113 // Find out if T can be a weak substitute for Expected attribute
114 namespace detail
115 {
116 // A type, which is convertible to the attribute is at the same time
117 // usable as its weak substitute.
118 template <typename T, typename Expected, typename Enable = void>
119 struct is_weak_substitute_impl : is_convertible<T, Expected> {};
120
121 // // An exposed attribute is a weak substitute for a supplied container
122 // // attribute if it is a weak substitute for its value_type. This is
123 // // true as all character parsers are compatible with a container
124 // // attribute having the corresponding character type as its value_type.
125 // template <typename T, typename Expected>
126 // struct is_weak_substitute_for_value_type
127 // : is_weak_substitute<T, typename container_value<Expected>::type>
128 // {};
129 //
130 // template <typename T, typename Expected>
131 // struct is_weak_substitute_impl<T, Expected,
132 // typename enable_if<
133 // mpl::and_<
134 // mpl::not_<is_string<T> >
135 // , is_string<Expected>
136 // , is_weak_substitute_for_value_type<T, Expected> >
137 // >::type>
138 // : mpl::true_
139 // {};
140
141 // An exposed container attribute is a weak substitute for a supplied
142 // container attribute if and only if their value_types are weak
143 // substitutes.
144 template <typename T, typename Expected>
145 struct value_type_is_weak_substitute
146 : is_weak_substitute<
147 typename container_value<T>::type
148 , typename container_value<Expected>::type>
149 {};
150
151 template <typename T, typename Expected>
152 struct is_weak_substitute_impl<T, Expected,
153 typename enable_if<
154 mpl::and_<
155 is_container<T>
156 , is_container<Expected>
157 , value_type_is_weak_substitute<T, Expected> >
158 >::type>
159 : mpl::true_ {};
160
161 // Two fusion sequences are weak substitutes if and only if their
162 // elements are pairwise weak substitutes.
163 template <typename T, typename Expected>
164 struct is_weak_substitute_impl<T, Expected,
165 typename enable_if<
166 mpl::and_<
167 fusion::traits::is_sequence<T>
168 , fusion::traits::is_sequence<Expected>
169 , mpl::equal<T, Expected, is_weak_substitute<mpl::_1, mpl::_2> > >
170 >::type>
171 : mpl::true_ {};
172
173 // If this is not defined, the main template definition above will return
174 // true if T is convertible to the first type in a fusion::vector. We
175 // globally declare any non-Fusion sequence T as not compatible with any
176 // Fusion sequence 'Expected'.
177 template <typename T, typename Expected>
178 struct is_weak_substitute_impl<T, Expected,
179 typename enable_if<
180 mpl::and_<
181 mpl::not_<fusion::traits::is_sequence<T> >
182 , fusion::traits::is_sequence<Expected> >
183 >::type>
184 : mpl::false_ {};
185 }
186
187 // main template forwards to detail namespace, this helps older compilers
188 // to disambiguate things
189 template <typename T, typename Expected, typename Enable /*= void*/>
190 struct is_weak_substitute
191 : detail::is_weak_substitute_impl<T, Expected> {};
192
193 template <typename T, typename Expected>
194 struct is_weak_substitute<optional<T>, optional<Expected> >
195 : is_weak_substitute<T, Expected> {};
196
197 template <typename T, typename Expected>
198 struct is_weak_substitute<optional<T>, Expected>
199 : is_weak_substitute<T, Expected> {};
200
201 template <typename T, typename Expected>
202 struct is_weak_substitute<T, optional<Expected> >
203 : is_weak_substitute<T, Expected> {};
204
205 #if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES)
206 template <typename T, typename Expected>
207 struct is_weak_substitute<boost::variant<T>, Expected>
208 : is_weak_substitute<T, Expected>
209 {};
210
211 template <typename T0, typename T1, typename ...TN, typename Expected>
212 struct is_weak_substitute<boost::variant<T0, T1, TN...>,
213 Expected>
214 : mpl::bool_<is_weak_substitute<T0, Expected>::type::value &&
215 is_weak_substitute<boost::variant<T1, TN...>, Expected>::type::value>
216 {};
217 #else
218 #define BOOST_SPIRIT_IS_WEAK_SUBSTITUTE(z, N, _) \
219 is_weak_substitute<BOOST_PP_CAT(T, N), Expected>::type::value && \
220 /***/
221
222 // make sure unused variant parameters do not affect the outcome
223 template <typename Expected>
224 struct is_weak_substitute<boost::detail::variant::void_, Expected>
225 : mpl::true_
226 {};
227
228 template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Expected>
229 struct is_weak_substitute<
230 boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Expected>
231 : mpl::bool_<BOOST_PP_REPEAT(BOOST_VARIANT_LIMIT_TYPES
232 , BOOST_SPIRIT_IS_WEAK_SUBSTITUTE, _) true>
233 {};
234
235 #undef BOOST_SPIRIT_IS_WEAK_SUBSTITUTE
236 #endif
237
238 template <typename T>
239 struct is_weak_substitute<T, T
240 , typename enable_if<
241 mpl::and_<not_is_optional<T>, not_is_variant<T> >
242 >::type>
243 : mpl::true_ {};
244
245 ///////////////////////////////////////////////////////////////////////////
246 template <typename T, typename Enable/* = void*/>
247 struct is_proxy : mpl::false_ {};
248
249 template <typename T>
250 struct is_proxy<T,
251 typename enable_if<
252 mpl::and_<
253 fusion::traits::is_sequence<T>,
254 fusion::traits::is_view<T>
255 >
256 >::type>
257 : mpl::true_ {};
258
259 namespace detail
260 {
261 // By declaring a nested struct in your class/struct, you tell
262 // spirit that it is regarded as a variant type. The minimum
263 // required interface for such a variant is that it has constructors
264 // for various types supported by your variant and a typedef 'types'
265 // which is an mpl sequence of the contained types.
266 //
267 // This is an intrusive interface. For a non-intrusive interface,
268 // use the not_is_variant trait.
269 BOOST_MPL_HAS_XXX_TRAIT_DEF(adapted_variant_tag)
270 }
271
272 template <typename T, typename Domain, typename Enable/* = void*/>
273 struct not_is_variant
274 : mpl::not_<detail::has_adapted_variant_tag<T> >
275 {};
276
277 template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Domain>
278 struct not_is_variant<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Domain>
279 : mpl::false_
280 {};
281
282 template <typename T, typename Domain>
283 struct not_is_variant<boost::optional<T>, Domain>
284 : not_is_variant<T, Domain>
285 {};
286
287 // we treat every type as if it where the variant (as this meta function is
288 // invoked for variant types only)
289 template <typename T>
290 struct variant_type
291 : mpl::identity<T>
292 {};
293
294 template <typename T>
295 struct variant_type<boost::optional<T> >
296 : variant_type<T>
297 {};
298
299 ///////////////////////////////////////////////////////////////////////////
300 // The compute_compatible_component_variant
301 ///////////////////////////////////////////////////////////////////////////
302 namespace detail
303 {
304 // A component is compatible to a given Attribute type if the
305 // Attribute is the same as the expected type of the component or if
306 // it is convertible to the expected type.
307 template <typename Expected, typename Attribute>
308 struct attribute_is_compatible
309 : is_convertible<Attribute, Expected>
310 {};
311
312 template <typename Expected, typename Attribute>
313 struct attribute_is_compatible<Expected, boost::optional<Attribute> >
314 : is_convertible<Attribute, Expected>
315 {};
316
317 template <typename Container>
318 struct is_hold_any_container
319 : traits::is_hold_any<typename traits::container_value<Container>::type>
320 {};
321 }
322
323 template <typename Attribute, typename Expected
324 , typename IsNotVariant = mpl::false_, typename Enable = void>
325 struct compute_compatible_component_variant
326 : mpl::or_<
327 traits::detail::attribute_is_compatible<Expected, Attribute>
328 , traits::is_hold_any<Expected>
329 , mpl::eval_if<
330 is_container<Expected>
331 , traits::detail::is_hold_any_container<Expected>
332 , mpl::false_> >
333 {};
334
335 namespace detail
336 {
337 BOOST_MPL_HAS_XXX_TRAIT_DEF(types)
338 }
339
340 template <typename Variant, typename Expected>
341 struct compute_compatible_component_variant<Variant, Expected, mpl::false_
342 , typename enable_if<detail::has_types<Variant> >::type>
343 {
344 typedef typename traits::variant_type<Variant>::type variant_type;
345 typedef typename variant_type::types types;
346 typedef typename mpl::end<types>::type end;
347
348 typedef typename
349 mpl::find_if<types, is_same<Expected, mpl::_1> >::type
350 iter;
351
352 typedef typename mpl::distance<
353 typename mpl::begin<types>::type, iter
354 >::type distance;
355
356 // true_ if the attribute matches one of the types in the variant
357 typedef typename mpl::not_<is_same<iter, end> >::type type;
358 enum { value = type::value };
359
360 // return the type in the variant the attribute is compatible with
361 typedef typename
362 mpl::eval_if<type, mpl::deref<iter>, mpl::identity<unused_type> >::type
363 compatible_type;
364
365 // return whether the given type is compatible with the Expected type
366 static bool is_compatible(int which)
367 {
368 return which == distance::value;
369 }
370 };
371
372 template <typename Expected, typename Attribute, typename Domain>
373 struct compute_compatible_component
374 : compute_compatible_component_variant<Attribute, Expected
375 , typename spirit::traits::not_is_variant<Attribute, Domain>::type> {};
376
377 template <typename Expected, typename Domain>
378 struct compute_compatible_component<Expected, unused_type, Domain>
379 : mpl::false_ {};
380
381 template <typename Attribute, typename Domain>
382 struct compute_compatible_component<unused_type, Attribute, Domain>
383 : mpl::false_ {};
384
385 template <typename Domain>
386 struct compute_compatible_component<unused_type, unused_type, Domain>
387 : mpl::false_ {};
388
389 ///////////////////////////////////////////////////////////////////////////
390 // return the type currently stored in the given variant
391 template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
392 struct variant_which<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
393 {
394 static int call(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& v)
395 {
396 return v.which();
397 }
398 };
399
400 template <typename T>
401 int which(T const& v)
402 {
403 return variant_which<T>::call(v);
404 }
405
406 ///////////////////////////////////////////////////////////////////////////
407 template <typename T, typename Domain, typename Enable/* = void*/>
408 struct not_is_optional
409 : mpl::true_
410 {};
411
412 template <typename T, typename Domain>
413 struct not_is_optional<boost::optional<T>, Domain>
414 : mpl::false_
415 {};
416
417 ///////////////////////////////////////////////////////////////////////////
418 // attribute_of
419 //
420 // Get the component's attribute
421 ///////////////////////////////////////////////////////////////////////////
422 template <typename Component
423 , typename Context = unused_type, typename Iterator = unused_type>
424 struct attribute_of
425 {
426 typedef typename Component::template
427 attribute<Context, Iterator>::type type;
428 };
429
430 ///////////////////////////////////////////////////////////////////////////
431 // attribute_not_unused
432 //
433 // An mpl meta-function class that determines whether a component's
434 // attribute is not unused.
435 ///////////////////////////////////////////////////////////////////////////
436 template <typename Context, typename Iterator = unused_type>
437 struct attribute_not_unused
438 {
439 template <typename Component>
440 struct apply
441 : not_is_unused<typename
442 attribute_of<Component, Context, Iterator>::type>
443 {};
444 };
445
446 ///////////////////////////////////////////////////////////////////////////
447 // Retrieve the attribute type to use from the given type
448 //
449 // This is needed to extract the correct attribute type from proxy classes
450 // as utilized in FUSION_ADAPT_ADT et. al.
451 ///////////////////////////////////////////////////////////////////////////
452 template <typename Attribute, typename Enable/* = void*/>
453 struct attribute_type : mpl::identity<Attribute> {};
454
455 ///////////////////////////////////////////////////////////////////////////
456 // Retrieve the size of a fusion sequence (compile time)
457 ///////////////////////////////////////////////////////////////////////////
458 template <typename T>
459 struct sequence_size
460 : fusion::result_of::size<T>
461 {};
462
463 template <>
464 struct sequence_size<unused_type>
465 : mpl::int_<0>
466 {};
467
468 ///////////////////////////////////////////////////////////////////////////
469 // Retrieve the size of an attribute (runtime)
470 ///////////////////////////////////////////////////////////////////////////
471 namespace detail
472 {
473 template <typename Attribute, typename Enable = void>
474 struct attribute_size_impl
475 {
476 typedef std::size_t type;
477
478 static type call(Attribute const&)
479 {
480 return 1;
481 }
482 };
483
484 template <typename Attribute>
485 struct attribute_size_impl<Attribute
486 , typename enable_if<
487 mpl::and_<
488 fusion::traits::is_sequence<Attribute>
489 , mpl::not_<traits::is_container<Attribute> >
490 >
491 >::type>
492 {
493 typedef typename fusion::result_of::size<Attribute>::value_type type;
494
495 static type call(Attribute const& attr)
496 {
497 return fusion::size(attr);
498 }
499 };
500
501 template <typename Attribute>
502 struct attribute_size_impl<Attribute
503 , typename enable_if<
504 mpl::and_<
505 traits::is_container<Attribute>
506 , mpl::not_<traits::is_iterator_range<Attribute> >
507 >
508 >::type>
509 {
510 typedef typename Attribute::size_type type;
511
512 static type call(Attribute const& attr)
513 {
514 return attr.size();
515 }
516 };
517 }
518
519 template <typename Attribute, typename Enable/* = void*/>
520 struct attribute_size
521 : detail::attribute_size_impl<Attribute>
522 {};
523
524 template <typename Attribute>
525 struct attribute_size<optional<Attribute> >
526 {
527 typedef typename attribute_size<Attribute>::type type;
528
529 static type call(optional<Attribute> const& val)
530 {
531 if (!val)
532 return 0;
533 return traits::size(val.get());
534 }
535 };
536
537 namespace detail
538 {
539 struct attribute_size_visitor : static_visitor<std::size_t>
540 {
541 template <typename T>
542 std::size_t operator()(T const& val) const
543 {
544 return spirit::traits::size(val);
545 }
546 };
547 }
548
549 template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
550 struct attribute_size<variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
551 {
552 typedef std::size_t type;
553
554 static type call(variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& val)
555 {
556 return apply_visitor(detail::attribute_size_visitor(), val);
557 }
558 };
559
560 template <typename Iterator>
561 struct attribute_size<iterator_range<Iterator> >
562 {
563 typedef typename boost::detail::iterator_traits<Iterator>::
564 difference_type type;
565
566 static type call(iterator_range<Iterator> const& r)
567 {
568 return boost::detail::distance(r.begin(), r.end());
569 }
570 };
571
572 template <>
573 struct attribute_size<unused_type>
574 {
575 typedef std::size_t type;
576
577 static type call(unused_type)
578 {
579 return 0;
580 }
581 };
582
583 template <typename Attribute>
584 typename attribute_size<Attribute>::type
585 size (Attribute const& attr)
586 {
587 return attribute_size<Attribute>::call(attr);
588 }
589
590 ///////////////////////////////////////////////////////////////////////////
591 // pass_attribute
592 //
593 // Determines how we pass attributes to semantic actions. This
594 // may be specialized. By default, all attributes are wrapped in
595 // a fusion sequence, because the attribute has to be treated as being
596 // a single value in any case (even if it actually already is a fusion
597 // sequence in its own).
598 ///////////////////////////////////////////////////////////////////////////
599 template <typename Component, typename Attribute, typename Enable/* = void*/>
600 struct pass_attribute
601 {
602 typedef fusion::vector1<Attribute&> type;
603 };
604
605 ///////////////////////////////////////////////////////////////////////////
606 // Subclass a pass_attribute specialization from this to wrap
607 // the attribute in a tuple only IFF it is not already a fusion tuple.
608 ///////////////////////////////////////////////////////////////////////////
609 template <typename Attribute, typename Force = mpl::false_>
610 struct wrap_if_not_tuple
611 : mpl::if_<
612 fusion::traits::is_sequence<Attribute>
613 , Attribute&, fusion::vector1<Attribute&> >
614 {};
615
616 template <typename Attribute>
617 struct wrap_if_not_tuple<Attribute, mpl::true_>
618 {
619 typedef fusion::vector1<Attribute&> type;
620 };
621
622 template <>
623 struct wrap_if_not_tuple<unused_type, mpl::false_>
624 {
625 typedef unused_type type;
626 };
627
628 template <>
629 struct wrap_if_not_tuple<unused_type const, mpl::false_>
630 {
631 typedef unused_type type;
632 };
633
634 ///////////////////////////////////////////////////////////////////////////
635 // build_optional
636 //
637 // Build a boost::optional from T. Return unused_type if T is unused_type.
638 ///////////////////////////////////////////////////////////////////////////
639 template <typename T>
640 struct build_optional
641 {
642 typedef boost::optional<T> type;
643 };
644
645 template <typename T>
646 struct build_optional<boost::optional<T> >
647 {
648 typedef boost::optional<T> type;
649 };
650
651 template <>
652 struct build_optional<unused_type>
653 {
654 typedef unused_type type;
655 };
656
657 ///////////////////////////////////////////////////////////////////////////
658 // build_std_vector
659 //
660 // Build a std::vector from T. Return unused_type if T is unused_type.
661 ///////////////////////////////////////////////////////////////////////////
662 template <typename T>
663 struct build_std_vector
664 {
665 typedef std::vector<T> type;
666 };
667
668 template <>
669 struct build_std_vector<unused_type>
670 {
671 typedef unused_type type;
672 };
673
674 ///////////////////////////////////////////////////////////////////////////
675 // filter_unused_attributes
676 //
677 // Remove unused_types from a sequence
678 ///////////////////////////////////////////////////////////////////////////
679
680 // Compute the list of all *used* attributes of sub-components
681 // (filter all unused attributes from the list)
682 template <typename Sequence>
683 struct filter_unused_attributes
684 : fusion::result_of::filter_if<Sequence, not_is_unused<mpl::_> >
685 {};
686
687 ///////////////////////////////////////////////////////////////////////////
688 // sequence_attribute_transform
689 //
690 // This transform is invoked for every attribute in a sequence allowing
691 // to modify the attribute type exposed by a component to the enclosing
692 // sequence component. By default no transformation is performed.
693 ///////////////////////////////////////////////////////////////////////////
694 template <typename Attribute, typename Domain>
695 struct sequence_attribute_transform
696 : mpl::identity<Attribute>
697 {};
698
699 ///////////////////////////////////////////////////////////////////////////
700 // permutation_attribute_transform
701 //
702 // This transform is invoked for every attribute in a sequence allowing
703 // to modify the attribute type exposed by a component to the enclosing
704 // permutation component. By default a build_optional transformation is
705 // performed.
706 ///////////////////////////////////////////////////////////////////////////
707 template <typename Attribute, typename Domain>
708 struct permutation_attribute_transform
709 : traits::build_optional<Attribute>
710 {};
711
712 ///////////////////////////////////////////////////////////////////////////
713 // sequential_or_attribute_transform
714 //
715 // This transform is invoked for every attribute in a sequential_or allowing
716 // to modify the attribute type exposed by a component to the enclosing
717 // sequential_or component. By default a build_optional transformation is
718 // performed.
719 ///////////////////////////////////////////////////////////////////////////
720 template <typename Attribute, typename Domain>
721 struct sequential_or_attribute_transform
722 : traits::build_optional<Attribute>
723 {};
724
725 ///////////////////////////////////////////////////////////////////////////
726 // build_fusion_vector
727 //
728 // Build a fusion vector from a fusion sequence. All unused attributes
729 // are filtered out. If the result is empty after the removal of unused
730 // types, return unused_type. If the input sequence is an unused_type,
731 // also return unused_type.
732 ///////////////////////////////////////////////////////////////////////////
733 template <typename Sequence>
734 struct build_fusion_vector
735 {
736 // Remove all unused attributes
737 typedef typename
738 filter_unused_attributes<Sequence>::type
739 filtered_attributes;
740
741 // Build a fusion vector from a fusion sequence (Sequence),
742 // But *only if* the sequence is not empty. i.e. if the
743 // sequence is empty, our result will be unused_type.
744
745 typedef typename
746 mpl::eval_if<
747 fusion::result_of::empty<filtered_attributes>
748 , mpl::identity<unused_type>
749 , fusion::result_of::as_vector<filtered_attributes>
750 >::type
751 type;
752 };
753
754 template <>
755 struct build_fusion_vector<unused_type>
756 {
757 typedef unused_type type;
758 };
759
760 ///////////////////////////////////////////////////////////////////////////
761 // build_attribute_sequence
762 //
763 // Build a fusion sequence attribute sequence from a sequence of
764 // components. Transform<T>::type is called on each element.
765 ///////////////////////////////////////////////////////////////////////////
766 template <typename Sequence, typename Context
767 , template <typename T, typename D> class Transform
768 , typename Iterator = unused_type, typename Domain = unused_type>
769 struct build_attribute_sequence
770 {
771 struct element_attribute
772 {
773 template <typename T>
774 struct result;
775
776 template <typename F, typename Element>
777 struct result<F(Element)>
778 {
779 typedef typename
780 Transform<
781 typename attribute_of<Element, Context, Iterator>::type
782 , Domain
783 >::type
784 type;
785 };
786
787 // never called, but needed for decltype-based result_of (C++0x)
788 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
789 template <typename Element>
790 typename result<element_attribute(Element)>::type
791 operator()(Element&&) const;
792 #endif
793 };
794
795 // Compute the list of attributes of all sub-components
796 typedef typename
797 fusion::result_of::transform<Sequence, element_attribute>::type
798 type;
799 };
800
801 ///////////////////////////////////////////////////////////////////////////
802 // has_no_unused
803 //
804 // Test if there are no unused attributes in Sequence
805 ///////////////////////////////////////////////////////////////////////////
806 template <typename Sequence>
807 struct has_no_unused
808 : is_same<
809 typename mpl::find_if<Sequence, is_same<mpl::_, unused_type> >::type
810 , typename mpl::end<Sequence>::type>
811 {};
812
813 namespace detail
814 {
815 template <typename Sequence, bool no_unused
816 , int size = mpl::size<Sequence>::value>
817 struct build_collapsed_variant;
818
819 // N element case, no unused
820 template <typename Sequence, int size>
821 struct build_collapsed_variant<Sequence, true, size>
822 : spirit::detail::as_variant<Sequence> {};
823
824 // N element case with unused
825 template <typename Sequence, int size>
826 struct build_collapsed_variant<Sequence, false, size>
827 {
828 typedef boost::optional<
829 typename spirit::detail::as_variant<
830 typename fusion::result_of::pop_front<Sequence>::type
831 >::type
832 > type;
833 };
834
835 // 1 element case, no unused
836 template <typename Sequence>
837 struct build_collapsed_variant<Sequence, true, 1>
838 : mpl::front<Sequence> {};
839
840 // 1 element case, with unused
841 template <typename Sequence>
842 struct build_collapsed_variant<Sequence, false, 1>
843 : mpl::front<Sequence> {};
844
845 // 2 element case, no unused
846 template <typename Sequence>
847 struct build_collapsed_variant<Sequence, true, 2>
848 : spirit::detail::as_variant<Sequence> {};
849
850 // 2 element case, with unused
851 template <typename Sequence>
852 struct build_collapsed_variant<Sequence, false, 2>
853 {
854 typedef boost::optional<
855 typename mpl::deref<
856 typename mpl::next<
857 typename mpl::begin<Sequence>::type
858 >::type
859 >::type
860 >
861 type;
862 };
863 }
864
865 ///////////////////////////////////////////////////////////////////////////
866 // alternative_attribute_transform
867 //
868 // This transform is invoked for every attribute in an alternative allowing
869 // to modify the attribute type exposed by a component to the enclosing
870 // alternative component. By default no transformation is performed.
871 ///////////////////////////////////////////////////////////////////////////
872 template <typename Attribute, typename Domain>
873 struct alternative_attribute_transform
874 : mpl::identity<Attribute>
875 {};
876
877 ///////////////////////////////////////////////////////////////////////////
878 // build_variant
879 //
880 // Build a boost::variant from a fusion sequence. build_variant makes sure
881 // that 1) all attributes in the variant are unique 2) puts the unused
882 // attribute, if there is any, to the front and 3) collapses single element
883 // variants, variant<T> to T.
884 ///////////////////////////////////////////////////////////////////////////
885 template <typename Sequence>
886 struct build_variant
887 {
888 // Remove all unused attributes.
889 typedef typename
890 filter_unused_attributes<Sequence>::type
891 filtered_attributes;
892
893 typedef has_no_unused<Sequence> no_unused;
894
895 // If the original attribute list does not contain any unused
896 // attributes, it is used, otherwise a single unused_type is
897 // pushed to the front of the list. This is to make sure that if
898 // there is an unused_type in the list, it is the first one.
899 typedef typename
900 mpl::eval_if<
901 no_unused,
902 mpl::identity<Sequence>,
903 fusion::result_of::push_front<filtered_attributes, unused_type>
904 >::type
905 attribute_sequence;
906
907 // Make sure each of the types occur only once in the type list
908 typedef typename
909 mpl::fold<
910 attribute_sequence, mpl::vector<>,
911 mpl::if_<
912 mpl::contains<mpl::_1, mpl::_2>,
913 mpl::_1, mpl::push_back<mpl::_1, mpl::_2>
914 >
915 >::type
916 no_duplicates;
917
918 // If there is only one type in the list of types we strip off the
919 // variant. IOTW, collapse single element variants, variant<T> to T.
920 // Take note that this also collapses variant<unused_type, T> to T.
921 typedef typename
922 traits::detail::build_collapsed_variant<
923 no_duplicates, no_unused::value>::type
924 type;
925 };
926
927 ///////////////////////////////////////////////////////////////////////////
928 // transform_attribute
929 //
930 // Sometimes the user needs to transform the attribute types for certain
931 // attributes. This template can be used as a customization point, where
932 // the user is able specify specific transformation rules for any attribute
933 // type.
934 ///////////////////////////////////////////////////////////////////////////
935 template <typename Exposed, typename Transformed, typename Domain
936 , typename Enable/* = void*/>
937 struct transform_attribute;
938
939 ///////////////////////////////////////////////////////////////////////////
940 template <typename Domain, typename Transformed, typename Exposed>
941 typename spirit::result_of::pre_transform<Exposed, Transformed, Domain>::type
942 pre_transform(Exposed& attr BOOST_PROTO_DISABLE_IF_IS_CONST(Exposed))
943 {
944 return transform_attribute<Exposed, Transformed, Domain>::pre(attr);
945 }
946
947 template <typename Domain, typename Transformed, typename Exposed>
948 typename spirit::result_of::pre_transform<Exposed const, Transformed, Domain>::type
949 pre_transform(Exposed const& attr)
950 {
951 return transform_attribute<Exposed const, Transformed, Domain>::pre(attr);
952 }
953
954 ///////////////////////////////////////////////////////////////////////////
955 // make_attribute
956 //
957 // All parsers and generators have specific attribute types.
958 // Spirit parsers and generators are passed an attribute; these are either
959 // references to the expected type, or an unused_type -- to flag that we do
960 // not care about the attribute. For semantic actions, however, we need to
961 // have a real value to pass to the semantic action. If the client did not
962 // provide one, we will have to synthesize the value. This class takes care
963 // of that. *Note that this behavior has changed. From Boost 1.47, semantic
964 // actions always take in the passed attribute as-is if the PP constant:
965 // BOOST_SPIRIT_ACTIONS_ALLOW_ATTR_COMPAT is defined.
966 ///////////////////////////////////////////////////////////////////////////
967 template <typename Attribute, typename ActualAttribute>
968 struct make_attribute
969 {
970 typedef typename remove_const<Attribute>::type attribute_type;
971 typedef typename
972 mpl::if_<
973 is_same<typename remove_const<ActualAttribute>::type, unused_type>
974 , attribute_type
975 , ActualAttribute&>::type
976 type;
977
978 typedef typename
979 mpl::if_<
980 is_same<typename remove_const<ActualAttribute>::type, unused_type>
981 , attribute_type
982 , ActualAttribute>::type
983 value_type;
984
985 static Attribute call(unused_type)
986 {
987 // synthesize the attribute/parameter
988 return boost::get(value_initialized<attribute_type>());
989 }
990
991 template <typename T>
992 static T& call(T& value)
993 {
994 return value; // just pass the one provided
995 }
996 };
997
998 template <typename Attribute, typename ActualAttribute>
999 struct make_attribute<Attribute&, ActualAttribute>
1000 : make_attribute<Attribute, ActualAttribute>
1001 {};
1002
1003 template <typename Attribute, typename ActualAttribute>
1004 struct make_attribute<Attribute const&, ActualAttribute>
1005 : make_attribute<Attribute const, ActualAttribute>
1006 {};
1007
1008 template <typename ActualAttribute>
1009 struct make_attribute<unused_type, ActualAttribute>
1010 {
1011 typedef unused_type type;
1012 typedef unused_type value_type;
1013 static unused_type call(unused_type)
1014 {
1015 return unused;
1016 }
1017 };
1018
1019 ///////////////////////////////////////////////////////////////////////////
1020 // swap_impl
1021 //
1022 // Swap (with proper handling of unused_types)
1023 ///////////////////////////////////////////////////////////////////////////
1024 template <typename A, typename B>
1025 void swap_impl(A& a, B& b)
1026 {
1027 A temp = a;
1028 a = b;
1029 b = temp;
1030 }
1031
1032 template <typename T>
1033 void swap_impl(T& a, T& b)
1034 {
1035 boost::swap(a, b);
1036 }
1037
1038 template <typename A>
1039 void swap_impl(A&, unused_type)
1040 {
1041 }
1042
1043 template <typename A>
1044 void swap_impl(unused_type, A&)
1045 {
1046 }
1047
1048 inline void swap_impl(unused_type, unused_type)
1049 {
1050 }
1051
1052 ///////////////////////////////////////////////////////////////////////////
1053 // Strips single element fusion vectors into its 'naked'
1054 // form: vector<T> --> T
1055 ///////////////////////////////////////////////////////////////////////////
1056 template <typename T>
1057 struct strip_single_element_vector
1058 {
1059 typedef T type;
1060 };
1061
1062 #if !defined(BOOST_FUSION_HAS_VARIADIC_VECTOR)
1063 template <typename T>
1064 struct strip_single_element_vector<fusion::vector1<T> >
1065 {
1066 typedef T type;
1067 };
1068 #endif
1069 template <typename T>
1070 struct strip_single_element_vector<fusion::vector<T> >
1071 {
1072 typedef T type;
1073 };
1074
1075 ///////////////////////////////////////////////////////////////////////////
1076 // meta function to return whether the argument is a one element fusion
1077 // sequence
1078 ///////////////////////////////////////////////////////////////////////////
1079 template <typename T
1080 , bool IsFusionSeq = fusion::traits::is_sequence<T>::value
1081 , bool IsProtoExpr = proto::is_expr<T>::value>
1082 struct one_element_sequence
1083 : mpl::false_
1084 {};
1085
1086 template <typename T>
1087 struct one_element_sequence<T, true, false>
1088 : mpl::bool_<mpl::size<T>::value == 1>
1089 {};
1090
1091 ///////////////////////////////////////////////////////////////////////////
1092 // clear
1093 //
1094 // Clear data efficiently
1095 ///////////////////////////////////////////////////////////////////////////
1096 template <typename T>
1097 void clear(T& val);
1098
1099 namespace detail
1100 {
1101 // this is used by the variant and fusion sequence dispatch
1102 struct clear_visitor : static_visitor<>
1103 {
1104 template <typename T>
1105 void operator()(T& val) const
1106 {
1107 spirit::traits::clear(val);
1108 }
1109 };
1110
1111 // default
1112 template <typename T>
1113 void clear_impl2(T& val, mpl::false_)
1114 {
1115 val = T();
1116 }
1117
1118 // for fusion sequences
1119 template <typename T>
1120 void clear_impl2(T& val, mpl::true_)
1121 {
1122 fusion::for_each(val, clear_visitor());
1123 }
1124
1125 // dispatch default or fusion sequence
1126 template <typename T>
1127 void clear_impl(T& val, mpl::false_)
1128 {
1129 clear_impl2(val, fusion::traits::is_sequence<T>());
1130 }
1131
1132 // STL containers
1133 template <typename T>
1134 void clear_impl(T& val, mpl::true_)
1135 {
1136 val.clear();
1137 }
1138 }
1139
1140 template <typename T, typename Enable/* = void*/>
1141 struct clear_value
1142 {
1143 static void call(T& val)
1144 {
1145 detail::clear_impl(val, typename is_container<T>::type());
1146 }
1147 };
1148
1149 // optionals
1150 template <typename T>
1151 struct clear_value<boost::optional<T> >
1152 {
1153 static void call(boost::optional<T>& val)
1154 {
1155 if (val)
1156 val = none; // leave optional uninitialized
1157 }
1158 };
1159
1160 // variants
1161 template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
1162 struct clear_value<variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
1163 {
1164 static void call(variant<BOOST_VARIANT_ENUM_PARAMS(T)>& val)
1165 {
1166 apply_visitor(detail::clear_visitor(), val);
1167 }
1168 };
1169
1170 // iterator range
1171 template <typename T>
1172 struct clear_value<iterator_range<T> >
1173 {
1174 static void call(iterator_range<T>& val)
1175 {
1176 val = iterator_range<T>(val.end(), val.end());
1177 }
1178 };
1179
1180 // main dispatch
1181 template <typename T>
1182 void clear(T& val)
1183 {
1184 clear_value<T>::call(val);
1185 }
1186
1187 // for unused
1188 inline void clear(unused_type)
1189 {
1190 }
1191
1192 ///////////////////////////////////////////////////////////////////////////
1193 namespace detail
1194 {
1195 template <typename Out>
1196 struct print_fusion_sequence
1197 {
1198 print_fusion_sequence(Out& out_)
1199 : out(out_), is_first(true) {}
1200
1201 typedef void result_type;
1202
1203 template <typename T>
1204 void operator()(T const& val) const
1205 {
1206 if (is_first)
1207 is_first = false;
1208 else
1209 out << ", ";
1210 spirit::traits::print_attribute(out, val);
1211 }
1212
1213 Out& out;
1214 mutable bool is_first;
1215 };
1216
1217 // print elements in a variant
1218 template <typename Out>
1219 struct print_visitor : static_visitor<>
1220 {
1221 print_visitor(Out& out_) : out(out_) {}
1222
1223 template <typename T>
1224 void operator()(T const& val) const
1225 {
1226 spirit::traits::print_attribute(out, val);
1227 }
1228
1229 Out& out;
1230 };
1231 }
1232
1233 template <typename Out, typename T, typename Enable>
1234 struct print_attribute_debug
1235 {
1236 // for plain data types
1237 template <typename T_>
1238 static void call_impl3(Out& out, T_ const& val, mpl::false_)
1239 {
1240 out << val;
1241 }
1242
1243 // for fusion data types
1244 template <typename T_>
1245 static void call_impl3(Out& out, T_ const& val, mpl::true_)
1246 {
1247 out << '[';
1248 fusion::for_each(val, detail::print_fusion_sequence<Out>(out));
1249 out << ']';
1250 }
1251
1252 // non-stl container
1253 template <typename T_>
1254 static void call_impl2(Out& out, T_ const& val, mpl::false_)
1255 {
1256 call_impl3(out, val, fusion::traits::is_sequence<T_>());
1257 }
1258
1259 // stl container
1260 template <typename T_>
1261 static void call_impl2(Out& out, T_ const& val, mpl::true_)
1262 {
1263 out << '[';
1264 if (!traits::is_empty(val))
1265 {
1266 bool first = true;
1267 typename container_iterator<T_ const>::type iend = traits::end(val);
1268 for (typename container_iterator<T_ const>::type i = traits::begin(val);
1269 !traits::compare(i, iend); traits::next(i))
1270 {
1271 if (!first)
1272 out << ", ";
1273 first = false;
1274 spirit::traits::print_attribute(out, traits::deref(i));
1275 }
1276 }
1277 out << ']';
1278 }
1279
1280 // for variant types
1281 template <typename T_>
1282 static void call_impl(Out& out, T_ const& val, mpl::false_)
1283 {
1284 apply_visitor(detail::print_visitor<Out>(out), val);
1285 }
1286
1287 // for non-variant types
1288 template <typename T_>
1289 static void call_impl(Out& out, T_ const& val, mpl::true_)
1290 {
1291 call_impl2(out, val, is_container<T_>());
1292 }
1293
1294 // main entry point
1295 static void call(Out& out, T const& val)
1296 {
1297 call_impl(out, val, not_is_variant<T>());
1298 }
1299 };
1300
1301 template <typename Out, typename T>
1302 struct print_attribute_debug<Out, boost::optional<T> >
1303 {
1304 static void call(Out& out, boost::optional<T> const& val)
1305 {
1306 if (val)
1307 spirit::traits::print_attribute(out, *val);
1308 else
1309 out << "[empty]";
1310 }
1311 };
1312
1313 ///////////////////////////////////////////////////////////////////////////
1314 template <typename Out, typename T>
1315 inline void print_attribute(Out& out, T const& val)
1316 {
1317 print_attribute_debug<Out, T>::call(out, val);
1318 }
1319
1320 template <typename Out>
1321 inline void print_attribute(Out&, unused_type)
1322 {
1323 }
1324
1325 ///////////////////////////////////////////////////////////////////////////
1326 // generate debug output for lookahead token (character) stream
1327 namespace detail
1328 {
1329 struct token_printer_debug_for_chars
1330 {
1331 template<typename Out, typename Char>
1332 static void print(Out& o, Char c)
1333 {
1334 using namespace std; // allow for ADL to find the proper iscntrl
1335
1336 if (c == static_cast<Char>('\a'))
1337 o << "\\a";
1338 else if (c == static_cast<Char>('\b'))
1339 o << "\\b";
1340 else if (c == static_cast<Char>('\f'))
1341 o << "\\f";
1342 else if (c == static_cast<Char>('\n'))
1343 o << "\\n";
1344 else if (c == static_cast<Char>('\r'))
1345 o << "\\r";
1346 else if (c == static_cast<Char>('\t'))
1347 o << "\\t";
1348 else if (c == static_cast<Char>('\v'))
1349 o << "\\v";
1350 else if (c >= 0 && c < 127 && iscntrl(c))
1351 o << "\\" << std::oct << static_cast<int>(c);
1352 else
1353 o << static_cast<char>(c);
1354 }
1355 };
1356
1357 // for token types where the comparison with char constants wouldn't work
1358 struct token_printer_debug
1359 {
1360 template<typename Out, typename T>
1361 static void print(Out& o, T const& val)
1362 {
1363 o << val;
1364 }
1365 };
1366 }
1367
1368 template <typename T, typename Enable>
1369 struct token_printer_debug
1370 : mpl::if_<
1371 mpl::and_<
1372 is_convertible<T, char>, is_convertible<char, T> >
1373 , detail::token_printer_debug_for_chars
1374 , detail::token_printer_debug>::type
1375 {};
1376
1377 template <typename Out, typename T>
1378 inline void print_token(Out& out, T const& val)
1379 {
1380 // allow to customize the token printer routine
1381 token_printer_debug<T>::print(out, val);
1382 }
1383 }}}
1384
1385 ///////////////////////////////////////////////////////////////////////////////
1386 namespace boost { namespace spirit { namespace result_of
1387 {
1388 template <typename Exposed, typename Transformed, typename Domain>
1389 struct pre_transform
1390 : traits::transform_attribute<Exposed, Transformed, Domain>
1391 {};
1392 }}}
1393
1394
1395 #endif