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 | |
37 | namespace boost { |
38 | namespace 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 | |
362 | using iterators::zip_iterator; |
363 | using iterators::make_zip_iterator; |
364 | |
365 | } // namespace boost |
366 | |
367 | #endif |
368 | |