zip_iterator.hpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369
  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 <utility> // for std::pair
  10. #include <boost/iterator/iterator_traits.hpp>
  11. #include <boost/iterator/iterator_facade.hpp>
  12. #include <boost/iterator/enable_if_convertible.hpp>
  13. #include <boost/iterator/iterator_categories.hpp>
  14. #include <boost/iterator/min_category.hpp>
  15. #include <boost/mp11/list.hpp>
  16. #include <boost/mp11/utility.hpp>
  17. #include <boost/fusion/adapted/boost_tuple.hpp> // for backward compatibility
  18. #include <boost/fusion/algorithm/iteration/for_each.hpp>
  19. #include <boost/fusion/algorithm/transformation/transform.hpp>
  20. #include <boost/fusion/sequence/convert.hpp>
  21. #include <boost/fusion/sequence/intrinsic/at_c.hpp>
  22. #include <boost/fusion/sequence/comparison/equal_to.hpp>
  23. #include <boost/fusion/support/tag_of_fwd.hpp>
  24. namespace boost {
  25. // Forward declarations for Boost.Tuple support
  26. namespace tuples {
  27. struct null_type;
  28. template< class, class >
  29. struct cons;
  30. } // namespace tuples
  31. // Forward declarations for Boost.Fusion support
  32. namespace fusion {
  33. struct void_;
  34. } // namespace fusion
  35. namespace iterators {
  36. // Zip iterator forward declaration for zip_iterator_base
  37. template< typename IteratorTuple >
  38. class zip_iterator;
  39. namespace detail {
  40. // Functors to be used with tuple algorithms
  41. //
  42. template< typename DiffType >
  43. class advance_iterator
  44. {
  45. public:
  46. advance_iterator(DiffType step) :
  47. m_step(step)
  48. {}
  49. template< typename Iterator >
  50. void operator()(Iterator& it) const { it += m_step; }
  51. private:
  52. DiffType m_step;
  53. };
  54. struct increment_iterator
  55. {
  56. template< typename Iterator >
  57. void operator()(Iterator& it) const { ++it; }
  58. };
  59. struct decrement_iterator
  60. {
  61. template< typename Iterator >
  62. void operator()(Iterator& it) const { --it; }
  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. using type = iterator_reference_t<
  72. typename std::remove_cv< typename std::remove_reference< Iterator >::type >::type
  73. >;
  74. };
  75. template< typename Iterator >
  76. typename result< dereference_iterator(Iterator) >::type operator()(Iterator const& it) const
  77. {
  78. return *it;
  79. }
  80. };
  81. // The trait checks if the type is a trailing "null" type used to indicate unused template parameters in non-variadic types
  82. template< typename T >
  83. struct is_trailing_null_type : std::false_type {};
  84. template< typename T >
  85. struct is_trailing_null_type< const T > : is_trailing_null_type< T > {};
  86. template< >
  87. struct is_trailing_null_type< tuples::null_type > : std::true_type {};
  88. template< >
  89. struct is_trailing_null_type< fusion::void_ > : std::true_type {};
  90. // Metafunction to obtain the type of the tuple whose element types
  91. // are the reference types of an iterator tuple.
  92. template< typename IteratorTuple >
  93. struct tuple_of_references;
  94. template< typename IteratorTuple >
  95. using tuple_of_references_t = typename tuple_of_references< IteratorTuple >::type;
  96. template< template< typename... > class Tuple, typename... Iterators >
  97. struct tuple_of_references< Tuple< Iterators... > >
  98. {
  99. // Note: non-variadic Boost.Tuple and Boost.Fusion need special handling
  100. // to avoid instantiating iterator traits on the trailing "null" types.
  101. // If not that, we could simply do
  102. // mp11::mp_transform< iterator_reference_t, IteratorTuple >.
  103. using type = Tuple<
  104. mp11::mp_eval_if<
  105. detail::is_trailing_null_type< Iterators >,
  106. Iterators,
  107. iterator_reference_t, Iterators
  108. >...
  109. >;
  110. };
  111. template< typename Front, typename Tail >
  112. struct tuple_of_references< tuples::cons< Front, Tail > >
  113. {
  114. using type = tuples::cons<
  115. iterator_reference_t< Front >,
  116. mp11::mp_eval_if<
  117. detail::is_trailing_null_type< Tail >,
  118. Tail,
  119. detail::tuple_of_references_t, Tail
  120. >
  121. >;
  122. };
  123. // Metafunction to obtain the minimal traversal tag in a list
  124. // of iterators.
  125. template< typename IteratorList >
  126. struct minimum_traversal_category_in_iterator_list;
  127. template< typename IteratorList >
  128. using minimum_traversal_category_in_iterator_list_t = typename minimum_traversal_category_in_iterator_list< IteratorList >::type;
  129. template< template< typename... > class List, typename... Iterators >
  130. struct minimum_traversal_category_in_iterator_list< List< Iterators... > >
  131. {
  132. // Note: non-variadic Boost.Tuple and Boost.Fusion need special handling
  133. // to avoid instantiating iterator traits on the trailing "null" types.
  134. // For such types just use random_access_traversal_tag, which will not
  135. // affect the result of min_category.
  136. using type = min_category_t<
  137. mp11::mp_eval_if<
  138. detail::is_trailing_null_type< Iterators >,
  139. random_access_traversal_tag,
  140. pure_iterator_traversal_t, Iterators
  141. >...
  142. >;
  143. };
  144. template< typename FrontTraversal, typename Tail >
  145. using minimum_traversal_category_in_tail_t = min_category_t<
  146. FrontTraversal,
  147. minimum_traversal_category_in_iterator_list_t< Tail >
  148. >;
  149. template< typename Front, typename Tail >
  150. struct minimum_traversal_category_in_iterator_list< tuples::cons< Front, Tail > >
  151. {
  152. using front_traversal = pure_iterator_traversal_t< Front >;
  153. using type = mp11::mp_eval_if<
  154. detail::is_trailing_null_type< Tail >,
  155. front_traversal,
  156. minimum_traversal_category_in_tail_t,
  157. front_traversal,
  158. Tail
  159. >;
  160. };
  161. ///////////////////////////////////////////////////////////////////
  162. //
  163. // Class zip_iterator_base
  164. //
  165. // Builds and exposes the iterator facade type from which the zip
  166. // iterator will be derived.
  167. //
  168. template< typename IteratorTuple >
  169. struct zip_iterator_base
  170. {
  171. private:
  172. // Reference type is the type of the tuple obtained from the
  173. // iterators' reference types.
  174. using reference = detail::tuple_of_references_t< IteratorTuple >;
  175. // Value type is the same as reference type.
  176. using value_type = reference;
  177. // Difference type is the first iterator's difference type
  178. using difference_type = iterator_difference_t< mp11::mp_front< IteratorTuple > >;
  179. // Traversal catetgory is the minimum traversal category in the
  180. // iterator tuple.
  181. using traversal_category = detail::minimum_traversal_category_in_iterator_list_t< IteratorTuple >;
  182. public:
  183. // The iterator facade type from which the zip iterator will
  184. // be derived.
  185. using type = iterator_facade<
  186. zip_iterator< IteratorTuple >,
  187. value_type,
  188. traversal_category,
  189. reference,
  190. difference_type
  191. >;
  192. };
  193. template< typename Reference >
  194. struct converter
  195. {
  196. template< typename Seq >
  197. static Reference call(Seq seq)
  198. {
  199. using tag = typename fusion::traits::tag_of< Reference >::type;
  200. return fusion::convert< tag >(seq);
  201. }
  202. };
  203. template< typename Reference1, typename Reference2 >
  204. struct converter< std::pair< Reference1, Reference2 > >
  205. {
  206. using reference = std::pair< Reference1, Reference2 >;
  207. template< typename Seq >
  208. static reference call(Seq seq)
  209. {
  210. return reference(fusion::at_c< 0 >(seq), fusion::at_c< 1 >(seq));
  211. }
  212. };
  213. } // namespace detail
  214. /////////////////////////////////////////////////////////////////////
  215. //
  216. // zip_iterator class definition
  217. //
  218. template< typename IteratorTuple >
  219. class zip_iterator :
  220. public detail::zip_iterator_base< IteratorTuple >::type
  221. {
  222. // Typedef super_t as our base class.
  223. using super_t = typename detail::zip_iterator_base< IteratorTuple >::type;
  224. // iterator_core_access is the iterator's best friend.
  225. friend class iterator_core_access;
  226. public:
  227. // Construction
  228. // ============
  229. // Default constructor
  230. zip_iterator() = default;
  231. // Constructor from iterator tuple
  232. zip_iterator(IteratorTuple iterator_tuple) :
  233. m_iterator_tuple(iterator_tuple)
  234. {}
  235. // Copy constructor
  236. template< typename OtherIteratorTuple, typename = enable_if_convertible_t< OtherIteratorTuple, IteratorTuple > >
  237. zip_iterator(zip_iterator< OtherIteratorTuple > const& other) :
  238. m_iterator_tuple(other.get_iterator_tuple())
  239. {}
  240. // Get method for the iterator tuple.
  241. IteratorTuple const& get_iterator_tuple() const { return m_iterator_tuple; }
  242. private:
  243. // Implementation of Iterator Operations
  244. // =====================================
  245. // Dereferencing returns a tuple built from the dereferenced
  246. // iterators in the iterator tuple.
  247. typename super_t::reference dereference() const
  248. {
  249. using reference = typename super_t::reference;
  250. using gen = detail::converter< reference >;
  251. return gen::call(fusion::transform(get_iterator_tuple(), detail::dereference_iterator()));
  252. }
  253. // Two zip iterators are equal if all iterators in the iterator
  254. // tuple are equal. NOTE: It should be possible to implement this
  255. // as
  256. //
  257. // return get_iterator_tuple() == other.get_iterator_tuple();
  258. //
  259. // but equality of tuples currently (7/2003) does not compile
  260. // under several compilers. No point in bringing in a bunch
  261. // of #ifdefs here.
  262. //
  263. template< typename OtherIteratorTuple >
  264. bool equal(zip_iterator< OtherIteratorTuple > const& other) const
  265. {
  266. return fusion::equal_to(get_iterator_tuple(), other.get_iterator_tuple());
  267. }
  268. // Advancing a zip iterator means to advance all iterators in the
  269. // iterator tuple.
  270. void advance(typename super_t::difference_type n)
  271. {
  272. fusion::for_each(m_iterator_tuple, detail::advance_iterator< typename super_t::difference_type >(n));
  273. }
  274. // Incrementing a zip iterator means to increment all iterators in
  275. // the iterator tuple.
  276. void increment()
  277. {
  278. fusion::for_each(m_iterator_tuple, detail::increment_iterator());
  279. }
  280. // Decrementing a zip iterator means to decrement all iterators in
  281. // the iterator tuple.
  282. void decrement()
  283. {
  284. fusion::for_each(m_iterator_tuple, detail::decrement_iterator());
  285. }
  286. // Distance is calculated using the first iterator in the tuple.
  287. template< typename OtherIteratorTuple >
  288. typename super_t::difference_type distance_to(zip_iterator< OtherIteratorTuple > const& other) const
  289. {
  290. return fusion::at_c< 0 >(other.get_iterator_tuple()) - fusion::at_c< 0 >(this->get_iterator_tuple());
  291. }
  292. private:
  293. // Data Members
  294. // ============
  295. // The iterator tuple.
  296. IteratorTuple m_iterator_tuple;
  297. };
  298. // Make function for zip iterator
  299. //
  300. template< typename IteratorTuple >
  301. inline zip_iterator< IteratorTuple > make_zip_iterator(IteratorTuple t)
  302. {
  303. return zip_iterator< IteratorTuple >(t);
  304. }
  305. } // namespace iterators
  306. using iterators::zip_iterator;
  307. using iterators::make_zip_iterator;
  308. } // namespace boost
  309. #endif