• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1[section:zip Zip Iterator]
2
3The zip iterator provides the ability to parallel-iterate
4over several controlled sequences simultaneously. A zip
5iterator is constructed from a tuple of iterators. Moving
6the zip iterator moves all the iterators in parallel.
7Dereferencing the zip iterator returns a tuple that contains
8the results of dereferencing the individual iterators.
9
10The tuple of iterators is now implemented in terms of a Boost fusion sequence.
11Because of this the 'tuple' may be any Boost fusion sequence and, for backwards
12compatibility through a Boost fusion sequence adapter, a Boost tuple. Because the
13'tuple' may be any boost::fusion sequence the 'tuple' may also be any type for which a
14Boost fusion adapter exists. This includes, among others, a std::tuple and a std::pair.
15Just remember to include the appropriate Boost fusion adapter header files for these
16other Boost fusion adapters. The zip_iterator header file already includes the
17Boost fusion adapter header file for Boost tuple, so you need not include it yourself
18to use a Boost tuple as your 'tuple'.
19
20[section:zip_example Example]
21
22There are two main types of applications of the `zip_iterator`. The first
23one concerns runtime efficiency: If one has several controlled sequences
24of the same length that must be somehow processed, e.g., with the
25`for_each` algorithm, then it is more efficient to perform just
26one parallel-iteration rather than several individual iterations. For an
27example, assume that `vect_of_doubles` and `vect_of_ints`
28are two vectors of equal length containing doubles and ints, respectively,
29and consider the following two iterations:
30
31    std::vector<double>::const_iterator beg1 = vect_of_doubles.begin();
32    std::vector<double>::const_iterator end1 = vect_of_doubles.end();
33    std::vector<int>::const_iterator beg2 = vect_of_ints.begin();
34    std::vector<int>::const_iterator end2 = vect_of_ints.end();
35
36    std::for_each(beg1, end1, func_0());
37    std::for_each(beg2, end2, func_1());
38
39These two iterations can now be replaced with a single one as follows:
40
41
42    std::for_each(
43      boost::make_zip_iterator(
44        boost::make_tuple(beg1, beg2)
45        ),
46      boost::make_zip_iterator(
47        boost::make_tuple(end1, end2)
48        ),
49      zip_func()
50      );
51
52A non-generic implementation of `zip_func` could look as follows:
53
54
55      struct zip_func :
56        public std::unary_function<const boost::tuple<const double&, const int&>&, void>
57      {
58        void operator()(const boost::tuple<const double&, const int&>& t) const
59        {
60          m_f0(t.get<0>());
61          m_f1(t.get<1>());
62        }
63
64      private:
65        func_0 m_f0;
66        func_1 m_f1;
67      };
68
69The second important application of the `zip_iterator` is as a building block
70to make combining iterators. A combining iterator is an iterator
71that parallel-iterates over several controlled sequences and, upon
72dereferencing, returns the result of applying a functor to the values of the
73sequences at the respective positions. This can now be achieved by using the
74`zip_iterator` in conjunction with the `transform_iterator`.
75
76Suppose, for example, that you have two vectors of doubles, say
77`vect_1` and `vect_2`, and you need to expose to a client
78a controlled sequence containing the products of the elements of
79`vect_1` and `vect_2`. Rather than placing these products
80in a third vector, you can use a combining iterator that calculates the
81products on the fly. Let us assume that `tuple_multiplies` is a
82functor that works like `std::multiplies`, except that it takes
83its two arguments packaged in a tuple. Then the two iterators
84`it_begin` and `it_end` defined below delimit a controlled
85sequence containing the products of the elements of `vect_1` and
86`vect_2`:
87
88    typedef boost::tuple<
89      std::vector<double>::const_iterator,
90      std::vector<double>::const_iterator
91      > the_iterator_tuple;
92
93    typedef boost::zip_iterator<
94      the_iterator_tuple
95      > the_zip_iterator;
96
97    typedef boost::transform_iterator<
98      tuple_multiplies<double>,
99      the_zip_iterator
100      > the_transform_iterator;
101
102    the_transform_iterator it_begin(
103      the_zip_iterator(
104        the_iterator_tuple(
105          vect_1.begin(),
106          vect_2.begin()
107          )
108        ),
109      tuple_multiplies<double>()
110      );
111
112    the_transform_iterator it_end(
113      the_zip_iterator(
114        the_iterator_tuple(
115          vect_1.end(),
116          vect_2.end()
117          )
118        ),
119      tuple_multiplies<double>()
120      );
121
122[endsect]
123
124[section:zip_reference Reference]
125
126[h2 Synopsis]
127
128  template<typename IteratorTuple>
129  class zip_iterator
130  {
131
132  public:
133    typedef /* see below */ reference;
134    typedef reference value_type;
135    typedef value_type* pointer;
136    typedef /* see below */ difference_type;
137    typedef /* see below */ iterator_category;
138
139    zip_iterator();
140    zip_iterator(IteratorTuple iterator_tuple);
141
142    template<typename OtherIteratorTuple>
143    zip_iterator(
144          const zip_iterator<OtherIteratorTuple>& other
145        , typename enable_if_convertible<
146                OtherIteratorTuple
147              , IteratorTuple>::type* = 0     // exposition only
148    );
149
150    const IteratorTuple& get_iterator_tuple() const;
151
152  private:
153    IteratorTuple m_iterator_tuple;     // exposition only
154  };
155
156  template<typename IteratorTuple>
157  zip_iterator<IteratorTuple>
158  make_zip_iterator(IteratorTuple t);
159
160The `reference` member of `zip_iterator` is the type of the tuple
161made of the reference types of the iterator types in the `IteratorTuple`
162argument.
163
164The `difference_type` member of `zip_iterator` is the `difference_type`
165of the first of the iterator types in the `IteratorTuple` argument.
166
167The `iterator_category` member of `zip_iterator` is convertible to the
168minimum of the traversal categories of the iterator types in the `IteratorTuple`
169argument. For example, if the `zip_iterator` holds only vector
170iterators, then `iterator_category` is convertible to
171`boost::random_access_traversal_tag`. If you add a list iterator, then
172`iterator_category` will be convertible to `boost::bidirectional_traversal_tag`,
173but no longer to `boost::random_access_traversal_tag`.
174
175[h2 Requirements]
176
177All iterator types in the argument `IteratorTuple` shall model Readable Iterator.
178
179[h2 Concepts]
180
181The resulting `zip_iterator` models Readable Iterator.
182
183The fact that the `zip_iterator` models only Readable Iterator does not
184prevent you from modifying the values that the individual iterators point
185to. The tuple returned by the `zip_iterator`'s `operator*` is a tuple
186constructed from the reference types of the individual iterators, not
187their value types. For example, if `zip_it` is a `zip_iterator` whose
188first member iterator is an `std::vector<double>::iterator`, then the
189following line will modify the value which the first member iterator of
190`zip_it` currently points to:
191
192    zip_it->get<0>() = 42.0;
193
194
195Consider the set of standard traversal concepts obtained by taking
196the most refined standard traversal concept modeled by each individual
197iterator type in the `IteratorTuple` argument.The `zip_iterator`
198models the least refined standard traversal concept in this set.
199
200`zip_iterator<IteratorTuple1>` is interoperable with
201`zip_iterator<IteratorTuple2>` if and only if `IteratorTuple1`
202is interoperable with `IteratorTuple2`.
203
204[h2 Operations]
205
206In addition to the operations required by the concepts modeled by
207`zip_iterator`, `zip_iterator` provides the following
208operations.
209
210  zip_iterator();
211
212[*Returns:] An instance of `zip_iterator` with `m_iterator_tuple`
213  default constructed.
214
215
216  zip_iterator(IteratorTuple iterator_tuple);
217
218[*Returns:] An instance of `zip_iterator` with `m_iterator_tuple`
219  initialized to `iterator_tuple`.
220
221
222    template<typename OtherIteratorTuple>
223    zip_iterator(
224          const zip_iterator<OtherIteratorTuple>& other
225        , typename enable_if_convertible<
226                OtherIteratorTuple
227              , IteratorTuple>::type* = 0     // exposition only
228    );
229
230[*Returns:] An instance of `zip_iterator` that is a copy of `other`.[br]
231[*Requires:] `OtherIteratorTuple` is implicitly convertible to `IteratorTuple`.
232
233
234  const IteratorTuple& get_iterator_tuple() const;
235
236[*Returns:] `m_iterator_tuple`
237
238
239  reference operator*() const;
240
241[*Returns:] A tuple consisting of the results of dereferencing all iterators in
242  `m_iterator_tuple`.
243
244
245  zip_iterator& operator++();
246
247[*Effects:] Increments each iterator in `m_iterator_tuple`.[br]
248[*Returns:] `*this`
249
250
251  zip_iterator& operator--();
252
253[*Effects:] Decrements each iterator in `m_iterator_tuple`.[br]
254[*Returns:] `*this`
255
256    template<typename IteratorTuple>
257    zip_iterator<IteratorTuple>
258    make_zip_iterator(IteratorTuple t);
259
260[*Returns:] An instance of `zip_iterator<IteratorTuple>` with `m_iterator_tuple`
261  initialized to `t`.
262
263[endsect]
264
265[endsect]
266