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.hpp>
13 #include <boost/iterator/iterator_traits.hpp>
14 #include <boost/iterator/iterator_facade.hpp>
15 #include <boost/iterator/iterator_adaptor.hpp> // for enable_if_convertible
16 #include <boost/iterator/iterator_categories.hpp>
18 #include <boost/iterator/minimum_category.hpp>
20 #include <utility> // for std::pair
21 #include <boost/fusion/adapted/boost_tuple.hpp> // for backward compatibility
23 #include <boost/type_traits/remove_reference.hpp>
24 #include <boost/type_traits/remove_cv.hpp>
26 #include <boost/mpl/at.hpp>
27 #include <boost/mpl/fold.hpp>
28 #include <boost/mpl/transform.hpp>
29 #include <boost/mpl/placeholders.hpp>
31 #include <boost/fusion/algorithm/iteration/for_each.hpp>
32 #include <boost/fusion/algorithm/transformation/transform.hpp>
33 #include <boost/fusion/sequence/convert.hpp>
34 #include <boost/fusion/sequence/intrinsic/at_c.hpp>
35 #include <boost/fusion/sequence/comparison/equal_to.hpp>
36 #include <boost/fusion/support/tag_of_fwd.hpp>
41 // Zip iterator forward declaration for zip_iterator_base
42 template<typename IteratorTuple>
48 // Functors to be used with tuple algorithms
50 template<typename DiffType>
51 class advance_iterator
54 advance_iterator(DiffType step) : m_step(step) {}
56 template<typename Iterator>
57 void operator()(Iterator& it) const
64 struct increment_iterator
66 template<typename Iterator>
67 void operator()(Iterator& it) const
71 struct decrement_iterator
73 template<typename Iterator>
74 void operator()(Iterator& it) const
78 struct dereference_iterator
83 template<typename This, typename Iterator>
84 struct result<This(Iterator)>
87 remove_reference<typename remove_cv<Iterator>::type>::type
90 typedef typename iterator_reference<iterator>::type type;
93 template<typename Iterator>
94 typename result<dereference_iterator(Iterator)>::type
95 operator()(Iterator const& it) const
99 // Metafunction to obtain the type of the tuple whose element types
100 // are the reference types of an iterator tuple.
102 template<typename IteratorTuple>
103 struct tuple_of_references
106 iterator_reference<mpl::_1>
111 // Specialization for std::pair
112 template<typename Iterator1, typename Iterator2>
113 struct tuple_of_references<std::pair<Iterator1, Iterator2> >
116 typename iterator_reference<Iterator1>::type
117 , typename iterator_reference<Iterator2>::type
121 // Metafunction to obtain the minimal traversal tag in a tuple
124 template<typename IteratorTuple>
125 struct minimum_traversal_category_in_iterator_tuple
127 typedef typename mpl::transform<
129 , pure_traversal_tag<iterator_traversal<> >
130 >::type tuple_of_traversal_tags;
132 typedef typename mpl::fold<
133 tuple_of_traversal_tags
134 , random_access_traversal_tag
139 template<typename Iterator1, typename Iterator2>
140 struct minimum_traversal_category_in_iterator_tuple<std::pair<Iterator1, Iterator2> >
142 typedef typename pure_traversal_tag<
143 typename iterator_traversal<Iterator1>::type
144 >::type iterator1_traversal;
145 typedef typename pure_traversal_tag<
146 typename iterator_traversal<Iterator2>::type
147 >::type iterator2_traversal;
149 typedef typename minimum_category<
151 , typename minimum_category<
153 , random_access_traversal_tag
158 ///////////////////////////////////////////////////////////////////
160 // Class zip_iterator_base
162 // Builds and exposes the iterator facade type from which the zip
163 // iterator will be derived.
165 template<typename IteratorTuple>
166 struct zip_iterator_base
169 // Reference type is the type of the tuple obtained from the
170 // iterators' reference types.
172 detail::tuple_of_references<IteratorTuple>::type reference;
174 // Value type is the same as reference type.
175 typedef reference value_type;
177 // Difference type is the first iterator's difference type
178 typedef typename iterator_difference<
179 typename mpl::at_c<IteratorTuple, 0>::type
180 >::type difference_type;
182 // Traversal catetgory is the minimum traversal category in the
185 detail::minimum_traversal_category_in_iterator_tuple<
187 >::type traversal_category;
190 // The iterator facade type from which the zip iterator will
192 typedef iterator_facade<
193 zip_iterator<IteratorTuple>,
202 struct zip_iterator_base<int>
207 template <typename reference>
210 template <typename Seq>
211 static reference call(Seq seq)
213 typedef typename fusion::traits::tag_of<reference>::type tag;
214 return fusion::convert<tag>(seq);
218 template <typename Reference1, typename Reference2>
219 struct converter<std::pair<Reference1, Reference2> >
221 typedef std::pair<Reference1, Reference2> reference;
222 template <typename Seq>
223 static reference call(Seq seq)
227 , fusion::at_c<1>(seq));
232 /////////////////////////////////////////////////////////////////////
234 // zip_iterator class definition
236 template<typename IteratorTuple>
238 public detail::zip_iterator_base<IteratorTuple>::type
241 // Typedef super_t as our base class.
243 detail::zip_iterator_base<IteratorTuple>::type super_t;
245 // iterator_core_access is the iterator's best friend.
246 friend class iterator_core_access;
253 // Default constructor
256 // Constructor from iterator tuple
257 zip_iterator(IteratorTuple iterator_tuple)
258 : m_iterator_tuple(iterator_tuple)
262 template<typename OtherIteratorTuple>
264 const zip_iterator<OtherIteratorTuple>& other,
265 typename enable_if_convertible<
269 ) : m_iterator_tuple(other.get_iterator_tuple())
272 // Get method for the iterator tuple.
273 const IteratorTuple& get_iterator_tuple() const
274 { return m_iterator_tuple; }
278 // Implementation of Iterator Operations
279 // =====================================
281 // Dereferencing returns a tuple built from the dereferenced
282 // iterators in the iterator tuple.
283 typename super_t::reference dereference() const
285 typedef typename super_t::reference reference;
286 typedef detail::converter<reference> gen;
287 return gen::call(fusion::transform(
288 get_iterator_tuple(),
289 detail::dereference_iterator()));
292 // Two zip iterators are equal if all iterators in the iterator
293 // tuple are equal. NOTE: It should be possible to implement this
296 // return get_iterator_tuple() == other.get_iterator_tuple();
298 // but equality of tuples currently (7/2003) does not compile
299 // under several compilers. No point in bringing in a bunch
302 template<typename OtherIteratorTuple>
303 bool equal(const zip_iterator<OtherIteratorTuple>& other) const
305 return fusion::equal_to(
306 get_iterator_tuple(),
307 other.get_iterator_tuple());
310 // Advancing a zip iterator means to advance all iterators in the
312 void advance(typename super_t::difference_type n)
316 detail::advance_iterator<BOOST_DEDUCED_TYPENAME super_t::difference_type>(n));
318 // Incrementing a zip iterator means to increment all iterators in
319 // the iterator tuple.
324 detail::increment_iterator());
327 // Decrementing a zip iterator means to decrement all iterators in
328 // the iterator tuple.
333 detail::decrement_iterator());
336 // Distance is calculated using the first iterator in the tuple.
337 template<typename OtherIteratorTuple>
338 typename super_t::difference_type distance_to(
339 const zip_iterator<OtherIteratorTuple>& other
342 return fusion::at_c<0>(other.get_iterator_tuple()) -
343 fusion::at_c<0>(this->get_iterator_tuple());
349 // The iterator tuple.
350 IteratorTuple m_iterator_tuple;
354 // Make function for zip iterator
356 template<typename IteratorTuple>
357 inline zip_iterator<IteratorTuple>
358 make_zip_iterator(IteratorTuple t)
359 { return zip_iterator<IteratorTuple>(t); }
361 } // namespace iterators
363 using iterators::zip_iterator;
364 using iterators::make_zip_iterator;