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 #if BOOST_VERSION < 103300 47 struct void_t; 48 #endif 49 50 struct nil; 51 52 struct cons_tag; 53 54 template <typename Car, typename Cdr> 55 struct cons; 56 57 struct cons_iterator_tag; 58 59 template <typename Cons> 60 struct cons_iterator; 61 62 namespace cons_detail 63 { 64 template <typename Iterator> 65 struct deref_traits_impl 66 { 67 typedef typename Iterator::cons_type cons_type; 68 typedef typename cons_type::car_type value_type; 69 70 typedef typename mpl::eval_if< 71 is_const<cons_type> 72 , add_reference<typename add_const<value_type>::type> 73 , add_reference<value_type> >::type 74 type; 75 76 static type callboost::fusion::cons_detail::deref_traits_impl77 call(Iterator const& i) 78 { 79 return detail::ref(i.cons.car); 80 } 81 }; 82 83 template <typename Iterator> 84 struct next_traits_impl 85 { 86 typedef typename Iterator::cons_type cons_type; 87 typedef typename cons_type::cdr_type cdr_type; 88 89 typedef cons_iterator< 90 typename mpl::eval_if< 91 is_const<cons_type> 92 , add_const<cdr_type> 93 , mpl::identity<cdr_type> 94 >::type> 95 type; 96 97 static type callboost::fusion::cons_detail::next_traits_impl98 call(Iterator const& i) 99 { 100 return type(detail::ref(i.cons.cdr)); 101 } 102 }; 103 104 template <typename Iterator> 105 struct value_traits_impl 106 { 107 typedef typename Iterator::cons_type cons_type; 108 typedef typename cons_type::car_type type; 109 }; 110 111 template <typename Cons> 112 struct begin_traits_impl 113 { 114 typedef cons_iterator<Cons> type; 115 116 static type callboost::fusion::cons_detail::begin_traits_impl117 call(Cons& t) 118 { 119 return type(t); 120 } 121 }; 122 123 template <typename Cons> 124 struct end_traits_impl 125 { 126 typedef cons_iterator< 127 typename mpl::if_<is_const<Cons>, nil const, nil>::type> 128 type; 129 130 static type callboost::fusion::cons_detail::end_traits_impl131 call(Cons& t) 132 { 133 FUSION_RETURN_DEFAULT_CONSTRUCTED; 134 } 135 }; 136 } // namespace cons_detail 137 138 namespace meta 139 { 140 template <typename Tag> 141 struct deref_impl; 142 143 template <> 144 struct deref_impl<cons_iterator_tag> 145 { 146 template <typename Iterator> 147 struct apply : cons_detail::deref_traits_impl<Iterator> {}; 148 }; 149 150 template <typename Tag> 151 struct next_impl; 152 153 template <> 154 struct next_impl<cons_iterator_tag> 155 { 156 template <typename Iterator> 157 struct apply : cons_detail::next_traits_impl<Iterator> {}; 158 }; 159 160 template <typename Tag> 161 struct value_impl; 162 163 template <> 164 struct value_impl<cons_iterator_tag> 165 { 166 template <typename Iterator> 167 struct apply : cons_detail::value_traits_impl<Iterator> {}; 168 }; 169 170 template <typename Tag> 171 struct begin_impl; 172 173 template <> 174 struct begin_impl<cons_tag> 175 { 176 template <typename Sequence> 177 struct apply : cons_detail::begin_traits_impl<Sequence> 178 {}; 179 }; 180 181 template <typename Tag> 182 struct end_impl; 183 184 template <> 185 struct end_impl<cons_tag> 186 { 187 template <typename Sequence> 188 struct apply : cons_detail::end_traits_impl<Sequence> 189 {}; 190 }; 191 } // namespace meta 192 193 template <typename Cons = nil> 194 struct cons_iterator : iterator_base<cons_iterator<Cons> > 195 { 196 typedef cons_iterator_tag tag; 197 typedef Cons cons_type; 198 cons_iteratorboost::fusion::cons_iterator199 explicit cons_iterator(cons_type& cons_) 200 : cons(cons_) {} 201 202 cons_type& cons; 203 }; 204 205 template <> 206 struct cons_iterator<nil> : iterator_base<cons_iterator<nil> > 207 { 208 typedef cons_iterator_tag tag; 209 typedef nil cons_type; cons_iteratorboost::fusion::cons_iterator210 cons_iterator() {} cons_iteratorboost::fusion::cons_iterator211 explicit cons_iterator(nil const&) {} 212 }; 213 214 template <> 215 struct cons_iterator<nil const> : iterator_base<cons_iterator<nil const> > 216 { 217 typedef cons_iterator_tag tag; 218 typedef nil const cons_type; cons_iteratorboost::fusion::cons_iterator219 cons_iterator() {} cons_iteratorboost::fusion::cons_iterator220 explicit cons_iterator(nil const&) {} 221 }; 222 223 struct nil : sequence_base<nil> 224 { 225 typedef cons_tag tag; 226 typedef void_t car_type; 227 typedef void_t cdr_type; 228 }; 229 230 template <typename Car, typename Cdr = nil> 231 struct cons : sequence_base<cons<Car,Cdr> > 232 { 233 typedef cons_tag tag; 234 typedef typename call_traits<Car>::value_type car_type; 235 typedef Cdr cdr_type; 236 consboost::fusion::cons237 cons() 238 : car(), cdr() {} 239 consboost::fusion::cons240 explicit cons( 241 typename call_traits<Car>::param_type car_ 242 , typename call_traits<Cdr>::param_type cdr_ = Cdr()) 243 : car(car_), cdr(cdr_) {} 244 245 car_type car; 246 cdr_type cdr; 247 }; 248 249 template <typename Car> 250 inline cons<Car> make_cons(Car const & car)251 make_cons(Car const& car) 252 { 253 return cons<Car>(car); 254 } 255 256 template <typename Car, typename Cdr> 257 inline cons<Car, Cdr> make_cons(Car const & car,Cdr const & cdr)258 make_cons(Car const& car, Cdr const& cdr) 259 { 260 return cons<Car, Cdr>(car, cdr); 261 } 262 }} // namespace boost::fusion 263 264 namespace boost { namespace mpl 265 { 266 template <typename Tag> 267 struct begin_impl; 268 269 template <typename Tag> 270 struct end_impl; 271 272 template <> 273 struct begin_impl<fusion::cons_tag> 274 : fusion::meta::begin_impl<fusion::cons_tag> 275 { 276 }; 277 278 template <> 279 struct end_impl<fusion::cons_tag> 280 : fusion::meta::end_impl<fusion::cons_tag> 281 { 282 }; 283 284 }} // namespace boost::mpl 285 286 #endif 287 288 // Before Boost v1.33.1, Fusion cons lists were not valid MPL sequences. 289 #if BOOST_VERSION < 103301 290 namespace boost { namespace mpl 291 { 292 template<typename Iterator> 293 struct next; 294 295 template<typename Cons> 296 struct next<fusion::cons_iterator<Cons> > 297 : fusion::cons_detail::next_traits_impl<fusion::cons_iterator<Cons> > 298 { 299 }; 300 301 template<typename Iterator> 302 struct deref; 303 304 template<typename Cons> 305 struct deref<fusion::cons_iterator<Cons> > 306 : fusion::cons_detail::value_traits_impl<fusion::cons_iterator<Cons> > 307 { 308 }; 309 310 }} // namespace boost::mpl 311 #endif 312 313 #endif 314