zip_iterator.hpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585
  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
  4. // http://www.boost.org/LICENSE_1_0.txt)
  5. #ifndef BOOST_ZIP_ITERATOR_TMB_07_13_2003_HPP_
  6. # define BOOST_ZIP_ITERATOR_TMB_07_13_2003_HPP_
  7. #include <stddef.h>
  8. #include <boost/iterator.hpp>
  9. #include <boost/iterator/iterator_traits.hpp>
  10. #include <boost/iterator/iterator_facade.hpp>
  11. #include <boost/iterator/iterator_adaptor.hpp> // for enable_if_convertible
  12. #include <boost/iterator/iterator_categories.hpp>
  13. #include <boost/detail/iterator.hpp>
  14. #include <boost/iterator/detail/minimum_category.hpp>
  15. #include <boost/tuple/tuple.hpp>
  16. #include <boost/type_traits/is_same.hpp>
  17. #include <boost/mpl/and.hpp>
  18. #include <boost/mpl/apply.hpp>
  19. #include <boost/mpl/eval_if.hpp>
  20. #include <boost/mpl/lambda.hpp>
  21. #include <boost/mpl/placeholders.hpp>
  22. #include <boost/mpl/aux_/lambda_support.hpp>
  23. namespace boost {
  24. // Zip iterator forward declaration for zip_iterator_base
  25. template<typename IteratorTuple>
  26. class zip_iterator;
  27. // One important design goal of the zip_iterator is to isolate all
  28. // functionality whose implementation relies on the current tuple
  29. // implementation. This goal has been achieved as follows: Inside
  30. // the namespace detail there is a namespace tuple_impl_specific.
  31. // This namespace encapsulates all functionality that is specific
  32. // to the current Boost tuple implementation. More precisely, the
  33. // namespace tuple_impl_specific provides the following tuple
  34. // algorithms and meta-algorithms for the current Boost tuple
  35. // implementation:
  36. //
  37. // tuple_meta_transform
  38. // tuple_meta_accumulate
  39. // tuple_transform
  40. // tuple_for_each
  41. //
  42. // If the tuple implementation changes, all that needs to be
  43. // replaced is the implementation of these four (meta-)algorithms.
  44. namespace detail
  45. {
  46. // Functors to be used with tuple algorithms
  47. //
  48. template<typename DiffType>
  49. class advance_iterator
  50. {
  51. public:
  52. advance_iterator(DiffType step) : m_step(step) {}
  53. template<typename Iterator>
  54. void operator()(Iterator& it) const
  55. { it += m_step; }
  56. private:
  57. DiffType m_step;
  58. };
  59. //
  60. struct increment_iterator
  61. {
  62. template<typename Iterator>
  63. void operator()(Iterator& it)
  64. { ++it; }
  65. };
  66. //
  67. struct decrement_iterator
  68. {
  69. template<typename Iterator>
  70. void operator()(Iterator& it)
  71. { --it; }
  72. };
  73. //
  74. struct dereference_iterator
  75. {
  76. template<typename Iterator>
  77. struct apply
  78. {
  79. typedef typename
  80. iterator_traits<Iterator>::reference
  81. type;
  82. };
  83. template<typename Iterator>
  84. typename apply<Iterator>::type operator()(Iterator const& it)
  85. { return *it; }
  86. };
  87. // The namespace tuple_impl_specific provides two meta-
  88. // algorithms and two algorithms for tuples.
  89. //
  90. namespace tuple_impl_specific
  91. {
  92. // Meta-transform algorithm for tuples
  93. //
  94. template<typename Tuple, class UnaryMetaFun>
  95. struct tuple_meta_transform;
  96. template<typename Tuple, class UnaryMetaFun>
  97. struct tuple_meta_transform_impl
  98. {
  99. typedef tuples::cons<
  100. typename mpl::apply1<
  101. typename mpl::lambda<UnaryMetaFun>::type
  102. , typename Tuple::head_type
  103. >::type
  104. , typename tuple_meta_transform<
  105. typename Tuple::tail_type
  106. , UnaryMetaFun
  107. >::type
  108. > type;
  109. };
  110. template<typename Tuple, class UnaryMetaFun>
  111. struct tuple_meta_transform
  112. : mpl::eval_if<
  113. boost::is_same<Tuple, tuples::null_type>
  114. , mpl::identity<tuples::null_type>
  115. , tuple_meta_transform_impl<Tuple, UnaryMetaFun>
  116. >
  117. {
  118. };
  119. // Meta-accumulate algorithm for tuples. Note: The template
  120. // parameter StartType corresponds to the initial value in
  121. // ordinary accumulation.
  122. //
  123. template<class Tuple, class BinaryMetaFun, class StartType>
  124. struct tuple_meta_accumulate;
  125. template<
  126. typename Tuple
  127. , class BinaryMetaFun
  128. , typename StartType
  129. >
  130. struct tuple_meta_accumulate_impl
  131. {
  132. typedef typename mpl::apply2<
  133. typename mpl::lambda<BinaryMetaFun>::type
  134. , typename Tuple::head_type
  135. , typename tuple_meta_accumulate<
  136. typename Tuple::tail_type
  137. , BinaryMetaFun
  138. , StartType
  139. >::type
  140. >::type type;
  141. };
  142. template<
  143. typename Tuple
  144. , class BinaryMetaFun
  145. , typename StartType
  146. >
  147. struct tuple_meta_accumulate
  148. : mpl::eval_if<
  149. #if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
  150. mpl::or_<
  151. #endif
  152. boost::is_same<Tuple, tuples::null_type>
  153. #if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
  154. , boost::is_same<Tuple,int>
  155. >
  156. #endif
  157. , mpl::identity<StartType>
  158. , tuple_meta_accumulate_impl<
  159. Tuple
  160. , BinaryMetaFun
  161. , StartType
  162. >
  163. >
  164. {
  165. };
  166. #if defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) \
  167. || ( \
  168. BOOST_WORKAROUND(BOOST_INTEL_CXX_VERSION, != 0) && defined(_MSC_VER) \
  169. )
  170. // Not sure why intel's partial ordering fails in this case, but I'm
  171. // assuming int's an MSVC bug-compatibility feature.
  172. # define BOOST_TUPLE_ALGO_DISPATCH
  173. # define BOOST_TUPLE_ALGO(algo) algo##_impl
  174. # define BOOST_TUPLE_ALGO_TERMINATOR , int
  175. # define BOOST_TUPLE_ALGO_RECURSE , ...
  176. #else
  177. # define BOOST_TUPLE_ALGO(algo) algo
  178. # define BOOST_TUPLE_ALGO_TERMINATOR
  179. # define BOOST_TUPLE_ALGO_RECURSE
  180. #endif
  181. // transform algorithm for tuples. The template parameter Fun
  182. // must be a unary functor which is also a unary metafunction
  183. // class that computes its return type based on its argument
  184. // type. For example:
  185. //
  186. // struct to_ptr
  187. // {
  188. // template <class Arg>
  189. // struct apply
  190. // {
  191. // typedef Arg* type;
  192. // }
  193. //
  194. // template <class Arg>
  195. // Arg* operator()(Arg x);
  196. // };
  197. template<typename Fun>
  198. tuples::null_type BOOST_TUPLE_ALGO(tuple_transform)
  199. (tuples::null_type const&, Fun BOOST_TUPLE_ALGO_TERMINATOR)
  200. { return tuples::null_type(); }
  201. template<typename Tuple, typename Fun>
  202. typename tuple_meta_transform<
  203. Tuple
  204. , Fun
  205. >::type
  206. BOOST_TUPLE_ALGO(tuple_transform)(
  207. const Tuple& t,
  208. Fun f
  209. BOOST_TUPLE_ALGO_RECURSE
  210. )
  211. {
  212. typedef typename tuple_meta_transform<
  213. BOOST_DEDUCED_TYPENAME Tuple::tail_type
  214. , Fun
  215. >::type transformed_tail_type;
  216. return tuples::cons<
  217. BOOST_DEDUCED_TYPENAME mpl::apply1<
  218. Fun, BOOST_DEDUCED_TYPENAME Tuple::head_type
  219. >::type
  220. , transformed_tail_type
  221. >(
  222. f(boost::tuples::get<0>(t)), tuple_transform(t.get_tail(), f)
  223. );
  224. }
  225. #ifdef BOOST_TUPLE_ALGO_DISPATCH
  226. template<typename Tuple, typename Fun>
  227. typename tuple_meta_transform<
  228. Tuple
  229. , Fun
  230. >::type
  231. tuple_transform(
  232. const Tuple& t,
  233. Fun f
  234. )
  235. {
  236. return tuple_transform_impl(t, f, 1);
  237. }
  238. #endif
  239. // for_each algorithm for tuples.
  240. //
  241. template<typename Fun>
  242. Fun BOOST_TUPLE_ALGO(tuple_for_each)(
  243. tuples::null_type
  244. , Fun f BOOST_TUPLE_ALGO_TERMINATOR
  245. )
  246. { return f; }
  247. template<typename Tuple, typename Fun>
  248. Fun BOOST_TUPLE_ALGO(tuple_for_each)(
  249. Tuple& t
  250. , Fun f BOOST_TUPLE_ALGO_RECURSE)
  251. {
  252. f( t.get_head() );
  253. return tuple_for_each(t.get_tail(), f);
  254. }
  255. #ifdef BOOST_TUPLE_ALGO_DISPATCH
  256. template<typename Tuple, typename Fun>
  257. Fun
  258. tuple_for_each(
  259. Tuple& t,
  260. Fun f
  261. )
  262. {
  263. return tuple_for_each_impl(t, f, 1);
  264. }
  265. #endif
  266. // Equality of tuples. NOTE: "==" for tuples currently (7/2003)
  267. // has problems under some compilers, so I just do my own.
  268. // No point in bringing in a bunch of #ifdefs here. This is
  269. // going to go away with the next tuple implementation anyway.
  270. //
  271. inline bool tuple_equal(tuples::null_type, tuples::null_type)
  272. { return true; }
  273. template<typename Tuple1, typename Tuple2>
  274. bool tuple_equal(
  275. Tuple1 const& t1,
  276. Tuple2 const& t2
  277. )
  278. {
  279. return t1.get_head() == t2.get_head() &&
  280. tuple_equal(t1.get_tail(), t2.get_tail());
  281. }
  282. }
  283. //
  284. // end namespace tuple_impl_specific
  285. template<typename Iterator>
  286. struct iterator_reference
  287. {
  288. typedef typename iterator_traits<Iterator>::reference type;
  289. };
  290. #ifdef BOOST_MPL_CFG_NO_FULL_LAMBDA_SUPPORT
  291. // Hack because BOOST_MPL_AUX_LAMBDA_SUPPORT doesn't seem to work
  292. // out well. Instantiating the nested apply template also
  293. // requires instantiating iterator_traits on the
  294. // placeholder. Instead we just specialize it as a metafunction
  295. // class.
  296. template<>
  297. struct iterator_reference<mpl::_1>
  298. {
  299. template <class T>
  300. struct apply : iterator_reference<T> {};
  301. };
  302. #endif
  303. // Metafunction to obtain the type of the tuple whose element types
  304. // are the reference types of an iterator tuple.
  305. //
  306. template<typename IteratorTuple>
  307. struct tuple_of_references
  308. : tuple_impl_specific::tuple_meta_transform<
  309. IteratorTuple,
  310. iterator_reference<mpl::_1>
  311. >
  312. {
  313. };
  314. // Metafunction to obtain the minimal traversal tag in a tuple
  315. // of iterators.
  316. //
  317. template<typename IteratorTuple>
  318. struct minimum_traversal_category_in_iterator_tuple
  319. {
  320. typedef typename tuple_impl_specific::tuple_meta_transform<
  321. IteratorTuple
  322. , iterator_traversal<>
  323. >::type tuple_of_traversal_tags;
  324. typedef typename tuple_impl_specific::tuple_meta_accumulate<
  325. tuple_of_traversal_tags
  326. , minimum_category<>
  327. , random_access_traversal_tag
  328. >::type type;
  329. };
  330. #if BOOST_WORKAROUND(BOOST_MSVC, < 1300) // ETI workaround
  331. template <>
  332. struct minimum_traversal_category_in_iterator_tuple<int>
  333. {
  334. typedef int type;
  335. };
  336. #endif
  337. // We need to call tuple_meta_accumulate with mpl::and_ as the
  338. // accumulating functor. To this end, we need to wrap it into
  339. // a struct that has exactly two arguments (that is, template
  340. // parameters) and not five, like mpl::and_ does.
  341. //
  342. template<typename Arg1, typename Arg2>
  343. struct and_with_two_args
  344. : mpl::and_<Arg1, Arg2>
  345. {
  346. };
  347. # ifdef BOOST_MPL_CFG_NO_FULL_LAMBDA_SUPPORT
  348. // Hack because BOOST_MPL_AUX_LAMBDA_SUPPORT doesn't seem to work
  349. // out well. In this case I think it's an MPL bug
  350. template<>
  351. struct and_with_two_args<mpl::_1,mpl::_2>
  352. {
  353. template <class A1, class A2>
  354. struct apply : mpl::and_<A1,A2>
  355. {};
  356. };
  357. # endif
  358. ///////////////////////////////////////////////////////////////////
  359. //
  360. // Class zip_iterator_base
  361. //
  362. // Builds and exposes the iterator facade type from which the zip
  363. // iterator will be derived.
  364. //
  365. template<typename IteratorTuple>
  366. struct zip_iterator_base
  367. {
  368. private:
  369. // Reference type is the type of the tuple obtained from the
  370. // iterators' reference types.
  371. typedef typename
  372. detail::tuple_of_references<IteratorTuple>::type reference;
  373. // Value type is the same as reference type.
  374. typedef reference value_type;
  375. // Difference type is the first iterator's difference type
  376. typedef typename iterator_traits<
  377. typename tuples::element<0, IteratorTuple>::type
  378. >::difference_type difference_type;
  379. // Traversal catetgory is the minimum traversal category in the
  380. // iterator tuple.
  381. typedef typename
  382. detail::minimum_traversal_category_in_iterator_tuple<
  383. IteratorTuple
  384. >::type traversal_category;
  385. public:
  386. // The iterator facade type from which the zip iterator will
  387. // be derived.
  388. typedef iterator_facade<
  389. zip_iterator<IteratorTuple>,
  390. value_type,
  391. traversal_category,
  392. reference,
  393. difference_type
  394. > type;
  395. };
  396. template <>
  397. struct zip_iterator_base<int>
  398. {
  399. typedef int type;
  400. };
  401. }
  402. /////////////////////////////////////////////////////////////////////
  403. //
  404. // zip_iterator class definition
  405. //
  406. template<typename IteratorTuple>
  407. class zip_iterator :
  408. public detail::zip_iterator_base<IteratorTuple>::type
  409. {
  410. // Typedef super_t as our base class.
  411. typedef typename
  412. detail::zip_iterator_base<IteratorTuple>::type super_t;
  413. // iterator_core_access is the iterator's best friend.
  414. friend class iterator_core_access;
  415. public:
  416. // Construction
  417. // ============
  418. // Default constructor
  419. zip_iterator() { }
  420. // Constructor from iterator tuple
  421. zip_iterator(IteratorTuple iterator_tuple)
  422. : m_iterator_tuple(iterator_tuple)
  423. { }
  424. // Copy constructor
  425. template<typename OtherIteratorTuple>
  426. zip_iterator(
  427. const zip_iterator<OtherIteratorTuple>& other,
  428. typename enable_if_convertible<
  429. OtherIteratorTuple,
  430. IteratorTuple
  431. >::type* = 0
  432. ) : m_iterator_tuple(other.get_iterator_tuple())
  433. {}
  434. // Get method for the iterator tuple.
  435. const IteratorTuple& get_iterator_tuple() const
  436. { return m_iterator_tuple; }
  437. private:
  438. // Implementation of Iterator Operations
  439. // =====================================
  440. // Dereferencing returns a tuple built from the dereferenced
  441. // iterators in the iterator tuple.
  442. typename super_t::reference dereference() const
  443. {
  444. return detail::tuple_impl_specific::tuple_transform(
  445. get_iterator_tuple(),
  446. detail::dereference_iterator()
  447. );
  448. }
  449. // Two zip iterators are equal if all iterators in the iterator
  450. // tuple are equal. NOTE: It should be possible to implement this
  451. // as
  452. //
  453. // return get_iterator_tuple() == other.get_iterator_tuple();
  454. //
  455. // but equality of tuples currently (7/2003) does not compile
  456. // under several compilers. No point in bringing in a bunch
  457. // of #ifdefs here.
  458. //
  459. template<typename OtherIteratorTuple>
  460. bool equal(const zip_iterator<OtherIteratorTuple>& other) const
  461. {
  462. return detail::tuple_impl_specific::tuple_equal(
  463. get_iterator_tuple(),
  464. other.get_iterator_tuple()
  465. );
  466. }
  467. // Advancing a zip iterator means to advance all iterators in the
  468. // iterator tuple.
  469. void advance(typename super_t::difference_type n)
  470. {
  471. detail::tuple_impl_specific::tuple_for_each(
  472. m_iterator_tuple,
  473. detail::advance_iterator<BOOST_DEDUCED_TYPENAME super_t::difference_type>(n)
  474. );
  475. }
  476. // Incrementing a zip iterator means to increment all iterators in
  477. // the iterator tuple.
  478. void increment()
  479. {
  480. detail::tuple_impl_specific::tuple_for_each(
  481. m_iterator_tuple,
  482. detail::increment_iterator()
  483. );
  484. }
  485. // Decrementing a zip iterator means to decrement all iterators in
  486. // the iterator tuple.
  487. void decrement()
  488. {
  489. detail::tuple_impl_specific::tuple_for_each(
  490. m_iterator_tuple,
  491. detail::decrement_iterator()
  492. );
  493. }
  494. // Distance is calculated using the first iterator in the tuple.
  495. template<typename OtherIteratorTuple>
  496. typename super_t::difference_type distance_to(
  497. const zip_iterator<OtherIteratorTuple>& other
  498. ) const
  499. {
  500. return boost::tuples::get<0>(other.get_iterator_tuple()) -
  501. boost::tuples::get<0>(this->get_iterator_tuple());
  502. }
  503. // Data Members
  504. // ============
  505. // The iterator tuple.
  506. IteratorTuple m_iterator_tuple;
  507. };
  508. // Make function for zip iterator
  509. //
  510. template<typename IteratorTuple>
  511. zip_iterator<IteratorTuple>
  512. make_zip_iterator(IteratorTuple t)
  513. { return zip_iterator<IteratorTuple>(t); }
  514. }
  515. #endif