Chris@16
|
1 // Copyright David Abrahams and Thomas Becker 2000-2006. Distributed
|
Chris@16
|
2 // under the Boost Software License, Version 1.0. (See accompanying
|
Chris@16
|
3 // file LICENSE_1_0.txt or copy at
|
Chris@16
|
4 // http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
5
|
Chris@16
|
6 #ifndef BOOST_ZIP_ITERATOR_TMB_07_13_2003_HPP_
|
Chris@16
|
7 # define BOOST_ZIP_ITERATOR_TMB_07_13_2003_HPP_
|
Chris@16
|
8
|
Chris@16
|
9 #include <stddef.h>
|
Chris@16
|
10 #include <boost/iterator.hpp>
|
Chris@16
|
11 #include <boost/iterator/iterator_traits.hpp>
|
Chris@16
|
12 #include <boost/iterator/iterator_facade.hpp>
|
Chris@16
|
13 #include <boost/iterator/iterator_adaptor.hpp> // for enable_if_convertible
|
Chris@16
|
14 #include <boost/iterator/iterator_categories.hpp>
|
Chris@16
|
15 #include <boost/detail/iterator.hpp>
|
Chris@16
|
16
|
Chris@101
|
17 #include <boost/iterator/minimum_category.hpp>
|
Chris@16
|
18
|
Chris@16
|
19 #include <boost/tuple/tuple.hpp>
|
Chris@16
|
20
|
Chris@16
|
21 #include <boost/type_traits/is_same.hpp>
|
Chris@16
|
22 #include <boost/mpl/and.hpp>
|
Chris@16
|
23 #include <boost/mpl/apply.hpp>
|
Chris@16
|
24 #include <boost/mpl/eval_if.hpp>
|
Chris@16
|
25 #include <boost/mpl/lambda.hpp>
|
Chris@16
|
26 #include <boost/mpl/placeholders.hpp>
|
Chris@16
|
27 #include <boost/mpl/aux_/lambda_support.hpp>
|
Chris@16
|
28
|
Chris@16
|
29 namespace boost {
|
Chris@101
|
30 namespace iterators {
|
Chris@16
|
31
|
Chris@16
|
32 // Zip iterator forward declaration for zip_iterator_base
|
Chris@16
|
33 template<typename IteratorTuple>
|
Chris@16
|
34 class zip_iterator;
|
Chris@16
|
35
|
Chris@16
|
36 // One important design goal of the zip_iterator is to isolate all
|
Chris@16
|
37 // functionality whose implementation relies on the current tuple
|
Chris@16
|
38 // implementation. This goal has been achieved as follows: Inside
|
Chris@16
|
39 // the namespace detail there is a namespace tuple_impl_specific.
|
Chris@16
|
40 // This namespace encapsulates all functionality that is specific
|
Chris@16
|
41 // to the current Boost tuple implementation. More precisely, the
|
Chris@16
|
42 // namespace tuple_impl_specific provides the following tuple
|
Chris@16
|
43 // algorithms and meta-algorithms for the current Boost tuple
|
Chris@16
|
44 // implementation:
|
Chris@16
|
45 //
|
Chris@16
|
46 // tuple_meta_transform
|
Chris@16
|
47 // tuple_meta_accumulate
|
Chris@16
|
48 // tuple_transform
|
Chris@16
|
49 // tuple_for_each
|
Chris@16
|
50 //
|
Chris@16
|
51 // If the tuple implementation changes, all that needs to be
|
Chris@16
|
52 // replaced is the implementation of these four (meta-)algorithms.
|
Chris@16
|
53
|
Chris@16
|
54 namespace detail
|
Chris@16
|
55 {
|
Chris@16
|
56
|
Chris@16
|
57 // Functors to be used with tuple algorithms
|
Chris@16
|
58 //
|
Chris@16
|
59 template<typename DiffType>
|
Chris@16
|
60 class advance_iterator
|
Chris@16
|
61 {
|
Chris@16
|
62 public:
|
Chris@16
|
63 advance_iterator(DiffType step) : m_step(step) {}
|
Chris@101
|
64
|
Chris@16
|
65 template<typename Iterator>
|
Chris@16
|
66 void operator()(Iterator& it) const
|
Chris@16
|
67 { it += m_step; }
|
Chris@16
|
68
|
Chris@16
|
69 private:
|
Chris@16
|
70 DiffType m_step;
|
Chris@16
|
71 };
|
Chris@16
|
72 //
|
Chris@16
|
73 struct increment_iterator
|
Chris@16
|
74 {
|
Chris@16
|
75 template<typename Iterator>
|
Chris@16
|
76 void operator()(Iterator& it)
|
Chris@16
|
77 { ++it; }
|
Chris@16
|
78 };
|
Chris@16
|
79 //
|
Chris@16
|
80 struct decrement_iterator
|
Chris@16
|
81 {
|
Chris@16
|
82 template<typename Iterator>
|
Chris@16
|
83 void operator()(Iterator& it)
|
Chris@16
|
84 { --it; }
|
Chris@16
|
85 };
|
Chris@16
|
86 //
|
Chris@16
|
87 struct dereference_iterator
|
Chris@16
|
88 {
|
Chris@16
|
89 template<typename Iterator>
|
Chris@16
|
90 struct apply
|
Chris@101
|
91 {
|
Chris@16
|
92 typedef typename
|
Chris@101
|
93 boost::detail::iterator_traits<Iterator>::reference
|
Chris@16
|
94 type;
|
Chris@16
|
95 };
|
Chris@16
|
96
|
Chris@16
|
97 template<typename Iterator>
|
Chris@16
|
98 typename apply<Iterator>::type operator()(Iterator const& it)
|
Chris@16
|
99 { return *it; }
|
Chris@16
|
100 };
|
Chris@101
|
101
|
Chris@16
|
102
|
Chris@16
|
103 // The namespace tuple_impl_specific provides two meta-
|
Chris@16
|
104 // algorithms and two algorithms for tuples.
|
Chris@16
|
105 //
|
Chris@16
|
106 namespace tuple_impl_specific
|
Chris@16
|
107 {
|
Chris@16
|
108 // Meta-transform algorithm for tuples
|
Chris@16
|
109 //
|
Chris@16
|
110 template<typename Tuple, class UnaryMetaFun>
|
Chris@16
|
111 struct tuple_meta_transform;
|
Chris@101
|
112
|
Chris@16
|
113 template<typename Tuple, class UnaryMetaFun>
|
Chris@16
|
114 struct tuple_meta_transform_impl
|
Chris@16
|
115 {
|
Chris@16
|
116 typedef tuples::cons<
|
Chris@16
|
117 typename mpl::apply1<
|
Chris@16
|
118 typename mpl::lambda<UnaryMetaFun>::type
|
Chris@16
|
119 , typename Tuple::head_type
|
Chris@16
|
120 >::type
|
Chris@16
|
121 , typename tuple_meta_transform<
|
Chris@16
|
122 typename Tuple::tail_type
|
Chris@101
|
123 , UnaryMetaFun
|
Chris@16
|
124 >::type
|
Chris@16
|
125 > type;
|
Chris@16
|
126 };
|
Chris@16
|
127
|
Chris@16
|
128 template<typename Tuple, class UnaryMetaFun>
|
Chris@16
|
129 struct tuple_meta_transform
|
Chris@16
|
130 : mpl::eval_if<
|
Chris@16
|
131 boost::is_same<Tuple, tuples::null_type>
|
Chris@16
|
132 , mpl::identity<tuples::null_type>
|
Chris@16
|
133 , tuple_meta_transform_impl<Tuple, UnaryMetaFun>
|
Chris@16
|
134 >
|
Chris@16
|
135 {
|
Chris@16
|
136 };
|
Chris@101
|
137
|
Chris@101
|
138 // Meta-accumulate algorithm for tuples. Note: The template
|
Chris@101
|
139 // parameter StartType corresponds to the initial value in
|
Chris@16
|
140 // ordinary accumulation.
|
Chris@16
|
141 //
|
Chris@16
|
142 template<class Tuple, class BinaryMetaFun, class StartType>
|
Chris@16
|
143 struct tuple_meta_accumulate;
|
Chris@101
|
144
|
Chris@16
|
145 template<
|
Chris@16
|
146 typename Tuple
|
Chris@16
|
147 , class BinaryMetaFun
|
Chris@16
|
148 , typename StartType
|
Chris@16
|
149 >
|
Chris@16
|
150 struct tuple_meta_accumulate_impl
|
Chris@16
|
151 {
|
Chris@16
|
152 typedef typename mpl::apply2<
|
Chris@16
|
153 typename mpl::lambda<BinaryMetaFun>::type
|
Chris@16
|
154 , typename Tuple::head_type
|
Chris@16
|
155 , typename tuple_meta_accumulate<
|
Chris@16
|
156 typename Tuple::tail_type
|
Chris@16
|
157 , BinaryMetaFun
|
Chris@101
|
158 , StartType
|
Chris@16
|
159 >::type
|
Chris@16
|
160 >::type type;
|
Chris@16
|
161 };
|
Chris@16
|
162
|
Chris@16
|
163 template<
|
Chris@16
|
164 typename Tuple
|
Chris@16
|
165 , class BinaryMetaFun
|
Chris@16
|
166 , typename StartType
|
Chris@16
|
167 >
|
Chris@16
|
168 struct tuple_meta_accumulate
|
Chris@16
|
169 : mpl::eval_if<
|
Chris@16
|
170 boost::is_same<Tuple, tuples::null_type>
|
Chris@16
|
171 , mpl::identity<StartType>
|
Chris@16
|
172 , tuple_meta_accumulate_impl<
|
Chris@16
|
173 Tuple
|
Chris@16
|
174 , BinaryMetaFun
|
Chris@16
|
175 , StartType
|
Chris@16
|
176 >
|
Chris@16
|
177 >
|
Chris@16
|
178 {
|
Chris@101
|
179 };
|
Chris@16
|
180
|
Chris@16
|
181 #if defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) \
|
Chris@16
|
182 || ( \
|
Chris@16
|
183 BOOST_WORKAROUND(BOOST_INTEL_CXX_VERSION, != 0) && defined(_MSC_VER) \
|
Chris@16
|
184 )
|
Chris@16
|
185 // Not sure why intel's partial ordering fails in this case, but I'm
|
Chris@16
|
186 // assuming int's an MSVC bug-compatibility feature.
|
Chris@101
|
187
|
Chris@16
|
188 # define BOOST_TUPLE_ALGO_DISPATCH
|
Chris@16
|
189 # define BOOST_TUPLE_ALGO(algo) algo##_impl
|
Chris@16
|
190 # define BOOST_TUPLE_ALGO_TERMINATOR , int
|
Chris@16
|
191 # define BOOST_TUPLE_ALGO_RECURSE , ...
|
Chris@101
|
192 #else
|
Chris@16
|
193 # define BOOST_TUPLE_ALGO(algo) algo
|
Chris@16
|
194 # define BOOST_TUPLE_ALGO_TERMINATOR
|
Chris@16
|
195 # define BOOST_TUPLE_ALGO_RECURSE
|
Chris@16
|
196 #endif
|
Chris@101
|
197
|
Chris@16
|
198 // transform algorithm for tuples. The template parameter Fun
|
Chris@16
|
199 // must be a unary functor which is also a unary metafunction
|
Chris@16
|
200 // class that computes its return type based on its argument
|
Chris@16
|
201 // type. For example:
|
Chris@16
|
202 //
|
Chris@16
|
203 // struct to_ptr
|
Chris@16
|
204 // {
|
Chris@16
|
205 // template <class Arg>
|
Chris@16
|
206 // struct apply
|
Chris@16
|
207 // {
|
Chris@16
|
208 // typedef Arg* type;
|
Chris@16
|
209 // }
|
Chris@16
|
210 //
|
Chris@16
|
211 // template <class Arg>
|
Chris@16
|
212 // Arg* operator()(Arg x);
|
Chris@16
|
213 // };
|
Chris@16
|
214 template<typename Fun>
|
Chris@101
|
215 inline tuples::null_type BOOST_TUPLE_ALGO(tuple_transform)
|
Chris@16
|
216 (tuples::null_type const&, Fun BOOST_TUPLE_ALGO_TERMINATOR)
|
Chris@16
|
217 { return tuples::null_type(); }
|
Chris@16
|
218
|
Chris@16
|
219 template<typename Tuple, typename Fun>
|
Chris@101
|
220 inline typename tuple_meta_transform<
|
Chris@16
|
221 Tuple
|
Chris@16
|
222 , Fun
|
Chris@16
|
223 >::type
|
Chris@101
|
224
|
Chris@16
|
225 BOOST_TUPLE_ALGO(tuple_transform)(
|
Chris@101
|
226 const Tuple& t,
|
Chris@16
|
227 Fun f
|
Chris@16
|
228 BOOST_TUPLE_ALGO_RECURSE
|
Chris@16
|
229 )
|
Chris@101
|
230 {
|
Chris@16
|
231 typedef typename tuple_meta_transform<
|
Chris@16
|
232 BOOST_DEDUCED_TYPENAME Tuple::tail_type
|
Chris@16
|
233 , Fun
|
Chris@16
|
234 >::type transformed_tail_type;
|
Chris@16
|
235
|
Chris@16
|
236 return tuples::cons<
|
Chris@16
|
237 BOOST_DEDUCED_TYPENAME mpl::apply1<
|
Chris@16
|
238 Fun, BOOST_DEDUCED_TYPENAME Tuple::head_type
|
Chris@16
|
239 >::type
|
Chris@16
|
240 , transformed_tail_type
|
Chris@101
|
241 >(
|
Chris@16
|
242 f(boost::tuples::get<0>(t)), tuple_transform(t.get_tail(), f)
|
Chris@16
|
243 );
|
Chris@16
|
244 }
|
Chris@16
|
245
|
Chris@16
|
246 #ifdef BOOST_TUPLE_ALGO_DISPATCH
|
Chris@16
|
247 template<typename Tuple, typename Fun>
|
Chris@101
|
248 inline typename tuple_meta_transform<
|
Chris@16
|
249 Tuple
|
Chris@16
|
250 , Fun
|
Chris@16
|
251 >::type
|
Chris@101
|
252
|
Chris@16
|
253 tuple_transform(
|
Chris@101
|
254 const Tuple& t,
|
Chris@16
|
255 Fun f
|
Chris@16
|
256 )
|
Chris@16
|
257 {
|
Chris@16
|
258 return tuple_transform_impl(t, f, 1);
|
Chris@16
|
259 }
|
Chris@16
|
260 #endif
|
Chris@101
|
261
|
Chris@16
|
262 // for_each algorithm for tuples.
|
Chris@16
|
263 //
|
Chris@16
|
264 template<typename Fun>
|
Chris@101
|
265 inline Fun BOOST_TUPLE_ALGO(tuple_for_each)(
|
Chris@16
|
266 tuples::null_type
|
Chris@16
|
267 , Fun f BOOST_TUPLE_ALGO_TERMINATOR
|
Chris@16
|
268 )
|
Chris@16
|
269 { return f; }
|
Chris@16
|
270
|
Chris@101
|
271
|
Chris@16
|
272 template<typename Tuple, typename Fun>
|
Chris@101
|
273 inline Fun BOOST_TUPLE_ALGO(tuple_for_each)(
|
Chris@16
|
274 Tuple& t
|
Chris@16
|
275 , Fun f BOOST_TUPLE_ALGO_RECURSE)
|
Chris@101
|
276 {
|
Chris@16
|
277 f( t.get_head() );
|
Chris@16
|
278 return tuple_for_each(t.get_tail(), f);
|
Chris@16
|
279 }
|
Chris@101
|
280
|
Chris@16
|
281 #ifdef BOOST_TUPLE_ALGO_DISPATCH
|
Chris@16
|
282 template<typename Tuple, typename Fun>
|
Chris@101
|
283 inline Fun
|
Chris@16
|
284 tuple_for_each(
|
Chris@101
|
285 Tuple& t,
|
Chris@16
|
286 Fun f
|
Chris@16
|
287 )
|
Chris@16
|
288 {
|
Chris@16
|
289 return tuple_for_each_impl(t, f, 1);
|
Chris@16
|
290 }
|
Chris@16
|
291 #endif
|
Chris@101
|
292
|
Chris@16
|
293 // Equality of tuples. NOTE: "==" for tuples currently (7/2003)
|
Chris@16
|
294 // has problems under some compilers, so I just do my own.
|
Chris@16
|
295 // No point in bringing in a bunch of #ifdefs here. This is
|
Chris@16
|
296 // going to go away with the next tuple implementation anyway.
|
Chris@16
|
297 //
|
Chris@16
|
298 inline bool tuple_equal(tuples::null_type, tuples::null_type)
|
Chris@16
|
299 { return true; }
|
Chris@16
|
300
|
Chris@16
|
301 template<typename Tuple1, typename Tuple2>
|
Chris@101
|
302 inline bool tuple_equal(Tuple1 const& t1, Tuple2 const& t2)
|
Chris@101
|
303 {
|
Chris@101
|
304 return t1.get_head() == t2.get_head() &&
|
Chris@16
|
305 tuple_equal(t1.get_tail(), t2.get_tail());
|
Chris@16
|
306 }
|
Chris@16
|
307 }
|
Chris@16
|
308 //
|
Chris@16
|
309 // end namespace tuple_impl_specific
|
Chris@16
|
310
|
Chris@16
|
311 template<typename Iterator>
|
Chris@16
|
312 struct iterator_reference
|
Chris@16
|
313 {
|
Chris@101
|
314 typedef typename boost::detail::iterator_traits<Iterator>::reference type;
|
Chris@16
|
315 };
|
Chris@16
|
316
|
Chris@16
|
317 #ifdef BOOST_MPL_CFG_NO_FULL_LAMBDA_SUPPORT
|
Chris@16
|
318 // Hack because BOOST_MPL_AUX_LAMBDA_SUPPORT doesn't seem to work
|
Chris@16
|
319 // out well. Instantiating the nested apply template also
|
Chris@16
|
320 // requires instantiating iterator_traits on the
|
Chris@16
|
321 // placeholder. Instead we just specialize it as a metafunction
|
Chris@16
|
322 // class.
|
Chris@16
|
323 template<>
|
Chris@16
|
324 struct iterator_reference<mpl::_1>
|
Chris@16
|
325 {
|
Chris@16
|
326 template <class T>
|
Chris@16
|
327 struct apply : iterator_reference<T> {};
|
Chris@16
|
328 };
|
Chris@16
|
329 #endif
|
Chris@101
|
330
|
Chris@16
|
331 // Metafunction to obtain the type of the tuple whose element types
|
Chris@16
|
332 // are the reference types of an iterator tuple.
|
Chris@16
|
333 //
|
Chris@16
|
334 template<typename IteratorTuple>
|
Chris@16
|
335 struct tuple_of_references
|
Chris@16
|
336 : tuple_impl_specific::tuple_meta_transform<
|
Chris@101
|
337 IteratorTuple,
|
Chris@16
|
338 iterator_reference<mpl::_1>
|
Chris@16
|
339 >
|
Chris@16
|
340 {
|
Chris@16
|
341 };
|
Chris@16
|
342
|
Chris@16
|
343 // Metafunction to obtain the minimal traversal tag in a tuple
|
Chris@16
|
344 // of iterators.
|
Chris@16
|
345 //
|
Chris@16
|
346 template<typename IteratorTuple>
|
Chris@16
|
347 struct minimum_traversal_category_in_iterator_tuple
|
Chris@16
|
348 {
|
Chris@16
|
349 typedef typename tuple_impl_specific::tuple_meta_transform<
|
Chris@16
|
350 IteratorTuple
|
Chris@16
|
351 , pure_traversal_tag<iterator_traversal<> >
|
Chris@16
|
352 >::type tuple_of_traversal_tags;
|
Chris@101
|
353
|
Chris@16
|
354 typedef typename tuple_impl_specific::tuple_meta_accumulate<
|
Chris@16
|
355 tuple_of_traversal_tags
|
Chris@16
|
356 , minimum_category<>
|
Chris@16
|
357 , random_access_traversal_tag
|
Chris@16
|
358 >::type type;
|
Chris@16
|
359 };
|
Chris@16
|
360
|
Chris@16
|
361 // We need to call tuple_meta_accumulate with mpl::and_ as the
|
Chris@16
|
362 // accumulating functor. To this end, we need to wrap it into
|
Chris@16
|
363 // a struct that has exactly two arguments (that is, template
|
Chris@16
|
364 // parameters) and not five, like mpl::and_ does.
|
Chris@16
|
365 //
|
Chris@16
|
366 template<typename Arg1, typename Arg2>
|
Chris@16
|
367 struct and_with_two_args
|
Chris@16
|
368 : mpl::and_<Arg1, Arg2>
|
Chris@16
|
369 {
|
Chris@16
|
370 };
|
Chris@101
|
371
|
Chris@16
|
372 # ifdef BOOST_MPL_CFG_NO_FULL_LAMBDA_SUPPORT
|
Chris@16
|
373 // Hack because BOOST_MPL_AUX_LAMBDA_SUPPORT doesn't seem to work
|
Chris@16
|
374 // out well. In this case I think it's an MPL bug
|
Chris@16
|
375 template<>
|
Chris@16
|
376 struct and_with_two_args<mpl::_1,mpl::_2>
|
Chris@16
|
377 {
|
Chris@16
|
378 template <class A1, class A2>
|
Chris@16
|
379 struct apply : mpl::and_<A1,A2>
|
Chris@16
|
380 {};
|
Chris@16
|
381 };
|
Chris@101
|
382 # endif
|
Chris@16
|
383
|
Chris@16
|
384 ///////////////////////////////////////////////////////////////////
|
Chris@16
|
385 //
|
Chris@16
|
386 // Class zip_iterator_base
|
Chris@16
|
387 //
|
Chris@101
|
388 // Builds and exposes the iterator facade type from which the zip
|
Chris@16
|
389 // iterator will be derived.
|
Chris@16
|
390 //
|
Chris@16
|
391 template<typename IteratorTuple>
|
Chris@16
|
392 struct zip_iterator_base
|
Chris@16
|
393 {
|
Chris@16
|
394 private:
|
Chris@16
|
395 // Reference type is the type of the tuple obtained from the
|
Chris@16
|
396 // iterators' reference types.
|
Chris@101
|
397 typedef typename
|
Chris@16
|
398 detail::tuple_of_references<IteratorTuple>::type reference;
|
Chris@101
|
399
|
Chris@16
|
400 // Value type is the same as reference type.
|
Chris@16
|
401 typedef reference value_type;
|
Chris@101
|
402
|
Chris@16
|
403 // Difference type is the first iterator's difference type
|
Chris@101
|
404 typedef typename boost::detail::iterator_traits<
|
Chris@16
|
405 typename tuples::element<0, IteratorTuple>::type
|
Chris@16
|
406 >::difference_type difference_type;
|
Chris@101
|
407
|
Chris@101
|
408 // Traversal catetgory is the minimum traversal category in the
|
Chris@16
|
409 // iterator tuple.
|
Chris@101
|
410 typedef typename
|
Chris@16
|
411 detail::minimum_traversal_category_in_iterator_tuple<
|
Chris@16
|
412 IteratorTuple
|
Chris@16
|
413 >::type traversal_category;
|
Chris@16
|
414 public:
|
Chris@101
|
415
|
Chris@16
|
416 // The iterator facade type from which the zip iterator will
|
Chris@16
|
417 // be derived.
|
Chris@16
|
418 typedef iterator_facade<
|
Chris@16
|
419 zip_iterator<IteratorTuple>,
|
Chris@101
|
420 value_type,
|
Chris@16
|
421 traversal_category,
|
Chris@16
|
422 reference,
|
Chris@16
|
423 difference_type
|
Chris@16
|
424 > type;
|
Chris@16
|
425 };
|
Chris@16
|
426
|
Chris@16
|
427 template <>
|
Chris@16
|
428 struct zip_iterator_base<int>
|
Chris@16
|
429 {
|
Chris@16
|
430 typedef int type;
|
Chris@16
|
431 };
|
Chris@16
|
432 }
|
Chris@101
|
433
|
Chris@16
|
434 /////////////////////////////////////////////////////////////////////
|
Chris@16
|
435 //
|
Chris@16
|
436 // zip_iterator class definition
|
Chris@16
|
437 //
|
Chris@16
|
438 template<typename IteratorTuple>
|
Chris@101
|
439 class zip_iterator :
|
Chris@16
|
440 public detail::zip_iterator_base<IteratorTuple>::type
|
Chris@101
|
441 {
|
Chris@16
|
442
|
Chris@101
|
443 // Typedef super_t as our base class.
|
Chris@101
|
444 typedef typename
|
Chris@16
|
445 detail::zip_iterator_base<IteratorTuple>::type super_t;
|
Chris@16
|
446
|
Chris@16
|
447 // iterator_core_access is the iterator's best friend.
|
Chris@16
|
448 friend class iterator_core_access;
|
Chris@16
|
449
|
Chris@16
|
450 public:
|
Chris@101
|
451
|
Chris@16
|
452 // Construction
|
Chris@16
|
453 // ============
|
Chris@101
|
454
|
Chris@16
|
455 // Default constructor
|
Chris@16
|
456 zip_iterator() { }
|
Chris@16
|
457
|
Chris@16
|
458 // Constructor from iterator tuple
|
Chris@101
|
459 zip_iterator(IteratorTuple iterator_tuple)
|
Chris@101
|
460 : m_iterator_tuple(iterator_tuple)
|
Chris@16
|
461 { }
|
Chris@16
|
462
|
Chris@16
|
463 // Copy constructor
|
Chris@16
|
464 template<typename OtherIteratorTuple>
|
Chris@16
|
465 zip_iterator(
|
Chris@16
|
466 const zip_iterator<OtherIteratorTuple>& other,
|
Chris@16
|
467 typename enable_if_convertible<
|
Chris@16
|
468 OtherIteratorTuple,
|
Chris@16
|
469 IteratorTuple
|
Chris@16
|
470 >::type* = 0
|
Chris@16
|
471 ) : m_iterator_tuple(other.get_iterator_tuple())
|
Chris@16
|
472 {}
|
Chris@16
|
473
|
Chris@16
|
474 // Get method for the iterator tuple.
|
Chris@16
|
475 const IteratorTuple& get_iterator_tuple() const
|
Chris@16
|
476 { return m_iterator_tuple; }
|
Chris@16
|
477
|
Chris@16
|
478 private:
|
Chris@101
|
479
|
Chris@16
|
480 // Implementation of Iterator Operations
|
Chris@16
|
481 // =====================================
|
Chris@101
|
482
|
Chris@16
|
483 // Dereferencing returns a tuple built from the dereferenced
|
Chris@16
|
484 // iterators in the iterator tuple.
|
Chris@16
|
485 typename super_t::reference dereference() const
|
Chris@101
|
486 {
|
Chris@101
|
487 return detail::tuple_impl_specific::tuple_transform(
|
Chris@16
|
488 get_iterator_tuple(),
|
Chris@16
|
489 detail::dereference_iterator()
|
Chris@16
|
490 );
|
Chris@16
|
491 }
|
Chris@16
|
492
|
Chris@16
|
493 // Two zip iterators are equal if all iterators in the iterator
|
Chris@16
|
494 // tuple are equal. NOTE: It should be possible to implement this
|
Chris@16
|
495 // as
|
Chris@16
|
496 //
|
Chris@16
|
497 // return get_iterator_tuple() == other.get_iterator_tuple();
|
Chris@16
|
498 //
|
Chris@16
|
499 // but equality of tuples currently (7/2003) does not compile
|
Chris@16
|
500 // under several compilers. No point in bringing in a bunch
|
Chris@16
|
501 // of #ifdefs here.
|
Chris@16
|
502 //
|
Chris@101
|
503 template<typename OtherIteratorTuple>
|
Chris@16
|
504 bool equal(const zip_iterator<OtherIteratorTuple>& other) const
|
Chris@16
|
505 {
|
Chris@16
|
506 return detail::tuple_impl_specific::tuple_equal(
|
Chris@16
|
507 get_iterator_tuple(),
|
Chris@16
|
508 other.get_iterator_tuple()
|
Chris@16
|
509 );
|
Chris@16
|
510 }
|
Chris@16
|
511
|
Chris@16
|
512 // Advancing a zip iterator means to advance all iterators in the
|
Chris@16
|
513 // iterator tuple.
|
Chris@16
|
514 void advance(typename super_t::difference_type n)
|
Chris@101
|
515 {
|
Chris@16
|
516 detail::tuple_impl_specific::tuple_for_each(
|
Chris@16
|
517 m_iterator_tuple,
|
Chris@16
|
518 detail::advance_iterator<BOOST_DEDUCED_TYPENAME super_t::difference_type>(n)
|
Chris@16
|
519 );
|
Chris@16
|
520 }
|
Chris@16
|
521 // Incrementing a zip iterator means to increment all iterators in
|
Chris@16
|
522 // the iterator tuple.
|
Chris@16
|
523 void increment()
|
Chris@101
|
524 {
|
Chris@16
|
525 detail::tuple_impl_specific::tuple_for_each(
|
Chris@16
|
526 m_iterator_tuple,
|
Chris@16
|
527 detail::increment_iterator()
|
Chris@16
|
528 );
|
Chris@16
|
529 }
|
Chris@101
|
530
|
Chris@16
|
531 // Decrementing a zip iterator means to decrement all iterators in
|
Chris@16
|
532 // the iterator tuple.
|
Chris@16
|
533 void decrement()
|
Chris@101
|
534 {
|
Chris@16
|
535 detail::tuple_impl_specific::tuple_for_each(
|
Chris@16
|
536 m_iterator_tuple,
|
Chris@16
|
537 detail::decrement_iterator()
|
Chris@16
|
538 );
|
Chris@16
|
539 }
|
Chris@101
|
540
|
Chris@16
|
541 // Distance is calculated using the first iterator in the tuple.
|
Chris@16
|
542 template<typename OtherIteratorTuple>
|
Chris@16
|
543 typename super_t::difference_type distance_to(
|
Chris@16
|
544 const zip_iterator<OtherIteratorTuple>& other
|
Chris@16
|
545 ) const
|
Chris@101
|
546 {
|
Chris@101
|
547 return boost::tuples::get<0>(other.get_iterator_tuple()) -
|
Chris@16
|
548 boost::tuples::get<0>(this->get_iterator_tuple());
|
Chris@16
|
549 }
|
Chris@101
|
550
|
Chris@16
|
551 // Data Members
|
Chris@16
|
552 // ============
|
Chris@101
|
553
|
Chris@16
|
554 // The iterator tuple.
|
Chris@16
|
555 IteratorTuple m_iterator_tuple;
|
Chris@101
|
556
|
Chris@16
|
557 };
|
Chris@16
|
558
|
Chris@16
|
559 // Make function for zip iterator
|
Chris@16
|
560 //
|
Chris@101
|
561 template<typename IteratorTuple>
|
Chris@101
|
562 inline zip_iterator<IteratorTuple>
|
Chris@16
|
563 make_zip_iterator(IteratorTuple t)
|
Chris@16
|
564 { return zip_iterator<IteratorTuple>(t); }
|
Chris@16
|
565
|
Chris@101
|
566 } // namespace iterators
|
Chris@101
|
567
|
Chris@101
|
568 using iterators::zip_iterator;
|
Chris@101
|
569 using iterators::make_zip_iterator;
|
Chris@101
|
570
|
Chris@101
|
571 } // namespace boost
|
Chris@16
|
572
|
Chris@16
|
573 #endif
|