Ticket #7526: zip_iterator.patch
File zip_iterator.patch, 19.4 KB (added by , 10 years ago) |
---|
-
boost/iterator/zip_iterator.hpp
From 69cb714a69a3a9335cf4c38e38343bbd8b160391 Mon Sep 17 00:00:00 2001 From: Kohei Takahashi <flast@flast.jp> Date: Wed, 17 Oct 2012 18:09:08 +0900 Subject: [PATCH] boost::zip_iterator rebase to Boost.Fusion --- boost/iterator/zip_iterator.hpp | 433 +++++++----------------------- libs/iterator/test/zip_iterator_test.cpp | 2 + 2 files changed, 96 insertions(+), 339 deletions(-) diff --git a/boost/iterator/zip_iterator.hpp b/boost/iterator/zip_iterator.hpp index a468070..28785e6 100644
a b 1 // Copyright David Abrahams and Thomas Becker 2000-2006. Distributed 2 // under the Boost Software License, Version 1.0. (See accompanying 3 // file LICENSE_1_0.txt or copy at 1 // Copyright David Abrahams and Thomas Becker 2000-2006. 2 // Copyright Kohei Takahashi 2012. 3 // 4 // Distributed under the Boost Software License, Version 1.0. (See 5 // accompanying file LICENSE_1_0.txt or copy at 4 6 // http://www.boost.org/LICENSE_1_0.txt) 5 7 6 8 #ifndef BOOST_ZIP_ITERATOR_TMB_07_13_2003_HPP_ … … 16 18 17 19 #include <boost/iterator/detail/minimum_category.hpp> 18 20 19 #include <boost/ tuple/tuple.hpp>21 #include <boost/fusion/adapted/boost_tuple.hpp> // for backward compatibility 20 22 21 #include <boost/type_traits/is_same.hpp> 22 #include <boost/mpl/and.hpp> 23 #include <boost/mpl/apply.hpp> 24 #include <boost/mpl/eval_if.hpp> 25 #include <boost/mpl/lambda.hpp> 23 #include <boost/type_traits/remove_reference.hpp> 24 #include <boost/type_traits/remove_cv.hpp> 25 26 #include <boost/mpl/at.hpp> 27 #include <boost/mpl/fold.hpp> 28 #include <boost/mpl/transform.hpp> 26 29 #include <boost/mpl/placeholders.hpp> 27 30 #include <boost/mpl/aux_/lambda_support.hpp> 28 31 32 #include <boost/fusion/algorithm/iteration/for_each.hpp> 33 #include <boost/fusion/algorithm/transformation/transform.hpp> 34 #include <boost/fusion/sequence/convert.hpp> 35 #include <boost/fusion/sequence/intrinsic/at_c.hpp> 36 #include <boost/fusion/sequence/comparison/equal_to.hpp> 37 #include <boost/fusion/support/tag_of_fwd.hpp> 38 29 39 namespace boost { 30 40 31 41 // Zip iterator forward declaration for zip_iterator_base 32 42 template<typename IteratorTuple> 33 43 class zip_iterator; 34 44 35 // One important design goal of the zip_iterator is to isolate all36 // functionality whose implementation relies on the current tuple37 // implementation. This goal has been achieved as follows: Inside38 // the namespace detail there is a namespace tuple_impl_specific.39 // This namespace encapsulates all functionality that is specific40 // to the current Boost tuple implementation. More precisely, the41 // namespace tuple_impl_specific provides the following tuple42 // algorithms and meta-algorithms for the current Boost tuple43 // implementation:44 //45 // tuple_meta_transform46 // tuple_meta_accumulate47 // tuple_transform48 // tuple_for_each49 //50 // If the tuple implementation changes, all that needs to be51 // replaced is the implementation of these four (meta-)algorithms.52 53 45 namespace detail 54 46 { 55 47 … … namespace boost { 60 52 { 61 53 public: 62 54 advance_iterator(DiffType step) : m_step(step) {} 63 55 64 56 template<typename Iterator> 65 57 void operator()(Iterator& it) const 66 58 { it += m_step; } … … namespace boost { 72 64 struct increment_iterator 73 65 { 74 66 template<typename Iterator> 75 void operator()(Iterator& it) 67 void operator()(Iterator& it) const 76 68 { ++it; } 77 69 }; 78 70 // 79 71 struct decrement_iterator 80 72 { 81 73 template<typename Iterator> 82 void operator()(Iterator& it) 74 void operator()(Iterator& it) const 83 75 { --it; } 84 76 }; 85 77 // 86 78 struct dereference_iterator 87 79 { 88 template<typename Iterator> 89 struct apply 90 { 80 template<typename> 81 struct result; 82 83 template<typename This, typename Iterator> 84 struct result<This(Iterator)> 85 { 86 typedef typename 87 remove_reference<typename remove_cv<Iterator>::type>::type 88 iterator; 89 91 90 typedef typename 92 iterator_traits< Iterator>::reference91 iterator_traits<iterator>::reference 93 92 type; 94 93 }; 95 94 96 95 template<typename Iterator> 97 typename apply<Iterator>::type operator()(Iterator const& it) 96 typename result<dereference_iterator(Iterator)>::type 97 operator()(Iterator const& it) const 98 98 { return *it; } 99 99 }; 100 101 102 // The namespace tuple_impl_specific provides two meta-103 // algorithms and two algorithms for tuples.104 //105 namespace tuple_impl_specific106 {107 // Meta-transform algorithm for tuples108 //109 template<typename Tuple, class UnaryMetaFun>110 struct tuple_meta_transform;111 112 template<typename Tuple, class UnaryMetaFun>113 struct tuple_meta_transform_impl114 {115 typedef tuples::cons<116 typename mpl::apply1<117 typename mpl::lambda<UnaryMetaFun>::type118 , typename Tuple::head_type119 >::type120 , typename tuple_meta_transform<121 typename Tuple::tail_type122 , UnaryMetaFun123 >::type124 > type;125 };126 127 template<typename Tuple, class UnaryMetaFun>128 struct tuple_meta_transform129 : mpl::eval_if<130 boost::is_same<Tuple, tuples::null_type>131 , mpl::identity<tuples::null_type>132 , tuple_meta_transform_impl<Tuple, UnaryMetaFun>133 >134 {135 };136 137 // Meta-accumulate algorithm for tuples. Note: The template138 // parameter StartType corresponds to the initial value in139 // ordinary accumulation.140 //141 template<class Tuple, class BinaryMetaFun, class StartType>142 struct tuple_meta_accumulate;143 144 template<145 typename Tuple146 , class BinaryMetaFun147 , typename StartType148 >149 struct tuple_meta_accumulate_impl150 {151 typedef typename mpl::apply2<152 typename mpl::lambda<BinaryMetaFun>::type153 , typename Tuple::head_type154 , typename tuple_meta_accumulate<155 typename Tuple::tail_type156 , BinaryMetaFun157 , StartType158 >::type159 >::type type;160 };161 162 template<163 typename Tuple164 , class BinaryMetaFun165 , typename StartType166 >167 struct tuple_meta_accumulate168 : mpl::eval_if<169 #if BOOST_WORKAROUND(BOOST_MSVC, < 1300)170 mpl::or_<171 #endif172 boost::is_same<Tuple, tuples::null_type>173 #if BOOST_WORKAROUND(BOOST_MSVC, < 1300)174 , boost::is_same<Tuple,int>175 >176 #endif177 , mpl::identity<StartType>178 , tuple_meta_accumulate_impl<179 Tuple180 , BinaryMetaFun181 , StartType182 >183 >184 {185 };186 187 #if defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) \188 || ( \189 BOOST_WORKAROUND(BOOST_INTEL_CXX_VERSION, != 0) && defined(_MSC_VER) \190 )191 // Not sure why intel's partial ordering fails in this case, but I'm192 // assuming int's an MSVC bug-compatibility feature.193 194 # define BOOST_TUPLE_ALGO_DISPATCH195 # define BOOST_TUPLE_ALGO(algo) algo##_impl196 # define BOOST_TUPLE_ALGO_TERMINATOR , int197 # define BOOST_TUPLE_ALGO_RECURSE , ...198 #else199 # define BOOST_TUPLE_ALGO(algo) algo200 # define BOOST_TUPLE_ALGO_TERMINATOR201 # define BOOST_TUPLE_ALGO_RECURSE202 #endif203 204 // transform algorithm for tuples. The template parameter Fun205 // must be a unary functor which is also a unary metafunction206 // class that computes its return type based on its argument207 // type. For example:208 //209 // struct to_ptr210 // {211 // template <class Arg>212 // struct apply213 // {214 // typedef Arg* type;215 // }216 //217 // template <class Arg>218 // Arg* operator()(Arg x);219 // };220 template<typename Fun>221 tuples::null_type BOOST_TUPLE_ALGO(tuple_transform)222 (tuples::null_type const&, Fun BOOST_TUPLE_ALGO_TERMINATOR)223 { return tuples::null_type(); }224 225 template<typename Tuple, typename Fun>226 typename tuple_meta_transform<227 Tuple228 , Fun229 >::type230 231 BOOST_TUPLE_ALGO(tuple_transform)(232 const Tuple& t,233 Fun f234 BOOST_TUPLE_ALGO_RECURSE235 )236 {237 typedef typename tuple_meta_transform<238 BOOST_DEDUCED_TYPENAME Tuple::tail_type239 , Fun240 >::type transformed_tail_type;241 242 return tuples::cons<243 BOOST_DEDUCED_TYPENAME mpl::apply1<244 Fun, BOOST_DEDUCED_TYPENAME Tuple::head_type245 >::type246 , transformed_tail_type247 >(248 f(boost::tuples::get<0>(t)), tuple_transform(t.get_tail(), f)249 );250 }251 252 #ifdef BOOST_TUPLE_ALGO_DISPATCH253 template<typename Tuple, typename Fun>254 typename tuple_meta_transform<255 Tuple256 , Fun257 >::type258 259 tuple_transform(260 const Tuple& t,261 Fun f262 )263 {264 return tuple_transform_impl(t, f, 1);265 }266 #endif267 268 // for_each algorithm for tuples.269 //270 template<typename Fun>271 Fun BOOST_TUPLE_ALGO(tuple_for_each)(272 tuples::null_type273 , Fun f BOOST_TUPLE_ALGO_TERMINATOR274 )275 { return f; }276 277 278 template<typename Tuple, typename Fun>279 Fun BOOST_TUPLE_ALGO(tuple_for_each)(280 Tuple& t281 , Fun f BOOST_TUPLE_ALGO_RECURSE)282 {283 f( t.get_head() );284 return tuple_for_each(t.get_tail(), f);285 }286 287 #ifdef BOOST_TUPLE_ALGO_DISPATCH288 template<typename Tuple, typename Fun>289 Fun290 tuple_for_each(291 Tuple& t,292 Fun f293 )294 {295 return tuple_for_each_impl(t, f, 1);296 }297 #endif298 299 // Equality of tuples. NOTE: "==" for tuples currently (7/2003)300 // has problems under some compilers, so I just do my own.301 // No point in bringing in a bunch of #ifdefs here. This is302 // going to go away with the next tuple implementation anyway.303 //304 inline bool tuple_equal(tuples::null_type, tuples::null_type)305 { return true; }306 307 template<typename Tuple1, typename Tuple2>308 bool tuple_equal(309 Tuple1 const& t1,310 Tuple2 const& t2311 )312 {313 return t1.get_head() == t2.get_head() &&314 tuple_equal(t1.get_tail(), t2.get_tail());315 }316 }317 //318 // end namespace tuple_impl_specific319 100 320 101 template<typename Iterator> 321 102 struct iterator_reference … … namespace boost { 336 117 struct apply : iterator_reference<T> {}; 337 118 }; 338 119 #endif 339 120 340 121 // Metafunction to obtain the type of the tuple whose element types 341 122 // are the reference types of an iterator tuple. 342 123 // 343 124 template<typename IteratorTuple> 344 125 struct tuple_of_references 345 : tuple_impl_specific::tuple_meta_transform<346 IteratorTuple, 126 : mpl::transform< 127 IteratorTuple, 347 128 iterator_reference<mpl::_1> 348 129 > 349 130 { … … namespace boost { 355 136 template<typename IteratorTuple> 356 137 struct minimum_traversal_category_in_iterator_tuple 357 138 { 358 typedef typename tuple_impl_specific::tuple_meta_transform<139 typedef typename mpl::transform< 359 140 IteratorTuple 360 141 , pure_traversal_tag<iterator_traversal<> > 361 142 >::type tuple_of_traversal_tags; 362 363 typedef typename tuple_impl_specific::tuple_meta_accumulate<143 144 typedef typename mpl::fold< 364 145 tuple_of_traversal_tags 365 , minimum_category<>366 146 , random_access_traversal_tag 147 , minimum_category<> 367 148 >::type type; 368 149 }; 369 150 … … namespace boost { 374 155 typedef int type; 375 156 }; 376 157 #endif 377 378 // We need to call tuple_meta_accumulate with mpl::and_ as the379 // accumulating functor. To this end, we need to wrap it into380 // a struct that has exactly two arguments (that is, template381 // parameters) and not five, like mpl::and_ does.382 //383 template<typename Arg1, typename Arg2>384 struct and_with_two_args385 : mpl::and_<Arg1, Arg2>386 {387 };388 389 # ifdef BOOST_MPL_CFG_NO_FULL_LAMBDA_SUPPORT390 // Hack because BOOST_MPL_AUX_LAMBDA_SUPPORT doesn't seem to work391 // out well. In this case I think it's an MPL bug392 template<>393 struct and_with_two_args<mpl::_1,mpl::_2>394 {395 template <class A1, class A2>396 struct apply : mpl::and_<A1,A2>397 {};398 };399 # endif400 158 401 159 /////////////////////////////////////////////////////////////////// 402 160 // 403 161 // Class zip_iterator_base 404 162 // 405 // Builds and exposes the iterator facade type from which the zip 163 // Builds and exposes the iterator facade type from which the zip 406 164 // iterator will be derived. 407 165 // 408 166 template<typename IteratorTuple> … … namespace boost { 411 169 private: 412 170 // Reference type is the type of the tuple obtained from the 413 171 // iterators' reference types. 414 typedef typename 172 typedef typename 415 173 detail::tuple_of_references<IteratorTuple>::type reference; 416 174 417 175 // Value type is the same as reference type. 418 176 typedef reference value_type; 419 177 420 178 // Difference type is the first iterator's difference type 421 179 typedef typename iterator_traits< 422 typename tuples::element<0, IteratorTuple>::type180 typename mpl::at_c<IteratorTuple, 0>::type 423 181 >::difference_type difference_type; 424 425 // Traversal catetgory is the minimum traversal category in the 182 183 // Traversal catetgory is the minimum traversal category in the 426 184 // iterator tuple. 427 typedef typename 185 typedef typename 428 186 detail::minimum_traversal_category_in_iterator_tuple< 429 187 IteratorTuple 430 188 >::type traversal_category; 431 189 public: 432 190 433 191 // The iterator facade type from which the zip iterator will 434 192 // be derived. 435 193 typedef iterator_facade< 436 194 zip_iterator<IteratorTuple>, 437 value_type, 195 value_type, 438 196 traversal_category, 439 197 reference, 440 198 difference_type … … namespace boost { 447 205 typedef int type; 448 206 }; 449 207 } 450 208 451 209 ///////////////////////////////////////////////////////////////////// 452 210 // 453 211 // zip_iterator class definition 454 212 // 455 213 template<typename IteratorTuple> 456 class zip_iterator : 214 class zip_iterator : 457 215 public detail::zip_iterator_base<IteratorTuple>::type 458 { 216 { 459 217 460 // Typedef super_t as our base class. 461 typedef typename 218 // Typedef super_t as our base class. 219 typedef typename 462 220 detail::zip_iterator_base<IteratorTuple>::type super_t; 463 221 464 222 // iterator_core_access is the iterator's best friend. 465 223 friend class iterator_core_access; 466 224 467 225 public: 468 226 469 227 // Construction 470 228 // ============ 471 229 472 230 // Default constructor 473 231 zip_iterator() { } 474 232 475 233 // Constructor from iterator tuple 476 zip_iterator(IteratorTuple iterator_tuple) 477 : m_iterator_tuple(iterator_tuple) 234 zip_iterator(IteratorTuple iterator_tuple) 235 : m_iterator_tuple(iterator_tuple) 478 236 { } 479 237 480 238 // Copy constructor … … namespace boost { 493 251 { return m_iterator_tuple; } 494 252 495 253 private: 496 254 497 255 // Implementation of Iterator Operations 498 256 // ===================================== 499 257 500 258 // Dereferencing returns a tuple built from the dereferenced 501 259 // iterators in the iterator tuple. 502 260 typename super_t::reference dereference() const 503 { 504 return detail::tuple_impl_specific::tuple_transform( 505 get_iterator_tuple(), 506 detail::dereference_iterator() 507 ); 261 { 262 typedef typename super_t::reference reference; 263 typedef typename fusion::traits::tag_of<reference>::type tag; 264 return fusion::convert<tag>(fusion::transform( 265 get_iterator_tuple(), 266 detail::dereference_iterator())); 508 267 } 509 268 510 269 // Two zip iterators are equal if all iterators in the iterator … … namespace boost { 517 276 // under several compilers. No point in bringing in a bunch 518 277 // of #ifdefs here. 519 278 // 520 template<typename OtherIteratorTuple> 279 template<typename OtherIteratorTuple> 521 280 bool equal(const zip_iterator<OtherIteratorTuple>& other) const 522 281 { 523 return detail::tuple_impl_specific::tuple_equal( 524 get_iterator_tuple(), 525 other.get_iterator_tuple() 526 ); 282 return fusion::equal_to( 283 get_iterator_tuple(), 284 other.get_iterator_tuple()); 527 285 } 528 286 529 287 // Advancing a zip iterator means to advance all iterators in the 530 288 // iterator tuple. 531 289 void advance(typename super_t::difference_type n) 532 { 533 detail::tuple_impl_specific::tuple_for_each(290 { 291 fusion::for_each( 534 292 m_iterator_tuple, 535 detail::advance_iterator<BOOST_DEDUCED_TYPENAME super_t::difference_type>(n) 536 ); 293 detail::advance_iterator<BOOST_DEDUCED_TYPENAME super_t::difference_type>(n)); 537 294 } 538 295 // Incrementing a zip iterator means to increment all iterators in 539 296 // the iterator tuple. 540 297 void increment() 541 { 542 detail::tuple_impl_specific::tuple_for_each( 543 m_iterator_tuple, 544 detail::increment_iterator() 545 ); 298 { 299 fusion::for_each( 300 m_iterator_tuple, 301 detail::increment_iterator()); 546 302 } 547 303 548 304 // Decrementing a zip iterator means to decrement all iterators in 549 305 // the iterator tuple. 550 306 void decrement() 551 { 552 detail::tuple_impl_specific::tuple_for_each( 553 m_iterator_tuple, 554 detail::decrement_iterator() 555 ); 307 { 308 fusion::for_each( 309 m_iterator_tuple, 310 detail::decrement_iterator()); 556 311 } 557 312 558 313 // Distance is calculated using the first iterator in the tuple. 559 314 template<typename OtherIteratorTuple> 560 315 typename super_t::difference_type distance_to( 561 316 const zip_iterator<OtherIteratorTuple>& other 562 317 ) const 563 { 564 return boost::tuples::get<0>(other.get_iterator_tuple()) -565 boost::tuples::get<0>(this->get_iterator_tuple());318 { 319 return fusion::at_c<0>(other.get_iterator_tuple()) - 320 fusion::at_c<0>(this->get_iterator_tuple()); 566 321 } 567 322 568 323 // Data Members 569 324 // ============ 570 325 571 326 // The iterator tuple. 572 327 IteratorTuple m_iterator_tuple; 573 328 574 329 }; 575 330 576 331 // Make function for zip iterator 577 332 // 578 template<typename IteratorTuple> 579 zip_iterator<IteratorTuple> 333 template<typename IteratorTuple> 334 zip_iterator<IteratorTuple> 580 335 make_zip_iterator(IteratorTuple t) 581 336 { return zip_iterator<IteratorTuple>(t); } 582 337 -
libs/iterator/test/zip_iterator_test.cpp
diff --git a/libs/iterator/test/zip_iterator_test.cpp b/libs/iterator/test/zip_iterator_test.cpp index 8062f08..3f56b16 100644
a b 49 49 #include <string> 50 50 #include <functional> 51 51 #include <boost/tuple/tuple.hpp> 52 #include <boost/fusion/adapted/boost_tuple.hpp> 53 #include <boost/fusion/mpl.hpp> 52 54 #include <boost/iterator/transform_iterator.hpp> 53 55 #include <boost/iterator/is_readable_iterator.hpp> 54 56 #include <boost/type_traits/is_same.hpp>