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/proto_fwd.hpp>
44 #include <boost/utility/enable_if.hpp>
45 #include <boost/variant.hpp>
46 #include <boost/range/iterator_range.hpp>
47 #include <boost/config.hpp>
48 #include <iterator> // for std::iterator_traits, std::distance
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     // we treat every type as if it where the variant (as this meta function is
283     // invoked for variant types only)
284     template <typename T>
285     struct variant_type
286       : mpl::identity<T>
287     {};
288 
289     template <typename T>
290     struct variant_type<boost::optional<T> >
291       : variant_type<T>
292     {};
293 
294     template <typename T, typename Domain>
295     struct not_is_variant_or_variant_in_optional
296       : not_is_variant<typename variant_type<T>::type, Domain>
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<typename variant_type<Variant>::type> >::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
is_compatibleboost::spirit::traits::compute_compatible_component_variant366         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 not_is_variant_or_variant_in_optional<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     {
callboost::spirit::traits::variant_which394         static int call(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& v)
395         {
396             return v.which();
397         }
398     };
399 
400     template <typename T>
which(T const & v)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 
callboost::spirit::traits::detail::attribute_size_impl478             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 
callboost::spirit::traits::detail::attribute_size_impl495             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 
callboost::spirit::traits::detail::attribute_size_impl512             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 
callboost::spirit::traits::attribute_size529         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>
operator ()boost::spirit::traits::detail::attribute_size_visitor542             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 
callboost::spirit::traits::attribute_size554         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 std::iterator_traits<Iterator>::
564             difference_type type;
565 
callboost::spirit::traits::attribute_size566         static type call(iterator_range<Iterator> const& r)
567         {
568             return std::distance(r.begin(), r.end());
569         }
570     };
571 
572     template <>
573     struct attribute_size<unused_type>
574     {
575         typedef std::size_t type;
576 
callboost::spirit::traits::attribute_size577         static type call(unused_type)
578         {
579             return 0;
580         }
581     };
582 
583     template <typename Attribute>
584     typename attribute_size<Attribute>::type
size(Attribute const & attr)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     namespace detail {
928         // Domain-agnostic class template partial specializations and
929         // type agnostic domain partial specializations are ambious.
930         // To resolve the ambiguity type agnostic domain partial
931         // specializations are dispatched via intermediate type.
932         template <typename Exposed, typename Transformed, typename Domain>
933         struct transform_attribute_base;
934 
935         template <typename Attribute>
936         struct synthesize_attribute
937         {
938             typedef Attribute type;
preboost::spirit::traits::detail::synthesize_attribute939             static Attribute pre(unused_type) { return Attribute(); }
postboost::spirit::traits::detail::synthesize_attribute940             static void post(unused_type, Attribute const&) {}
failboost::spirit::traits::detail::synthesize_attribute941             static void fail(unused_type) {}
942         };
943     }
944     ///////////////////////////////////////////////////////////////////////////
945     //  transform_attribute
946     //
947     //  Sometimes the user needs to transform the attribute types for certain
948     //  attributes. This template can be used as a customization point, where
949     //  the user is able specify specific transformation rules for any attribute
950     //  type.
951     //
952     //  Note: the transformations involving unused_type are internal details
953     //  and may be subject to change at any time.
954     //
955     ///////////////////////////////////////////////////////////////////////////
956     template <typename Exposed, typename Transformed, typename Domain
957       , typename Enable/* = void*/>
958     struct transform_attribute
959       : detail::transform_attribute_base<Exposed, Transformed, Domain>
960     {
961         BOOST_STATIC_ASSERT_MSG(!is_reference<Exposed>::value,
962             "Exposed cannot be a reference type");
963         BOOST_STATIC_ASSERT_MSG(!is_reference<Transformed>::value,
964             "Transformed cannot be a reference type");
965     };
966 
967     template <typename Transformed, typename Domain>
968     struct transform_attribute<unused_type, Transformed, Domain>
969       : detail::synthesize_attribute<Transformed>
970     {};
971 
972     template <typename Transformed, typename Domain>
973     struct transform_attribute<unused_type const, Transformed, Domain>
974       : detail::synthesize_attribute<Transformed>
975     {};
976 
977     ///////////////////////////////////////////////////////////////////////////
978     // swap_impl
979     //
980     // Swap (with proper handling of unused_types)
981     ///////////////////////////////////////////////////////////////////////////
982     template <typename A, typename B>
swap_impl(A & a,B & b)983     void swap_impl(A& a, B& b)
984     {
985         A temp = a;
986         a = b;
987         b = temp;
988     }
989 
990     template <typename T>
swap_impl(T & a,T & b)991     void swap_impl(T& a, T& b)
992     {
993         boost::swap(a, b);
994     }
995 
996     template <typename A>
swap_impl(A &,unused_type)997     void swap_impl(A&, unused_type)
998     {
999     }
1000 
1001     template <typename A>
swap_impl(unused_type,A &)1002     void swap_impl(unused_type, A&)
1003     {
1004     }
1005 
swap_impl(unused_type,unused_type)1006     inline void swap_impl(unused_type, unused_type)
1007     {
1008     }
1009 
1010     ///////////////////////////////////////////////////////////////////////////
1011     //  Strips single element fusion vectors into its 'naked'
1012     //  form: vector<T> --> T
1013     ///////////////////////////////////////////////////////////////////////////
1014     template <typename T>
1015     struct strip_single_element_vector
1016     {
1017         typedef T type;
1018     };
1019 
1020 #if !defined(BOOST_FUSION_HAS_VARIADIC_VECTOR)
1021     template <typename T>
1022     struct strip_single_element_vector<fusion::vector1<T> >
1023     {
1024         typedef T type;
1025     };
1026 #endif
1027     template <typename T>
1028     struct strip_single_element_vector<fusion::vector<T> >
1029     {
1030         typedef T type;
1031     };
1032 
1033     ///////////////////////////////////////////////////////////////////////////
1034     // meta function to return whether the argument is a one element fusion
1035     // sequence
1036     ///////////////////////////////////////////////////////////////////////////
1037     template <typename T
1038       , bool IsFusionSeq = fusion::traits::is_sequence<T>::value
1039       , bool IsProtoExpr = proto::is_expr<T>::value>
1040     struct one_element_sequence
1041       : mpl::false_
1042     {};
1043 
1044     template <typename T>
1045     struct one_element_sequence<T, true, false>
1046       : mpl::bool_<mpl::size<T>::value == 1>
1047     {};
1048 
1049     ///////////////////////////////////////////////////////////////////////////
1050     // clear
1051     //
1052     // Clear data efficiently
1053     ///////////////////////////////////////////////////////////////////////////
1054     template <typename T>
1055     void clear(T& val);
1056 
1057     namespace detail
1058     {
1059         // this is used by the variant and fusion sequence dispatch
1060         struct clear_visitor : static_visitor<>
1061         {
1062             template <typename T>
operator ()boost::spirit::traits::detail::clear_visitor1063             void operator()(T& val) const
1064             {
1065                 spirit::traits::clear(val);
1066             }
1067         };
1068 
1069         // default
1070         template <typename T>
clear_impl2(T & val,mpl::false_)1071         void clear_impl2(T& val, mpl::false_)
1072         {
1073             val = T();
1074         }
1075 
1076         // for fusion sequences
1077         template <typename T>
clear_impl2(T & val,mpl::true_)1078         void clear_impl2(T& val, mpl::true_)
1079         {
1080             fusion::for_each(val, clear_visitor());
1081         }
1082 
1083         // dispatch default or fusion sequence
1084         template <typename T>
clear_impl(T & val,mpl::false_)1085         void clear_impl(T& val, mpl::false_)
1086         {
1087             clear_impl2(val, fusion::traits::is_sequence<T>());
1088         }
1089 
1090         // STL containers
1091         template <typename T>
clear_impl(T & val,mpl::true_)1092         void clear_impl(T& val, mpl::true_)
1093         {
1094             val.clear();
1095         }
1096     }
1097 
1098     template <typename T, typename Enable/* = void*/>
1099     struct clear_value
1100     {
callboost::spirit::traits::clear_value1101         static void call(T& val)
1102         {
1103             detail::clear_impl(val, typename is_container<T>::type());
1104         }
1105     };
1106 
1107     // optionals
1108     template <typename T>
1109     struct clear_value<boost::optional<T> >
1110     {
callboost::spirit::traits::clear_value1111         static void call(boost::optional<T>& val)
1112         {
1113             if (val)
1114                 val = none;   // leave optional uninitialized
1115         }
1116     };
1117 
1118     // variants
1119     template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
1120     struct clear_value<variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
1121     {
callboost::spirit::traits::clear_value1122         static void call(variant<BOOST_VARIANT_ENUM_PARAMS(T)>& val)
1123         {
1124             apply_visitor(detail::clear_visitor(), val);
1125         }
1126     };
1127 
1128     // iterator range
1129     template <typename T>
1130     struct clear_value<iterator_range<T> >
1131     {
callboost::spirit::traits::clear_value1132         static void call(iterator_range<T>& val)
1133         {
1134             val = iterator_range<T>(val.end(), val.end());
1135         }
1136     };
1137 
1138     // main dispatch
1139     template <typename T>
clear(T & val)1140     void clear(T& val)
1141     {
1142         clear_value<T>::call(val);
1143     }
1144 
1145     // for unused
clear(unused_type)1146     inline void clear(unused_type)
1147     {
1148     }
1149 
1150     ///////////////////////////////////////////////////////////////////////////
1151     namespace detail
1152     {
1153         template <typename Out>
1154         struct print_fusion_sequence
1155         {
print_fusion_sequenceboost::spirit::traits::detail::print_fusion_sequence1156             print_fusion_sequence(Out& out_)
1157               : out(out_), is_first(true) {}
1158 
1159             typedef void result_type;
1160 
1161             template <typename T>
operator ()boost::spirit::traits::detail::print_fusion_sequence1162             void operator()(T const& val) const
1163             {
1164                 if (is_first)
1165                     is_first = false;
1166                 else
1167                     out << ", ";
1168                 spirit::traits::print_attribute(out, val);
1169             }
1170 
1171             Out& out;
1172             mutable bool is_first;
1173         };
1174 
1175         // print elements in a variant
1176         template <typename Out>
1177         struct print_visitor : static_visitor<>
1178         {
print_visitorboost::spirit::traits::detail::print_visitor1179             print_visitor(Out& out_) : out(out_) {}
1180 
1181             template <typename T>
operator ()boost::spirit::traits::detail::print_visitor1182             void operator()(T const& val) const
1183             {
1184                 spirit::traits::print_attribute(out, val);
1185             }
1186 
1187             Out& out;
1188         };
1189     }
1190 
1191     template <typename Out, typename T, typename Enable>
1192     struct print_attribute_debug
1193     {
1194         // for plain data types
1195         template <typename T_>
call_impl3boost::spirit::traits::print_attribute_debug1196         static void call_impl3(Out& out, T_ const& val, mpl::false_)
1197         {
1198             out << val;
1199         }
1200 
1201         // for fusion data types
1202         template <typename T_>
call_impl3boost::spirit::traits::print_attribute_debug1203         static void call_impl3(Out& out, T_ const& val, mpl::true_)
1204         {
1205             out << '[';
1206             fusion::for_each(val, detail::print_fusion_sequence<Out>(out));
1207             out << ']';
1208         }
1209 
1210         // non-stl container
1211         template <typename T_>
call_impl2boost::spirit::traits::print_attribute_debug1212         static void call_impl2(Out& out, T_ const& val, mpl::false_)
1213         {
1214             call_impl3(out, val, fusion::traits::is_sequence<T_>());
1215         }
1216 
1217         // stl container
1218         template <typename T_>
call_impl2boost::spirit::traits::print_attribute_debug1219         static void call_impl2(Out& out, T_ const& val, mpl::true_)
1220         {
1221             out << '[';
1222             if (!traits::is_empty(val))
1223             {
1224                 bool first = true;
1225                 typename container_iterator<T_ const>::type iend = traits::end(val);
1226                 for (typename container_iterator<T_ const>::type i = traits::begin(val);
1227                      !traits::compare(i, iend); traits::next(i))
1228                 {
1229                     if (!first)
1230                         out << ", ";
1231                     first = false;
1232                     spirit::traits::print_attribute(out, traits::deref(i));
1233                 }
1234             }
1235             out << ']';
1236         }
1237 
1238         // for variant types
1239         template <typename T_>
call_implboost::spirit::traits::print_attribute_debug1240         static void call_impl(Out& out, T_ const& val, mpl::false_)
1241         {
1242             apply_visitor(detail::print_visitor<Out>(out), val);
1243         }
1244 
1245         // for non-variant types
1246         template <typename T_>
call_implboost::spirit::traits::print_attribute_debug1247         static void call_impl(Out& out, T_ const& val, mpl::true_)
1248         {
1249             call_impl2(out, val, is_container<T_>());
1250         }
1251 
1252         // main entry point
callboost::spirit::traits::print_attribute_debug1253         static void call(Out& out, T const& val)
1254         {
1255             call_impl(out, val, not_is_variant<T>());
1256         }
1257     };
1258 
1259     template <typename Out, typename T>
1260     struct print_attribute_debug<Out, boost::optional<T> >
1261     {
callboost::spirit::traits::print_attribute_debug1262         static void call(Out& out, boost::optional<T> const& val)
1263         {
1264             if (val)
1265                 spirit::traits::print_attribute(out, *val);
1266             else
1267                 out << "[empty]";
1268         }
1269     };
1270 
1271     ///////////////////////////////////////////////////////////////////////////
1272     template <typename Out, typename T>
print_attribute(Out & out,T const & val)1273     inline void print_attribute(Out& out, T const& val)
1274     {
1275         print_attribute_debug<Out, T>::call(out, val);
1276     }
1277 
1278     template <typename Out>
print_attribute(Out &,unused_type)1279     inline void print_attribute(Out&, unused_type)
1280     {
1281     }
1282 
1283     ///////////////////////////////////////////////////////////////////////////
1284     // generate debug output for lookahead token (character) stream
1285     namespace detail
1286     {
1287         struct token_printer_debug_for_chars
1288         {
1289             template<typename Out, typename Char>
printboost::spirit::traits::detail::token_printer_debug_for_chars1290             static void print(Out& o, Char c)
1291             {
1292                 using namespace std;    // allow for ADL to find the proper iscntrl
1293 
1294                 if (c == static_cast<Char>('\a'))
1295                     o << "\\a";
1296                 else if (c == static_cast<Char>('\b'))
1297                     o << "\\b";
1298                 else if (c == static_cast<Char>('\f'))
1299                     o << "\\f";
1300                 else if (c == static_cast<Char>('\n'))
1301                     o << "\\n";
1302                 else if (c == static_cast<Char>('\r'))
1303                     o << "\\r";
1304                 else if (c == static_cast<Char>('\t'))
1305                     o << "\\t";
1306                 else if (c == static_cast<Char>('\v'))
1307                     o << "\\v";
1308                 else if (c >= 0 && c < 127 && iscntrl(c))
1309                     o << "\\" << std::oct << static_cast<int>(c);
1310                 else
1311                     o << static_cast<char>(c);
1312             }
1313         };
1314 
1315         // for token types where the comparison with char constants wouldn't work
1316         struct token_printer_debug
1317         {
1318             template<typename Out, typename T>
printboost::spirit::traits::detail::token_printer_debug1319             static void print(Out& o, T const& val)
1320             {
1321                 o << val;
1322             }
1323         };
1324     }
1325 
1326     template <typename T, typename Enable>
1327     struct token_printer_debug
1328       : mpl::if_<
1329             mpl::and_<
1330                 is_convertible<T, char>, is_convertible<char, T> >
1331           , detail::token_printer_debug_for_chars
1332           , detail::token_printer_debug>::type
1333     {};
1334 
1335     template <typename Out, typename T>
print_token(Out & out,T const & val)1336     inline void print_token(Out& out, T const& val)
1337     {
1338         // allow to customize the token printer routine
1339         token_printer_debug<T>::print(out, val);
1340     }
1341 }}}
1342 
1343 #endif
1344