1 // Copyright David Abrahams and Thomas Becker 2000-2006.
2 // Copyright Kohei Takahashi 2012-2014.
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)
8 #ifndef BOOST_ZIP_ITERATOR_TMB_07_13_2003_HPP_
9 # define BOOST_ZIP_ITERATOR_TMB_07_13_2003_HPP_
12 #include <boost/iterator/iterator_traits.hpp>
13 #include <boost/iterator/iterator_facade.hpp>
14 #include <boost/iterator/iterator_adaptor.hpp> // for enable_if_convertible
15 #include <boost/iterator/iterator_categories.hpp>
17 #include <boost/iterator/minimum_category.hpp>
19 #include <utility> // for std::pair
20 #include <boost/fusion/adapted/boost_tuple.hpp> // for backward compatibility
22 #include <boost/type_traits/remove_reference.hpp>
23 #include <boost/type_traits/remove_cv.hpp>
25 #include <boost/mpl/at.hpp>
26 #include <boost/mpl/fold.hpp>
27 #include <boost/mpl/transform.hpp>
28 #include <boost/mpl/placeholders.hpp>
30 #include <boost/fusion/algorithm/iteration/for_each.hpp>
31 #include <boost/fusion/algorithm/transformation/transform.hpp>
32 #include <boost/fusion/sequence/convert.hpp>
33 #include <boost/fusion/sequence/intrinsic/at_c.hpp>
34 #include <boost/fusion/sequence/comparison/equal_to.hpp>
35 #include <boost/fusion/support/tag_of_fwd.hpp>
40 // Zip iterator forward declaration for zip_iterator_base
41 template<typename IteratorTuple>
47 // Functors to be used with tuple algorithms
49 template<typename DiffType>
50 class advance_iterator
53 advance_iterator(DiffType step) : m_step(step) {}
55 template<typename Iterator>
56 void operator()(Iterator& it) const
63 struct increment_iterator
65 template<typename Iterator>
66 void operator()(Iterator& it) const
70 struct decrement_iterator
72 template<typename Iterator>
73 void operator()(Iterator& it) const
77 struct dereference_iterator
82 template<typename This, typename Iterator>
83 struct result<This(Iterator)>
86 remove_cv<typename remove_reference<Iterator>::type>::type
89 typedef typename iterator_reference<iterator>::type type;
92 template<typename Iterator>
93 typename result<dereference_iterator(Iterator)>::type
94 operator()(Iterator const& it) const
98 // Metafunction to obtain the type of the tuple whose element types
99 // are the reference types of an iterator tuple.
101 template<typename IteratorTuple>
102 struct tuple_of_references
105 iterator_reference<mpl::_1>
110 // Specialization for std::pair
111 template<typename Iterator1, typename Iterator2>
112 struct tuple_of_references<std::pair<Iterator1, Iterator2> >
115 typename iterator_reference<Iterator1>::type
116 , typename iterator_reference<Iterator2>::type
120 // Metafunction to obtain the minimal traversal tag in a tuple
123 template<typename IteratorTuple>
124 struct minimum_traversal_category_in_iterator_tuple
126 typedef typename mpl::transform<
128 , pure_traversal_tag<iterator_traversal<> >
129 >::type tuple_of_traversal_tags;
131 typedef typename mpl::fold<
132 tuple_of_traversal_tags
133 , random_access_traversal_tag
138 template<typename Iterator1, typename Iterator2>
139 struct minimum_traversal_category_in_iterator_tuple<std::pair<Iterator1, Iterator2> >
141 typedef typename pure_traversal_tag<
142 typename iterator_traversal<Iterator1>::type
143 >::type iterator1_traversal;
144 typedef typename pure_traversal_tag<
145 typename iterator_traversal<Iterator2>::type
146 >::type iterator2_traversal;
148 typedef typename minimum_category<
150 , typename minimum_category<
152 , random_access_traversal_tag
157 ///////////////////////////////////////////////////////////////////
159 // Class zip_iterator_base
161 // Builds and exposes the iterator facade type from which the zip
162 // iterator will be derived.
164 template<typename IteratorTuple>
165 struct zip_iterator_base
168 // Reference type is the type of the tuple obtained from the
169 // iterators' reference types.
171 detail::tuple_of_references<IteratorTuple>::type reference;
173 // Value type is the same as reference type.
174 typedef reference value_type;
176 // Difference type is the first iterator's difference type
177 typedef typename iterator_difference<
178 typename mpl::at_c<IteratorTuple, 0>::type
179 >::type difference_type;
181 // Traversal catetgory is the minimum traversal category in the
184 detail::minimum_traversal_category_in_iterator_tuple<
186 >::type traversal_category;
189 // The iterator facade type from which the zip iterator will
191 typedef iterator_facade<
192 zip_iterator<IteratorTuple>,
201 struct zip_iterator_base<int>
206 template <typename reference>
209 template <typename Seq>
210 static reference call(Seq seq)
212 typedef typename fusion::traits::tag_of<reference>::type tag;
213 return fusion::convert<tag>(seq);
217 template <typename Reference1, typename Reference2>
218 struct converter<std::pair<Reference1, Reference2> >
220 typedef std::pair<Reference1, Reference2> reference;
221 template <typename Seq>
222 static reference call(Seq seq)
226 , fusion::at_c<1>(seq));
231 /////////////////////////////////////////////////////////////////////
233 // zip_iterator class definition
235 template<typename IteratorTuple>
237 public detail::zip_iterator_base<IteratorTuple>::type
240 // Typedef super_t as our base class.
242 detail::zip_iterator_base<IteratorTuple>::type super_t;
244 // iterator_core_access is the iterator's best friend.
245 friend class iterator_core_access;
252 // Default constructor
255 // Constructor from iterator tuple
256 zip_iterator(IteratorTuple iterator_tuple)
257 : m_iterator_tuple(iterator_tuple)
261 template<typename OtherIteratorTuple>
263 const zip_iterator<OtherIteratorTuple>& other,
264 typename enable_if_convertible<
268 ) : m_iterator_tuple(other.get_iterator_tuple())
271 // Get method for the iterator tuple.
272 const IteratorTuple& get_iterator_tuple() const
273 { return m_iterator_tuple; }
277 // Implementation of Iterator Operations
278 // =====================================
280 // Dereferencing returns a tuple built from the dereferenced
281 // iterators in the iterator tuple.
282 typename super_t::reference dereference() const
284 typedef typename super_t::reference reference;
285 typedef detail::converter<reference> gen;
286 return gen::call(fusion::transform(
287 get_iterator_tuple(),
288 detail::dereference_iterator()));
291 // Two zip iterators are equal if all iterators in the iterator
292 // tuple are equal. NOTE: It should be possible to implement this
295 // return get_iterator_tuple() == other.get_iterator_tuple();
297 // but equality of tuples currently (7/2003) does not compile
298 // under several compilers. No point in bringing in a bunch
301 template<typename OtherIteratorTuple>
302 bool equal(const zip_iterator<OtherIteratorTuple>& other) const
304 return fusion::equal_to(
305 get_iterator_tuple(),
306 other.get_iterator_tuple());
309 // Advancing a zip iterator means to advance all iterators in the
311 void advance(typename super_t::difference_type n)
315 detail::advance_iterator<BOOST_DEDUCED_TYPENAME super_t::difference_type>(n));
317 // Incrementing a zip iterator means to increment all iterators in
318 // the iterator tuple.
323 detail::increment_iterator());
326 // Decrementing a zip iterator means to decrement all iterators in
327 // the iterator tuple.
332 detail::decrement_iterator());
335 // Distance is calculated using the first iterator in the tuple.
336 template<typename OtherIteratorTuple>
337 typename super_t::difference_type distance_to(
338 const zip_iterator<OtherIteratorTuple>& other
341 return fusion::at_c<0>(other.get_iterator_tuple()) -
342 fusion::at_c<0>(this->get_iterator_tuple());
348 // The iterator tuple.
349 IteratorTuple m_iterator_tuple;
353 // Make function for zip iterator
355 template<typename IteratorTuple>
356 inline zip_iterator<IteratorTuple>
357 make_zip_iterator(IteratorTuple t)
358 { return zip_iterator<IteratorTuple>(t); }
360 } // namespace iterators
362 using iterators::zip_iterator;
363 using iterators::make_zip_iterator;