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
8#ifndef BOOST_ZIP_ITERATOR_TMB_07_13_2003_HPP_
9# define BOOST_ZIP_ITERATOR_TMB_07_13_2003_HPP_
10
11#include <stddef.h>
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>
16
17#include <boost/iterator/minimum_category.hpp>
18
19#include <utility> // for std::pair
20#include <boost/fusion/adapted/boost_tuple.hpp> // for backward compatibility
21
22#include <boost/type_traits/remove_reference.hpp>
23#include <boost/type_traits/remove_cv.hpp>
24
25#include <boost/mpl/at.hpp>
26#include <boost/mpl/fold.hpp>
27#include <boost/mpl/transform.hpp>
28#include <boost/mpl/placeholders.hpp>
29
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>
36
37namespace boost {
38namespace iterators {
39
40 // Zip iterator forward declaration for zip_iterator_base
41 template<typename IteratorTuple>
42 class zip_iterator;
43
44 namespace detail
45 {
46
47 // Functors to be used with tuple algorithms
48 //
49 template<typename DiffType>
50 class advance_iterator
51 {
52 public:
53 advance_iterator(DiffType step) : m_step(step) {}
54
55 template<typename Iterator>
56 void operator()(Iterator& it) const
57 { it += m_step; }
58
59 private:
60 DiffType m_step;
61 };
62 //
63 struct increment_iterator
64 {
65 template<typename Iterator>
66 void operator()(Iterator& it) const
67 { ++it; }
68 };
69 //
70 struct decrement_iterator
71 {
72 template<typename Iterator>
73 void operator()(Iterator& it) const
74 { --it; }
75 };
76 //
77 struct dereference_iterator
78 {
79 template<typename>
80 struct result;
81
82 template<typename This, typename Iterator>
83 struct result<This(Iterator)>
84 {
85 typedef typename
86 remove_cv<typename remove_reference<Iterator>::type>::type
87 iterator;
88
89 typedef typename iterator_reference<iterator>::type type;
90 };
91
92 template<typename Iterator>
93 typename result<dereference_iterator(Iterator)>::type
94 operator()(Iterator const& it) const
95 { return *it; }
96 };
97
98 // Metafunction to obtain the type of the tuple whose element types
99 // are the reference types of an iterator tuple.
100 //
101 template<typename IteratorTuple>
102 struct tuple_of_references
103 : mpl::transform<
104 IteratorTuple,
105 iterator_reference<mpl::_1>
106 >
107 {
108 };
109
110 // Specialization for std::pair
111 template<typename Iterator1, typename Iterator2>
112 struct tuple_of_references<std::pair<Iterator1, Iterator2> >
113 {
114 typedef std::pair<
115 typename iterator_reference<Iterator1>::type
116 , typename iterator_reference<Iterator2>::type
117 > type;
118 };
119
120 // Metafunction to obtain the minimal traversal tag in a tuple
121 // of iterators.
122 //
123 template<typename IteratorTuple>
124 struct minimum_traversal_category_in_iterator_tuple
125 {
126 typedef typename mpl::transform<
127 IteratorTuple
128 , pure_traversal_tag<iterator_traversal<> >
129 >::type tuple_of_traversal_tags;
130
131 typedef typename mpl::fold<
132 tuple_of_traversal_tags
133 , random_access_traversal_tag
134 , minimum_category<>
135 >::type type;
136 };
137
138 template<typename Iterator1, typename Iterator2>
139 struct minimum_traversal_category_in_iterator_tuple<std::pair<Iterator1, Iterator2> >
140 {
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;
147
148 typedef typename minimum_category<
149 iterator1_traversal
150 , typename minimum_category<
151 iterator2_traversal
152 , random_access_traversal_tag
153 >::type
154 >::type type;
155 };
156
157 ///////////////////////////////////////////////////////////////////
158 //
159 // Class zip_iterator_base
160 //
161 // Builds and exposes the iterator facade type from which the zip
162 // iterator will be derived.
163 //
164 template<typename IteratorTuple>
165 struct zip_iterator_base
166 {
167 private:
168 // Reference type is the type of the tuple obtained from the
169 // iterators' reference types.
170 typedef typename
171 detail::tuple_of_references<IteratorTuple>::type reference;
172
173 // Value type is the same as reference type.
174 typedef reference value_type;
175
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;
180
181 // Traversal catetgory is the minimum traversal category in the
182 // iterator tuple.
183 typedef typename
184 detail::minimum_traversal_category_in_iterator_tuple<
185 IteratorTuple
186 >::type traversal_category;
187 public:
188
189 // The iterator facade type from which the zip iterator will
190 // be derived.
191 typedef iterator_facade<
192 zip_iterator<IteratorTuple>,
193 value_type,
194 traversal_category,
195 reference,
196 difference_type
197 > type;
198 };
199
200 template <>
201 struct zip_iterator_base<int>
202 {
203 typedef int type;
204 };
205
206 template <typename reference>
207 struct converter
208 {
209 template <typename Seq>
210 static reference call(Seq seq)
211 {
212 typedef typename fusion::traits::tag_of<reference>::type tag;
213 return fusion::convert<tag>(seq);
214 }
215 };
216
217 template <typename Reference1, typename Reference2>
218 struct converter<std::pair<Reference1, Reference2> >
219 {
220 typedef std::pair<Reference1, Reference2> reference;
221 template <typename Seq>
222 static reference call(Seq seq)
223 {
224 return reference(
225 fusion::at_c<0>(seq)
226 , fusion::at_c<1>(seq));
227 }
228 };
229 }
230
231 /////////////////////////////////////////////////////////////////////
232 //
233 // zip_iterator class definition
234 //
235 template<typename IteratorTuple>
236 class zip_iterator :
237 public detail::zip_iterator_base<IteratorTuple>::type
238 {
239
240 // Typedef super_t as our base class.
241 typedef typename
242 detail::zip_iterator_base<IteratorTuple>::type super_t;
243
244 // iterator_core_access is the iterator's best friend.
245 friend class iterator_core_access;
246
247 public:
248
249 // Construction
250 // ============
251
252 // Default constructor
253 zip_iterator() { }
254
255 // Constructor from iterator tuple
256 zip_iterator(IteratorTuple iterator_tuple)
257 : m_iterator_tuple(iterator_tuple)
258 { }
259
260 // Copy constructor
261 template<typename OtherIteratorTuple>
262 zip_iterator(
263 const zip_iterator<OtherIteratorTuple>& other,
264 typename enable_if_convertible<
265 OtherIteratorTuple,
266 IteratorTuple
267 >::type* = 0
268 ) : m_iterator_tuple(other.get_iterator_tuple())
269 {}
270
271 // Get method for the iterator tuple.
272 const IteratorTuple& get_iterator_tuple() const
273 { return m_iterator_tuple; }
274
275 private:
276
277 // Implementation of Iterator Operations
278 // =====================================
279
280 // Dereferencing returns a tuple built from the dereferenced
281 // iterators in the iterator tuple.
282 typename super_t::reference dereference() const
283 {
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()));
289 }
290
291 // Two zip iterators are equal if all iterators in the iterator
292 // tuple are equal. NOTE: It should be possible to implement this
293 // as
294 //
295 // return get_iterator_tuple() == other.get_iterator_tuple();
296 //
297 // but equality of tuples currently (7/2003) does not compile
298 // under several compilers. No point in bringing in a bunch
299 // of #ifdefs here.
300 //
301 template<typename OtherIteratorTuple>
302 bool equal(const zip_iterator<OtherIteratorTuple>& other) const
303 {
304 return fusion::equal_to(
305 get_iterator_tuple(),
306 other.get_iterator_tuple());
307 }
308
309 // Advancing a zip iterator means to advance all iterators in the
310 // iterator tuple.
311 void advance(typename super_t::difference_type n)
312 {
313 fusion::for_each(
314 m_iterator_tuple,
315 detail::advance_iterator<BOOST_DEDUCED_TYPENAME super_t::difference_type>(n));
316 }
317 // Incrementing a zip iterator means to increment all iterators in
318 // the iterator tuple.
319 void increment()
320 {
321 fusion::for_each(
322 m_iterator_tuple,
323 detail::increment_iterator());
324 }
325
326 // Decrementing a zip iterator means to decrement all iterators in
327 // the iterator tuple.
328 void decrement()
329 {
330 fusion::for_each(
331 m_iterator_tuple,
332 detail::decrement_iterator());
333 }
334
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
339 ) const
340 {
341 return fusion::at_c<0>(other.get_iterator_tuple()) -
342 fusion::at_c<0>(this->get_iterator_tuple());
343 }
344
345 // Data Members
346 // ============
347
348 // The iterator tuple.
349 IteratorTuple m_iterator_tuple;
350
351 };
352
353 // Make function for zip iterator
354 //
355 template<typename IteratorTuple>
356 inline zip_iterator<IteratorTuple>
357 make_zip_iterator(IteratorTuple t)
358 { return zip_iterator<IteratorTuple>(t); }
359
360} // namespace iterators
361
362using iterators::zip_iterator;
363using iterators::make_zip_iterator;
364
365} // namespace boost
366
367#endif
368

source code of boost/libs/iterator/include/boost/iterator/zip_iterator.hpp