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

source code of boost/libs/spirit/include/boost/spirit/home/support/attributes.hpp