1 /*=============================================================================
2    Copyright (c) 2006 Eric Niebler
3 
4    Use, modification and distribution is subject to the Boost Software
5    License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
6    http://www.boost.org/LICENSE_1_0.txt)
7 ==============================================================================*/
8 #ifndef FUSION_BINARY_TREE_EAN_05032006_1027
9 #define FUSION_BINARY_TREE_EAN_05032006_1027
10 
11 #include <boost/mpl/if.hpp>
12 #include <boost/type_traits/is_const.hpp>
13 #include <boost/type_traits/add_const.hpp>
14 #include <boost/type_traits/add_reference.hpp>
15 #include <boost/fusion/support/is_sequence.hpp>
16 #include <boost/fusion/sequence/intrinsic/at.hpp>
17 #include <boost/fusion/view/single_view.hpp>
18 #include <boost/fusion/container/list/cons.hpp> // for nil
19 #include <boost/fusion/container/vector/vector10.hpp>
20 #include <boost/fusion/support/sequence_base.hpp>
21 #include <boost/fusion/support/category_of.hpp>
22 #include <boost/fusion/support/is_segmented.hpp>
23 #include <boost/fusion/sequence/intrinsic/segments.hpp>
24 
25 namespace boost { namespace fusion
26 {
27    struct tree_tag;
28 
29    template <typename Data, typename Left = nil, typename Right = nil>
30    struct tree
31      : sequence_base<tree<Data, Left, Right> >
32    {
33        typedef Data data_type;
34        typedef Left left_type;
35        typedef Right right_type;
36        typedef tree_tag fusion_tag;
37        typedef forward_traversal_tag category;
38        typedef mpl::false_ is_view;
39 
40        typedef typename mpl::if_<
41            traits::is_sequence<Data>
42          , Data
43          , single_view<Data>
44        >::type data_view;
45 
treeboost::fusion::tree46        explicit tree(
47            typename fusion::detail::call_param<Data>::type data_
48          , typename fusion::detail::call_param<Left>::type left_ = Left()
49          , typename fusion::detail::call_param<Right>::type right_ = Right()
50        )
51          : segments(left_, data_view(data_), right_)
52        {}
53 
54        typedef vector3<Left, data_view, Right> segments_type;
55        segments_type segments;
56    };
57 
58    template <typename Data>
make_tree(Data const & data)59    tree<Data> make_tree(Data const &data)
60    {
61        return tree<Data>(data);
62    }
63 
64    template <typename Data, typename Left, typename Right>
make_tree(Data const & data,Left const & left,Right const & right)65    tree<Data, Left, Right> make_tree(Data const &data, Left const &left, Right const &right)
66    {
67        return tree<Data, Left, Right>(data, left, right);
68    }
69 
70    namespace extension
71    {
72        template <>
73        struct is_segmented_impl<tree_tag>
74        {
75            template <typename Sequence>
76            struct apply : mpl::true_ {};
77        };
78 
79        template <>
80        struct segments_impl<tree_tag>
81        {
82            template <typename Sequence>
83            struct apply
84            {
85                typedef typename mpl::if_<
86                    is_const<Sequence>
87                  , typename Sequence::segments_type const &
88                  , typename Sequence::segments_type &
89                >::type type;
90 
callboost::fusion::extension::segments_impl::apply91                static type call(Sequence &seq)
92                {
93                    return seq.segments;
94                }
95            };
96        };
97    }
98 }}
99 
100 #endif
101