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