2 [section:zip Zip Iterator]
4 The zip iterator provides the ability to parallel-iterate
5 over several controlled sequences simultaneously. A zip
6 iterator is constructed from a tuple of iterators. Moving
7 the zip iterator moves all the iterators in parallel.
8 Dereferencing the zip iterator returns a tuple that contains
9 the results of dereferencing the individual iterators.
11 The tuple of iterators is now implemented in terms of a Boost fusion sequence.
12 Because of this the 'tuple' may be any Boost fusion sequence and, for backwards
13 compatibility through a Boost fusion sequence adapter, a Boost tuple. Because the
14 'tuple' may be any boost::fusion sequence the 'tuple' may also be any type for which a
15 Boost fusion adapter exists. This includes, among others, a std::tuple and a std::pair.
16 Just remember to include the appropriate Boost fusion adapter header files for these
17 other Boost fusion adapters. The zip_iterator header file already includes the
18 Boost fusion adapter header file for Boost tuple, so you need not include it yourself
19 to use a Boost tuple as your 'tuple'.
21 [section:zip_example Example]
23 There are two main types of applications of the `zip_iterator`. The first
24 one concerns runtime efficiency: If one has several controlled sequences
25 of the same length that must be somehow processed, e.g., with the
26 `for_each` algorithm, then it is more efficient to perform just
27 one parallel-iteration rather than several individual iterations. For an
28 example, assume that `vect_of_doubles` and `vect_of_ints`
29 are two vectors of equal length containing doubles and ints, respectively,
30 and consider the following two iterations:
32 std::vector<double>::const_iterator beg1 = vect_of_doubles.begin();
33 std::vector<double>::const_iterator end1 = vect_of_doubles.end();
34 std::vector<int>::const_iterator beg2 = vect_of_ints.begin();
35 std::vector<int>::const_iterator end2 = vect_of_ints.end();
37 std::for_each(beg1, end1, func_0());
38 std::for_each(beg2, end2, func_1());
40 These two iterations can now be replaced with a single one as follows:
44 boost::make_zip_iterator(
45 boost::make_tuple(beg1, beg2)
47 boost::make_zip_iterator(
48 boost::make_tuple(end1, end2)
53 A non-generic implementation of `zip_func` could look as follows:
57 public std::unary_function<const boost::tuple<const double&, const int&>&, void>
59 void operator()(const boost::tuple<const double&, const int&>& t) const
70 The second important application of the `zip_iterator` is as a building block
71 to make combining iterators. A combining iterator is an iterator
72 that parallel-iterates over several controlled sequences and, upon
73 dereferencing, returns the result of applying a functor to the values of the
74 sequences at the respective positions. This can now be achieved by using the
75 `zip_iterator` in conjunction with the `transform_iterator`.
77 Suppose, for example, that you have two vectors of doubles, say
78 `vect_1` and `vect_2`, and you need to expose to a client
79 a controlled sequence containing the products of the elements of
80 `vect_1` and `vect_2`. Rather than placing these products
81 in a third vector, you can use a combining iterator that calculates the
82 products on the fly. Let us assume that `tuple_multiplies` is a
83 functor that works like `std::multiplies`, except that it takes
84 its two arguments packaged in a tuple. Then the two iterators
85 `it_begin` and `it_end` defined below delimit a controlled
86 sequence containing the products of the elements of `vect_1` and
90 std::vector<double>::const_iterator,
91 std::vector<double>::const_iterator
94 typedef boost::zip_iterator<
98 typedef boost::transform_iterator<
99 tuple_multiplies<double>,
101 > the_transform_iterator;
103 the_transform_iterator it_begin(
110 tuple_multiplies<double>()
113 the_transform_iterator it_end(
120 tuple_multiplies<double>()
125 [section:zip_reference Reference]
129 template<typename IteratorTuple>
134 typedef /* see below */ reference;
135 typedef reference value_type;
136 typedef value_type* pointer;
137 typedef /* see below */ difference_type;
138 typedef /* see below */ iterator_category;
141 zip_iterator(IteratorTuple iterator_tuple);
143 template<typename OtherIteratorTuple>
145 const zip_iterator<OtherIteratorTuple>& other
146 , typename enable_if_convertible<
148 , IteratorTuple>::type* = 0 // exposition only
151 const IteratorTuple& get_iterator_tuple() const;
154 IteratorTuple m_iterator_tuple; // exposition only
157 template<typename IteratorTuple>
158 zip_iterator<IteratorTuple>
159 make_zip_iterator(IteratorTuple t);
161 The `reference` member of `zip_iterator` is the type of the tuple
162 made of the reference types of the iterator types in the `IteratorTuple`
165 The `difference_type` member of `zip_iterator` is the `difference_type`
166 of the first of the iterator types in the `IteratorTuple` argument.
168 The `iterator_category` member of `zip_iterator` is convertible to the
169 minimum of the traversal categories of the iterator types in the `IteratorTuple`
170 argument. For example, if the `zip_iterator` holds only vector
171 iterators, then `iterator_category` is convertible to
172 `boost::random_access_traversal_tag`. If you add a list iterator, then
173 `iterator_category` will be convertible to `boost::bidirectional_traversal_tag`,
174 but no longer to `boost::random_access_traversal_tag`.
178 All iterator types in the argument `IteratorTuple` shall model Readable Iterator.
182 The resulting `zip_iterator` models Readable Iterator.
184 The fact that the `zip_iterator` models only Readable Iterator does not
185 prevent you from modifying the values that the individual iterators point
186 to. The tuple returned by the `zip_iterator`'s `operator*` is a tuple
187 constructed from the reference types of the individual iterators, not
188 their value types. For example, if `zip_it` is a `zip_iterator` whose
189 first member iterator is an `std::vector<double>::iterator`, then the
190 following line will modify the value which the first member iterator of
191 `zip_it` currently points to:
193 zip_it->get<0>() = 42.0;
196 Consider the set of standard traversal concepts obtained by taking
197 the most refined standard traversal concept modeled by each individual
198 iterator type in the `IteratorTuple` argument.The `zip_iterator`
199 models the least refined standard traversal concept in this set.
201 `zip_iterator<IteratorTuple1>` is interoperable with
202 `zip_iterator<IteratorTuple2>` if and only if `IteratorTuple1`
203 is interoperable with `IteratorTuple2`.
207 In addition to the operations required by the concepts modeled by
208 `zip_iterator`, `zip_iterator` provides the following
213 [*Returns:] An instance of `zip_iterator` with `m_iterator_tuple`
217 zip_iterator(IteratorTuple iterator_tuple);
219 [*Returns:] An instance of `zip_iterator` with `m_iterator_tuple`
220 initialized to `iterator_tuple`.
223 template<typename OtherIteratorTuple>
225 const zip_iterator<OtherIteratorTuple>& other
226 , typename enable_if_convertible<
228 , IteratorTuple>::type* = 0 // exposition only
231 [*Returns:] An instance of `zip_iterator` that is a copy of `other`.[br]
232 [*Requires:] `OtherIteratorTuple` is implicitly convertible to `IteratorTuple`.
235 const IteratorTuple& get_iterator_tuple() const;
237 [*Returns:] `m_iterator_tuple`
240 reference operator*() const;
242 [*Returns:] A tuple consisting of the results of dereferencing all iterators in
246 zip_iterator& operator++();
248 [*Effects:] Increments each iterator in `m_iterator_tuple`.[br]
252 zip_iterator& operator--();
254 [*Effects:] Decrements each iterator in `m_iterator_tuple`.[br]
257 template<typename IteratorTuple>
258 zip_iterator<IteratorTuple>
259 make_zip_iterator(IteratorTuple t);
261 [*Returns:] An instance of `zip_iterator<IteratorTuple>` with `m_iterator_tuple`