fix doc example typo
[boost.git] / boost / proto / fusion.hpp
blob8657fa6c578b33b4ecf6af5886a765c7001ba43f
1 ///////////////////////////////////////////////////////////////////////////////
2 /// \file fusion.hpp
3 /// Make any Proto expression a valid Fusion sequence
4 //
5 // Copyright 2008 Eric Niebler. Distributed under the Boost
6 // Software License, Version 1.0. (See accompanying file
7 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9 #ifndef BOOST_PROTO_FUSION_HPP_EAN_11_04_2006
10 #define BOOST_PROTO_FUSION_HPP_EAN_11_04_2006
12 #include <boost/proto/detail/prefix.hpp>
13 #include <boost/config.hpp>
14 #include <boost/version.hpp>
15 #include <boost/type_traits/remove_reference.hpp>
16 #include <boost/mpl/if.hpp>
17 #include <boost/mpl/long.hpp>
18 #include <boost/mpl/sequence_tag_fwd.hpp>
19 #if BOOST_VERSION >= 103500
20 #include <boost/fusion/include/is_view.hpp>
21 #include <boost/fusion/include/tag_of_fwd.hpp>
22 #include <boost/fusion/include/category_of.hpp>
23 #include <boost/fusion/include/iterator_base.hpp>
24 #include <boost/fusion/include/intrinsic.hpp>
25 #include <boost/fusion/include/pop_front.hpp>
26 #include <boost/fusion/include/reverse.hpp>
27 #include <boost/fusion/include/single_view.hpp>
28 #include <boost/fusion/include/transform_view.hpp>
29 #include <boost/fusion/support/ext_/is_segmented.hpp>
30 #include <boost/fusion/sequence/intrinsic/ext_/segments.hpp>
31 #include <boost/fusion/sequence/intrinsic/ext_/size_s.hpp>
32 #include <boost/fusion/view/ext_/segmented_iterator.hpp>
33 #else
34 #include <boost/spirit/fusion/sequence/is_sequence.hpp>
35 #include <boost/spirit/fusion/sequence/begin.hpp>
36 #include <boost/spirit/fusion/sequence/end.hpp>
37 #include <boost/spirit/fusion/sequence/at.hpp>
38 #include <boost/spirit/fusion/sequence/value_at.hpp>
39 #include <boost/spirit/fusion/sequence/single_view.hpp>
40 #include <boost/spirit/fusion/sequence/transform_view.hpp>
41 #include <boost/proto/detail/reverse.hpp>
42 #include <boost/proto/detail/pop_front.hpp>
43 #endif
44 #include <boost/proto/proto_fwd.hpp>
45 #include <boost/proto/traits.hpp>
46 #include <boost/proto/eval.hpp>
47 #include <boost/proto/detail/suffix.hpp>
49 #if BOOST_MSVC
50 #pragma warning(push)
51 #pragma warning(disable : 4510) // default constructor could not be generated
52 #pragma warning(disable : 4512) // assignment operator could not be generated
53 #pragma warning(disable : 4610) // can never be instantiated - user defined constructor required
54 #endif
56 namespace boost { namespace proto
59 /// INTERNAL ONLY
60 ///
61 #define UNREF(x) typename boost::remove_reference<x>::type
63 namespace detail
66 template<typename Expr, long Pos>
67 struct expr_iterator
68 : fusion::iterator_base<expr_iterator<Expr, Pos> >
70 typedef Expr expr_type;
71 typedef typename Expr::proto_tag proto_tag;
72 BOOST_STATIC_CONSTANT(long, index = Pos);
73 BOOST_PROTO_FUSION_DEFINE_CATEGORY(fusion::random_access_traversal_tag)
74 BOOST_PROTO_FUSION_DEFINE_TAG(tag::proto_expr_iterator)
76 expr_iterator(Expr const &e)
77 : expr(e)
80 Expr const &expr;
83 template<typename Expr>
84 struct flat_view
86 typedef Expr expr_type;
87 typedef typename Expr::proto_tag proto_tag;
88 BOOST_PROTO_FUSION_DEFINE_CATEGORY(fusion::forward_traversal_tag)
89 BOOST_PROTO_FUSION_DEFINE_TAG(tag::proto_flat_view)
91 explicit flat_view(Expr &expr)
92 : expr_(expr)
95 Expr &expr_;
98 template<typename Tag>
99 struct as_element
101 template<typename Sig>
102 struct result;
104 template<typename This, typename Expr>
105 struct result<This(Expr)>
106 : mpl::if_<
107 is_same<Tag, UNREF(Expr)::proto_tag>
108 , flat_view<UNREF(Expr) const>
109 , fusion::single_view<UNREF(Expr) const &>
113 template<typename Expr>
114 typename result<as_element(Expr const &)>::type
115 operator ()(Expr const &expr) const
117 return typename result<as_element(Expr const &)>::type(expr);
122 namespace result_of
124 template<typename Expr>
125 struct flatten
127 typedef detail::flat_view<Expr const> type;
130 template<typename Expr>
131 struct flatten<Expr &>
133 typedef detail::flat_view<Expr const> type;
137 namespace functional
139 /// \brief A PolymorphicFunctionObject type that returns a "flattened"
140 /// view of a Proto expression tree.
142 /// A PolymorphicFunctionObject type that returns a "flattened"
143 /// view of a Proto expression tree. For a tree with a top-most node
144 /// tag of type \c T, the elements of the flattened sequence are
145 /// determined by recursing into each child node with the same
146 /// tag type and returning those nodes of different type. So for
147 /// instance, the Proto expression tree corresponding to the
148 /// expression <tt>a | b | c</tt> has a flattened view with elements
149 /// [a, b, c], even though the tree is grouped as
150 /// <tt>((a | b) | c)</tt>.
151 struct flatten
153 BOOST_PROTO_CALLABLE()
155 template<typename Sig>
156 struct result;
158 template<typename This, typename Expr>
159 struct result<This(Expr)>
161 typedef proto::detail::flat_view<UNREF(Expr) const> type;
164 template<typename Expr>
165 proto::detail::flat_view<Expr const>
166 operator ()(Expr const &expr) const
168 return proto::detail::flat_view<Expr const>(expr);
172 /// \brief A PolymorphicFunctionObject type that invokes the
173 /// \c fusion::pop_front() algorithm on its argument.
175 /// A PolymorphicFunctionObject type that invokes the
176 /// \c fusion::pop_front() algorithm on its argument. This is
177 /// useful for defining a CallableTransform like \c pop_front(_)
178 /// which removes the first child from a Proto expression node.
179 /// Such a transform might be used as the first argument to the
180 /// \c proto::fold\<\> transform; that is, fold all but
181 /// the first child.
182 struct pop_front
184 BOOST_PROTO_CALLABLE()
186 template<typename Sig>
187 struct result;
189 template<typename This, typename Expr>
190 struct result<This(Expr)>
192 typedef
193 typename fusion::BOOST_PROTO_FUSION_RESULT_OF::pop_front<UNREF(Expr) const>::type
194 type;
197 template<typename Expr>
198 typename fusion::BOOST_PROTO_FUSION_RESULT_OF::pop_front<Expr const>::type
199 operator ()(Expr const &expr) const
201 return fusion::pop_front(expr);
205 /// \brief A PolymorphicFunctionObject type that invokes the
206 /// \c fusion::reverse() algorithm on its argument.
208 /// A PolymorphicFunctionObject type that invokes the
209 /// \c fusion::reverse() algorithm on its argument. This is
210 /// useful for defining a CallableTransform like \c reverse(_)
211 /// which reverses the order of the children of a Proto
212 /// expression node.
213 struct reverse
215 BOOST_PROTO_CALLABLE()
217 template<typename Sig>
218 struct result;
220 template<typename This, typename Expr>
221 struct result<This(Expr)>
223 typedef
224 typename fusion::BOOST_PROTO_FUSION_RESULT_OF::reverse<UNREF(Expr) const>::type
225 type;
228 template<typename Expr>
229 typename fusion::BOOST_PROTO_FUSION_RESULT_OF::reverse<Expr const>::type
230 operator ()(Expr const &expr) const
232 return fusion::reverse(expr);
237 /// \brief A function that returns a "flattened"
238 /// view of a Proto expression tree.
240 /// For a tree with a top-most node
241 /// tag of type \c T, the elements of the flattened sequence are
242 /// determined by recursing into each child node with the same
243 /// tag type and returning those nodes of different type. So for
244 /// instance, the Proto expression tree corresponding to the
245 /// expression <tt>a | b | c</tt> has a flattened view with elements
246 /// [a, b, c], even though the tree is grouped as
247 /// <tt>((a | b) | c)</tt>.
248 template<typename Expr>
249 proto::detail::flat_view<Expr const>
250 flatten(Expr const &expr)
252 return proto::detail::flat_view<Expr const>(expr);
255 /// INTERNAL ONLY
257 template<>
258 struct is_callable<functional::flatten>
259 : mpl::true_
262 /// INTERNAL ONLY
264 template<>
265 struct is_callable<functional::pop_front>
266 : mpl::true_
269 /// INTERNAL ONLY
271 template<>
272 struct is_callable<functional::reverse>
273 : mpl::true_
276 /// INTERNAL ONLY
278 template<typename Context>
279 struct eval_fun
281 explicit eval_fun(Context &ctx)
282 : ctx_(ctx)
285 template<typename Sig>
286 struct result;
288 template<typename This, typename Expr>
289 struct result<This(Expr)>
291 typedef
292 typename proto::result_of::eval<UNREF(Expr), Context>::type
293 type;
296 template<typename Expr>
297 typename proto::result_of::eval<Expr, Context>::type
298 operator ()(Expr &expr) const
300 return proto::eval(expr, this->ctx_);
303 private:
304 Context &ctx_;
308 // Don't bother emitting all this into the Doxygen-generated
309 // reference section. It's enough to say that Proto expressions
310 // are valid Fusion sequence without showing all this gunk.
311 #ifndef BOOST_PROTO_BUILDING_DOCS
313 namespace boost { namespace fusion
315 #if BOOST_VERSION < 103500
316 template<typename Tag, typename Args, long Arity>
317 struct is_sequence<proto::expr<Tag, Args, Arity> >
318 : mpl::true_
321 template<typename Tag, typename Args, long Arity>
322 struct is_sequence<proto::expr<Tag, Args, Arity> const>
323 : mpl::true_
325 #endif
327 namespace BOOST_PROTO_FUSION_EXTENSION
330 template<typename Tag>
331 struct is_view_impl;
333 template<>
334 struct is_view_impl<proto::tag::proto_flat_view>
336 template<typename Sequence>
337 struct apply
338 : mpl::true_
342 template<>
343 struct is_view_impl<proto::tag::proto_expr>
345 template<typename Sequence>
346 struct apply
347 : mpl::false_
351 template<typename Tag>
352 struct value_of_impl;
354 template<>
355 struct value_of_impl<proto::tag::proto_expr_iterator>
357 template<
358 typename Iterator
359 , long Arity = proto::arity_of<typename Iterator::expr_type>::value
361 struct apply
363 typedef
364 typename proto::result_of::child_c<
365 typename Iterator::expr_type
366 , Iterator::index
367 >::value_type
368 type;
371 template<typename Iterator>
372 struct apply<Iterator, 0>
374 typedef
375 typename proto::result_of::value<
376 typename Iterator::expr_type
377 >::value_type
378 type;
382 #if BOOST_VERSION < 103500
383 template<typename Tag>
384 struct value_impl;
386 template<>
387 struct value_impl<proto::tag::proto_expr_iterator>
388 : value_of_impl<proto::tag::proto_expr_iterator>
390 #endif
392 template<typename Tag>
393 struct deref_impl;
395 template<>
396 struct deref_impl<proto::tag::proto_expr_iterator>
398 template<
399 typename Iterator
400 , long Arity = proto::arity_of<typename Iterator::expr_type>::value
402 struct apply
404 typedef
405 typename proto::result_of::child_c<
406 typename Iterator::expr_type const &
407 , Iterator::index
408 >::type
409 type;
411 static type call(Iterator const &iter)
413 return proto::child_c<Iterator::index>(iter.expr);
417 template<typename Iterator>
418 struct apply<Iterator, 0>
420 typedef
421 typename proto::result_of::value<
422 typename Iterator::expr_type const &
423 >::type
424 type;
426 static type call(Iterator const &iter)
428 return proto::value(iter.expr);
433 template<typename Tag>
434 struct advance_impl;
436 template<>
437 struct advance_impl<proto::tag::proto_expr_iterator>
439 template<typename Iterator, typename N>
440 struct apply
442 typedef
443 typename proto::detail::expr_iterator<
444 typename Iterator::expr_type
445 , Iterator::index + N::value
447 type;
449 static type call(Iterator const &iter)
451 return type(iter.expr);
456 template<typename Tag>
457 struct distance_impl;
459 template<>
460 struct distance_impl<proto::tag::proto_expr_iterator>
462 template<typename IteratorFrom, typename IteratorTo>
463 struct apply
464 : mpl::long_<IteratorTo::index - IteratorFrom::index>
468 template<typename Tag>
469 struct next_impl;
471 template<>
472 struct next_impl<proto::tag::proto_expr_iterator>
474 template<typename Iterator>
475 struct apply
476 : advance_impl<proto::tag::proto_expr_iterator>::template apply<Iterator, mpl::long_<1> >
480 template<typename Tag>
481 struct prior_impl;
483 template<>
484 struct prior_impl<proto::tag::proto_expr_iterator>
486 template<typename Iterator>
487 struct apply
488 : advance_impl<proto::tag::proto_expr_iterator>::template apply<Iterator, mpl::long_<-1> >
492 #if BOOST_VERSION >= 103500
493 template<typename Tag>
494 struct category_of_impl;
496 template<>
497 struct category_of_impl<proto::tag::proto_expr>
499 template<typename Sequence>
500 struct apply
502 typedef random_access_traversal_tag type;
505 #endif
507 template<typename Tag>
508 struct size_impl;
510 template<>
511 struct size_impl<proto::tag::proto_expr>
513 template<typename Sequence>
514 struct apply
515 : mpl::long_<0 == Sequence::proto_arity_c ? 1 : Sequence::proto_arity_c>
519 template<typename Tag>
520 struct begin_impl;
522 template<>
523 struct begin_impl<proto::tag::proto_expr>
525 template<typename Sequence>
526 struct apply
528 typedef proto::detail::expr_iterator<Sequence, 0> type;
530 static type call(Sequence const &seq)
532 return type(seq);
537 template<typename Tag>
538 struct end_impl;
540 template<>
541 struct end_impl<proto::tag::proto_expr>
543 template<typename Sequence>
544 struct apply
546 typedef
547 proto::detail::expr_iterator<
548 Sequence
549 , 0 == Sequence::proto_arity_c ? 1 : Sequence::proto_arity_c
551 type;
553 static type call(Sequence const &seq)
555 return type(seq);
560 template<typename Tag>
561 struct value_at_impl;
563 template<>
564 struct value_at_impl<proto::tag::proto_expr>
566 template<
567 typename Sequence
568 , typename Index
569 , long Arity = proto::arity_of<Sequence>::value
571 struct apply
573 typedef
574 typename proto::result_of::child_c<
575 Sequence
576 , Index::value
577 >::value_type
578 type;
581 template<typename Sequence, typename Index>
582 struct apply<Sequence, Index, 0>
584 typedef
585 typename proto::result_of::value<
586 Sequence
587 >::value_type
588 type;
592 template<typename Tag>
593 struct at_impl;
595 template<>
596 struct at_impl<proto::tag::proto_expr>
598 template<
599 typename Sequence
600 , typename Index
601 , long Arity = proto::arity_of<Sequence>::value
603 struct apply
605 typedef
606 typename proto::result_of::child_c<
607 Sequence &
608 , Index::value
609 >::type
610 type;
612 static type call(Sequence &seq)
614 return proto::child_c<Index::value>(seq);
618 template<typename Sequence, typename Index>
619 struct apply<Sequence, Index, 0>
621 typedef
622 typename proto::result_of::value<
623 Sequence &
624 >::type
625 type;
627 static type call(Sequence &seq)
629 return proto::value(seq);
634 #if BOOST_VERSION >= 103500
635 template<typename Tag>
636 struct is_segmented_impl;
638 template<>
639 struct is_segmented_impl<proto::tag::proto_flat_view>
641 template<typename Iterator>
642 struct apply
643 : mpl::true_
647 template<typename Tag>
648 struct segments_impl;
650 template<>
651 struct segments_impl<proto::tag::proto_flat_view>
653 template<typename Sequence>
654 struct apply
656 typedef typename Sequence::proto_tag proto_tag;
658 typedef fusion::transform_view<
659 typename Sequence::expr_type
660 , proto::detail::as_element<proto_tag>
661 > type;
663 static type call(Sequence &sequence)
665 return type(sequence.expr_, proto::detail::as_element<proto_tag>());
670 template<>
671 struct category_of_impl<proto::tag::proto_flat_view>
673 template<typename Sequence>
674 struct apply
676 typedef forward_traversal_tag type;
680 template<>
681 struct begin_impl<proto::tag::proto_flat_view>
683 template<typename Sequence>
684 struct apply
685 : fusion::segmented_begin<Sequence>
689 template<>
690 struct end_impl<proto::tag::proto_flat_view>
692 template<typename Sequence>
693 struct apply
694 : fusion::segmented_end<Sequence>
698 template<>
699 struct size_impl<proto::tag::proto_flat_view>
701 template<typename Sequence>
702 struct apply
703 : fusion::segmented_size<Sequence>
706 #endif
712 namespace boost { namespace mpl
714 template<typename Tag, typename Args, long Arity>
715 struct sequence_tag< proto::expr<Tag, Args, Arity> >
717 typedef fusion::fusion_sequence_tag type;
721 #endif // BOOST_PROTO_BUILDING_DOCS
723 #undef UNREF
725 #if BOOST_MSVC
726 #pragma warning(pop)
727 #endif
729 #endif