1 /////////////////////////////////////////////////////////////////////////////// 2 // cons.hpp 3 // 4 // Copyright 2008 Eric Niebler. Distributed under the Boost 5 // Software License, Version 1.0. (See accompanying file 6 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 8 #ifndef BOOST_XPRESSIVE_DETAIL_UTILITY_CONS_HPP_EAN_11_19_2005 9 #define BOOST_XPRESSIVE_DETAIL_UTILITY_CONS_HPP_EAN_11_19_2005 10 11 #include <boost/version.hpp> 12 13 #if BOOST_VERSION >= 103300 14 15 // In Boost 1.33+, we have a cons list in Fusion, so just include it. 16 17 # if BOOST_VERSION >= 103500 18 # include <boost/fusion/include/cons.hpp> // Boost 1.35+ has Fusion2 19 # else 20 # include <boost/spirit/fusion/sequence/cons.hpp> // Fusion1 21 # endif 22 23 #else 24 25 // For earlier versions of Boost, put the definition of cons here 26 # include <boost/call_traits.hpp> 27 # include <boost/mpl/if.hpp> 28 # include <boost/mpl/eval_if.hpp> 29 # include <boost/mpl/identity.hpp> 30 # include <boost/type_traits/is_const.hpp> 31 # include <boost/type_traits/add_const.hpp> 32 # include <boost/type_traits/add_reference.hpp> 33 # include <boost/spirit/fusion/detail/config.hpp> 34 # include <boost/spirit/fusion/detail/access.hpp> 35 # include <boost/spirit/fusion/iterator/next.hpp> 36 # include <boost/spirit/fusion/iterator/equal_to.hpp> 37 # include <boost/spirit/fusion/iterator/as_fusion_iterator.hpp> 38 # include <boost/spirit/fusion/iterator/detail/iterator_base.hpp> 39 # include <boost/spirit/fusion/sequence/begin.hpp> 40 # include <boost/spirit/fusion/sequence/end.hpp> 41 # include <boost/spirit/fusion/sequence/as_fusion_sequence.hpp> 42 # include <boost/spirit/fusion/sequence/detail/sequence_base.hpp> 43 44 namespace boost { namespace fusion 45 { 46 struct nil; 47 48 struct cons_tag; 49 50 template <typename Car, typename Cdr> 51 struct cons; 52 53 struct cons_iterator_tag; 54 55 template <typename Cons> 56 struct cons_iterator; 57 58 namespace cons_detail 59 { 60 template <typename Iterator> 61 struct deref_traits_impl 62 { 63 typedef typename Iterator::cons_type cons_type; 64 typedef typename cons_type::car_type value_type; 65 66 typedef typename mpl::eval_if< 67 is_const<cons_type> 68 , add_reference<typename add_const<value_type>::type> 69 , add_reference<value_type> >::type 70 type; 71 72 static type callboost::fusion::cons_detail::deref_traits_impl73 call(Iterator const& i) 74 { 75 return detail::ref(i.cons.car); 76 } 77 }; 78 79 template <typename Iterator> 80 struct next_traits_impl 81 { 82 typedef typename Iterator::cons_type cons_type; 83 typedef typename cons_type::cdr_type cdr_type; 84 85 typedef cons_iterator< 86 typename mpl::eval_if< 87 is_const<cons_type> 88 , add_const<cdr_type> 89 , mpl::identity<cdr_type> 90 >::type> 91 type; 92 93 static type callboost::fusion::cons_detail::next_traits_impl94 call(Iterator const& i) 95 { 96 return type(detail::ref(i.cons.cdr)); 97 } 98 }; 99 100 template <typename Iterator> 101 struct value_traits_impl 102 { 103 typedef typename Iterator::cons_type cons_type; 104 typedef typename cons_type::car_type type; 105 }; 106 107 template <typename Cons> 108 struct begin_traits_impl 109 { 110 typedef cons_iterator<Cons> type; 111 112 static type callboost::fusion::cons_detail::begin_traits_impl113 call(Cons& t) 114 { 115 return type(t); 116 } 117 }; 118 119 template <typename Cons> 120 struct end_traits_impl 121 { 122 typedef cons_iterator< 123 typename mpl::if_<is_const<Cons>, nil const, nil>::type> 124 type; 125 126 static type callboost::fusion::cons_detail::end_traits_impl127 call(Cons& t) 128 { 129 FUSION_RETURN_DEFAULT_CONSTRUCTED; 130 } 131 }; 132 } // namespace cons_detail 133 134 namespace meta 135 { 136 template <typename Tag> 137 struct deref_impl; 138 139 template <> 140 struct deref_impl<cons_iterator_tag> 141 { 142 template <typename Iterator> 143 struct apply : cons_detail::deref_traits_impl<Iterator> {}; 144 }; 145 146 template <typename Tag> 147 struct next_impl; 148 149 template <> 150 struct next_impl<cons_iterator_tag> 151 { 152 template <typename Iterator> 153 struct apply : cons_detail::next_traits_impl<Iterator> {}; 154 }; 155 156 template <typename Tag> 157 struct value_impl; 158 159 template <> 160 struct value_impl<cons_iterator_tag> 161 { 162 template <typename Iterator> 163 struct apply : cons_detail::value_traits_impl<Iterator> {}; 164 }; 165 166 template <typename Tag> 167 struct begin_impl; 168 169 template <> 170 struct begin_impl<cons_tag> 171 { 172 template <typename Sequence> 173 struct apply : cons_detail::begin_traits_impl<Sequence> 174 {}; 175 }; 176 177 template <typename Tag> 178 struct end_impl; 179 180 template <> 181 struct end_impl<cons_tag> 182 { 183 template <typename Sequence> 184 struct apply : cons_detail::end_traits_impl<Sequence> 185 {}; 186 }; 187 } // namespace meta 188 189 template <typename Cons = nil> 190 struct cons_iterator : iterator_base<cons_iterator<Cons> > 191 { 192 typedef cons_iterator_tag tag; 193 typedef Cons cons_type; 194 cons_iteratorboost::fusion::cons_iterator195 explicit cons_iterator(cons_type& cons_) 196 : cons(cons_) {} 197 198 cons_type& cons; 199 }; 200 201 template <> 202 struct cons_iterator<nil> : iterator_base<cons_iterator<nil> > 203 { 204 typedef cons_iterator_tag tag; 205 typedef nil cons_type; cons_iteratorboost::fusion::cons_iterator206 cons_iterator() {} cons_iteratorboost::fusion::cons_iterator207 explicit cons_iterator(nil const&) {} 208 }; 209 210 template <> 211 struct cons_iterator<nil const> : iterator_base<cons_iterator<nil const> > 212 { 213 typedef cons_iterator_tag tag; 214 typedef nil const cons_type; cons_iteratorboost::fusion::cons_iterator215 cons_iterator() {} cons_iteratorboost::fusion::cons_iterator216 explicit cons_iterator(nil const&) {} 217 }; 218 219 struct nil : sequence_base<nil> 220 { 221 typedef cons_tag tag; 222 typedef void_t car_type; 223 typedef void_t cdr_type; 224 }; 225 226 template <typename Car, typename Cdr = nil> 227 struct cons : sequence_base<cons<Car,Cdr> > 228 { 229 typedef cons_tag tag; 230 typedef typename call_traits<Car>::value_type car_type; 231 typedef Cdr cdr_type; 232 consboost::fusion::cons233 cons() 234 : car(), cdr() {} 235 consboost::fusion::cons236 explicit cons( 237 typename call_traits<Car>::param_type car_ 238 , typename call_traits<Cdr>::param_type cdr_ = Cdr()) 239 : car(car_), cdr(cdr_) {} 240 241 car_type car; 242 cdr_type cdr; 243 }; 244 245 template <typename Car> 246 inline cons<Car> make_cons(Car const & car)247 make_cons(Car const& car) 248 { 249 return cons<Car>(car); 250 } 251 252 template <typename Car, typename Cdr> 253 inline cons<Car, Cdr> make_cons(Car const & car,Cdr const & cdr)254 make_cons(Car const& car, Cdr const& cdr) 255 { 256 return cons<Car, Cdr>(car, cdr); 257 } 258 }} // namespace boost::fusion 259 260 namespace boost { namespace mpl 261 { 262 template <typename Tag> 263 struct begin_impl; 264 265 template <typename Tag> 266 struct end_impl; 267 268 template <> 269 struct begin_impl<fusion::cons_tag> 270 : fusion::meta::begin_impl<fusion::cons_tag> 271 { 272 }; 273 274 template <> 275 struct end_impl<fusion::cons_tag> 276 : fusion::meta::end_impl<fusion::cons_tag> 277 { 278 }; 279 280 }} // namespace boost::mpl 281 282 #endif 283 284 // Before Boost v1.33.1, Fusion cons lists were not valid MPL sequences. 285 #if BOOST_VERSION < 103301 286 namespace boost { namespace mpl 287 { 288 template<typename Iterator> 289 struct next; 290 291 template<typename Cons> 292 struct next<fusion::cons_iterator<Cons> > 293 : fusion::cons_detail::next_traits_impl<fusion::cons_iterator<Cons> > 294 { 295 }; 296 297 template<typename Iterator> 298 struct deref; 299 300 template<typename Cons> 301 struct deref<fusion::cons_iterator<Cons> > 302 : fusion::cons_detail::value_traits_impl<fusion::cons_iterator<Cons> > 303 { 304 }; 305 306 }} // namespace boost::mpl 307 #endif 308 309 #endif 310