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/sequence/intrinsic/ext_/segments.hpp>
22 #include <boost/fusion/support/ext_/is_segmented.hpp>
23 #include <boost/fusion/view/ext_/segmented_iterator.hpp>
24 
25 namespace boost { namespace fusion
26 {
27    struct tree_tag;
28 
29    namespace detail
30    {
31        template<typename T, bool IsConst>
32        struct reference : add_reference<T> {};
33 
34        template<typename T>
35        struct reference<T, true> : reference<typename add_const<T>::type, false> {};
36 
37        template<typename T>
38        struct reference<T &, true> : reference<T, false> {};
39    }
40 
41    template<typename Data, typename Left = nil, typename Right = nil>
42    struct tree
43      : sequence_base<tree<Data, Left, Right> >
44    {
45        typedef Data data_type;
46        typedef Left left_type;
47        typedef Right right_type;
48        typedef tree_tag fusion_tag;
49        typedef forward_traversal_tag category;
50        typedef mpl::false_ is_view;
51 
52        typedef typename mpl::if_<
53            traits::is_sequence<Data>
54          , Data
55          , single_view<Data>
56        >::type data_view;
57 
treeboost::fusion::tree58        explicit tree(
59            typename fusion::detail::call_param<Data>::type data_
60          , typename fusion::detail::call_param<Left>::type left_ = Left()
61          , typename fusion::detail::call_param<Right>::type right_ = Right()
62        )
63          : segments(left_, data_view(data_), right_)
64        {}
65 
66        typedef vector3<Left, data_view, Right> segments_type;
67        segments_type segments;
68    };
69 
70    template<typename Data>
make_tree(Data const & data)71    tree<Data> make_tree(Data const &data)
72    {
73        return tree<Data>(data);
74    }
75 
76    template<typename Data, typename Left, typename Right>
make_tree(Data const & data,Left const & left,Right const & right)77    tree<Data, Left, Right> make_tree(Data const &data, Left const &left, Right const &right)
78    {
79        return tree<Data, Left, Right>(data, left, right);
80    }
81 
82    namespace extension
83    {
84        template<>
85        struct is_segmented_impl<tree_tag>
86        {
87            template<typename Sequence>
88            struct apply : mpl::true_ {};
89        };
90 
91        template<>
92        struct segments_impl<tree_tag>
93        {
94            template<typename Sequence>
95            struct apply
96            {
97                typedef typename mpl::if_<
98                    is_const<Sequence>
99                  , typename Sequence::segments_type const &
100                  , typename Sequence::segments_type &
101                >::type type;
102 
callboost::fusion::extension::segments_impl::apply103                static type call(Sequence &seq)
104                {
105                    return seq.segments;
106                }
107            };
108        };
109 
110        template<>
111        struct begin_impl<tree_tag>
112        {
113            template<typename Sequence>
114            struct apply
115              : segmented_begin<Sequence>
116            {};
117        };
118 
119        template<>
120        struct end_impl<tree_tag>
121        {
122            template<typename Sequence>
123            struct apply
124              : segmented_end<Sequence>
125            {};
126        };
127    }
128 }}
129 
130 #endif
131