zip_iterator.hpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  1. // Copyright David Abrahams and Thomas Becker 2000-2006.
  2. // Copyright Kohei Takahashi 2012-2014.
  3. //
  4. // Distributed under the Boost Software License, Version 1.0. (See
  5. // accompanying file LICENSE_1_0.txt or copy at
  6. // http://www.boost.org/LICENSE_1_0.txt)
  7. #ifndef BOOST_ZIP_ITERATOR_TMB_07_13_2003_HPP_
  8. # define BOOST_ZIP_ITERATOR_TMB_07_13_2003_HPP_
  9. #include <stddef.h>
  10. #include <boost/iterator/iterator_traits.hpp>
  11. #include <boost/iterator/iterator_facade.hpp>
  12. #include <boost/iterator/iterator_adaptor.hpp> // for enable_if_convertible
  13. #include <boost/iterator/iterator_categories.hpp>
  14. #include <boost/iterator/minimum_category.hpp>
  15. #include <utility> // for std::pair
  16. #include <boost/fusion/adapted/boost_tuple.hpp> // for backward compatibility
  17. #include <boost/type_traits/remove_reference.hpp>
  18. #include <boost/type_traits/remove_cv.hpp>
  19. #include <boost/mpl/at.hpp>
  20. #include <boost/mpl/fold.hpp>
  21. #include <boost/mpl/transform.hpp>
  22. #include <boost/mpl/placeholders.hpp>
  23. #include <boost/fusion/algorithm/iteration/for_each.hpp>
  24. #include <boost/fusion/algorithm/transformation/transform.hpp>
  25. #include <boost/fusion/sequence/convert.hpp>
  26. #include <boost/fusion/sequence/intrinsic/at_c.hpp>
  27. #include <boost/fusion/sequence/comparison/equal_to.hpp>
  28. #include <boost/fusion/support/tag_of_fwd.hpp>
  29. namespace boost {
  30. namespace iterators {
  31. // Zip iterator forward declaration for zip_iterator_base
  32. template<typename IteratorTuple>
  33. class zip_iterator;
  34. namespace detail
  35. {
  36. // Functors to be used with tuple algorithms
  37. //
  38. template<typename DiffType>
  39. class advance_iterator
  40. {
  41. public:
  42. advance_iterator(DiffType step) : m_step(step) {}
  43. template<typename Iterator>
  44. void operator()(Iterator& it) const
  45. { it += m_step; }
  46. private:
  47. DiffType m_step;
  48. };
  49. //
  50. struct increment_iterator
  51. {
  52. template<typename Iterator>
  53. void operator()(Iterator& it) const
  54. { ++it; }
  55. };
  56. //
  57. struct decrement_iterator
  58. {
  59. template<typename Iterator>
  60. void operator()(Iterator& it) const
  61. { --it; }
  62. };
  63. //
  64. struct dereference_iterator
  65. {
  66. template<typename>
  67. struct result;
  68. template<typename This, typename Iterator>
  69. struct result<This(Iterator)>
  70. {
  71. typedef typename
  72. remove_cv<typename remove_reference<Iterator>::type>::type
  73. iterator;
  74. typedef typename iterator_reference<iterator>::type type;
  75. };
  76. template<typename Iterator>
  77. typename result<dereference_iterator(Iterator)>::type
  78. operator()(Iterator const& it) const
  79. { return *it; }
  80. };
  81. // Metafunction to obtain the type of the tuple whose element types
  82. // are the reference types of an iterator tuple.
  83. //
  84. template<typename IteratorTuple>
  85. struct tuple_of_references
  86. : mpl::transform<
  87. IteratorTuple,
  88. iterator_reference<mpl::_1>
  89. >
  90. {
  91. };
  92. // Specialization for std::pair
  93. template<typename Iterator1, typename Iterator2>
  94. struct tuple_of_references<std::pair<Iterator1, Iterator2> >
  95. {
  96. typedef std::pair<
  97. typename iterator_reference<Iterator1>::type
  98. , typename iterator_reference<Iterator2>::type
  99. > type;
  100. };
  101. // Metafunction to obtain the minimal traversal tag in a tuple
  102. // of iterators.
  103. //
  104. template<typename IteratorTuple>
  105. struct minimum_traversal_category_in_iterator_tuple
  106. {
  107. typedef typename mpl::transform<
  108. IteratorTuple
  109. , pure_traversal_tag<iterator_traversal<> >
  110. >::type tuple_of_traversal_tags;
  111. typedef typename mpl::fold<
  112. tuple_of_traversal_tags
  113. , random_access_traversal_tag
  114. , minimum_category<>
  115. >::type type;
  116. };
  117. template<typename Iterator1, typename Iterator2>
  118. struct minimum_traversal_category_in_iterator_tuple<std::pair<Iterator1, Iterator2> >
  119. {
  120. typedef typename pure_traversal_tag<
  121. typename iterator_traversal<Iterator1>::type
  122. >::type iterator1_traversal;
  123. typedef typename pure_traversal_tag<
  124. typename iterator_traversal<Iterator2>::type
  125. >::type iterator2_traversal;
  126. typedef typename minimum_category<
  127. iterator1_traversal
  128. , typename minimum_category<
  129. iterator2_traversal
  130. , random_access_traversal_tag
  131. >::type
  132. >::type type;
  133. };
  134. ///////////////////////////////////////////////////////////////////
  135. //
  136. // Class zip_iterator_base
  137. //
  138. // Builds and exposes the iterator facade type from which the zip
  139. // iterator will be derived.
  140. //
  141. template<typename IteratorTuple>
  142. struct zip_iterator_base
  143. {
  144. private:
  145. // Reference type is the type of the tuple obtained from the
  146. // iterators' reference types.
  147. typedef typename
  148. detail::tuple_of_references<IteratorTuple>::type reference;
  149. // Value type is the same as reference type.
  150. typedef reference value_type;
  151. // Difference type is the first iterator's difference type
  152. typedef typename iterator_difference<
  153. typename mpl::at_c<IteratorTuple, 0>::type
  154. >::type difference_type;
  155. // Traversal catetgory is the minimum traversal category in the
  156. // iterator tuple.
  157. typedef typename
  158. detail::minimum_traversal_category_in_iterator_tuple<
  159. IteratorTuple
  160. >::type traversal_category;
  161. public:
  162. // The iterator facade type from which the zip iterator will
  163. // be derived.
  164. typedef iterator_facade<
  165. zip_iterator<IteratorTuple>,
  166. value_type,
  167. traversal_category,
  168. reference,
  169. difference_type
  170. > type;
  171. };
  172. template <>
  173. struct zip_iterator_base<int>
  174. {
  175. typedef int type;
  176. };
  177. template <typename reference>
  178. struct converter
  179. {
  180. template <typename Seq>
  181. static reference call(Seq seq)
  182. {
  183. typedef typename fusion::traits::tag_of<reference>::type tag;
  184. return fusion::convert<tag>(seq);
  185. }
  186. };
  187. template <typename Reference1, typename Reference2>
  188. struct converter<std::pair<Reference1, Reference2> >
  189. {
  190. typedef std::pair<Reference1, Reference2> reference;
  191. template <typename Seq>
  192. static reference call(Seq seq)
  193. {
  194. return reference(
  195. fusion::at_c<0>(seq)
  196. , fusion::at_c<1>(seq));
  197. }
  198. };
  199. }
  200. /////////////////////////////////////////////////////////////////////
  201. //
  202. // zip_iterator class definition
  203. //
  204. template<typename IteratorTuple>
  205. class zip_iterator :
  206. public detail::zip_iterator_base<IteratorTuple>::type
  207. {
  208. // Typedef super_t as our base class.
  209. typedef typename
  210. detail::zip_iterator_base<IteratorTuple>::type super_t;
  211. // iterator_core_access is the iterator's best friend.
  212. friend class iterator_core_access;
  213. public:
  214. // Construction
  215. // ============
  216. // Default constructor
  217. zip_iterator() { }
  218. // Constructor from iterator tuple
  219. zip_iterator(IteratorTuple iterator_tuple)
  220. : m_iterator_tuple(iterator_tuple)
  221. { }
  222. // Copy constructor
  223. template<typename OtherIteratorTuple>
  224. zip_iterator(
  225. const zip_iterator<OtherIteratorTuple>& other,
  226. typename enable_if_convertible<
  227. OtherIteratorTuple,
  228. IteratorTuple
  229. >::type* = 0
  230. ) : m_iterator_tuple(other.get_iterator_tuple())
  231. {}
  232. // Get method for the iterator tuple.
  233. const IteratorTuple& get_iterator_tuple() const
  234. { return m_iterator_tuple; }
  235. private:
  236. // Implementation of Iterator Operations
  237. // =====================================
  238. // Dereferencing returns a tuple built from the dereferenced
  239. // iterators in the iterator tuple.
  240. typename super_t::reference dereference() const
  241. {
  242. typedef typename super_t::reference reference;
  243. typedef detail::converter<reference> gen;
  244. return gen::call(fusion::transform(
  245. get_iterator_tuple(),
  246. detail::dereference_iterator()));
  247. }
  248. // Two zip iterators are equal if all iterators in the iterator
  249. // tuple are equal. NOTE: It should be possible to implement this
  250. // as
  251. //
  252. // return get_iterator_tuple() == other.get_iterator_tuple();
  253. //
  254. // but equality of tuples currently (7/2003) does not compile
  255. // under several compilers. No point in bringing in a bunch
  256. // of #ifdefs here.
  257. //
  258. template<typename OtherIteratorTuple>
  259. bool equal(const zip_iterator<OtherIteratorTuple>& other) const
  260. {
  261. return fusion::equal_to(
  262. get_iterator_tuple(),
  263. other.get_iterator_tuple());
  264. }
  265. // Advancing a zip iterator means to advance all iterators in the
  266. // iterator tuple.
  267. void advance(typename super_t::difference_type n)
  268. {
  269. fusion::for_each(
  270. m_iterator_tuple,
  271. detail::advance_iterator<BOOST_DEDUCED_TYPENAME super_t::difference_type>(n));
  272. }
  273. // Incrementing a zip iterator means to increment all iterators in
  274. // the iterator tuple.
  275. void increment()
  276. {
  277. fusion::for_each(
  278. m_iterator_tuple,
  279. detail::increment_iterator());
  280. }
  281. // Decrementing a zip iterator means to decrement all iterators in
  282. // the iterator tuple.
  283. void decrement()
  284. {
  285. fusion::for_each(
  286. m_iterator_tuple,
  287. detail::decrement_iterator());
  288. }
  289. // Distance is calculated using the first iterator in the tuple.
  290. template<typename OtherIteratorTuple>
  291. typename super_t::difference_type distance_to(
  292. const zip_iterator<OtherIteratorTuple>& other
  293. ) const
  294. {
  295. return fusion::at_c<0>(other.get_iterator_tuple()) -
  296. fusion::at_c<0>(this->get_iterator_tuple());
  297. }
  298. // Data Members
  299. // ============
  300. // The iterator tuple.
  301. IteratorTuple m_iterator_tuple;
  302. };
  303. // Make function for zip iterator
  304. //
  305. template<typename IteratorTuple>
  306. inline zip_iterator<IteratorTuple>
  307. make_zip_iterator(IteratorTuple t)
  308. { return zip_iterator<IteratorTuple>(t); }
  309. } // namespace iterators
  310. using iterators::zip_iterator;
  311. using iterators::make_zip_iterator;
  312. } // namespace boost
  313. #endif