File: zip_iterator.qbk

package info (click to toggle)
boost1.35 1.35.0-5
  • links: PTS
  • area: main
  • in suites: lenny
  • size: 203,856 kB
  • ctags: 337,867
  • sloc: cpp: 938,683; xml: 56,847; ansic: 41,589; python: 18,999; sh: 11,566; makefile: 664; perl: 494; yacc: 456; asm: 353; csh: 6
file content (256 lines) | stat: -rw-r--r-- 8,168 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256

[section:zip Zip Iterator]

The zip iterator provides the ability to parallel-iterate
over several controlled sequences simultaneously. A zip 
iterator is constructed from a tuple of iterators. Moving
the zip iterator moves all the iterators in parallel.
Dereferencing the zip iterator returns a tuple that contains
the results of dereferencing the individual iterators. 

[section:zip_example Example]

There are two main types of applications of the `zip_iterator`. The first
one concerns runtime efficiency: If one has several controlled sequences
of the same length that must be somehow processed, e.g., with the 
`for_each` algorithm, then it is more efficient to perform just
one parallel-iteration rather than several individual iterations. For an 
example, assume that `vect_of_doubles` and `vect_of_ints`
are two vectors of equal length containing doubles and ints, respectively,
and consider the following two iterations:

    std::vector<double>::const_iterator beg1 = vect_of_doubles.begin();
    std::vector<double>::const_iterator end1 = vect_of_doubles.end();
    std::vector<int>::const_iterator beg2 = vect_of_ints.begin();
    std::vector<int>::const_iterator end2 = vect_of_ints.end();

    std::for_each(beg1, end1, func_0());
    std::for_each(beg2, end2, func_1());

These two iterations can now be replaced with a single one as follows:


    std::for_each(
      boost::make_zip_iterator(
        boost::make_tuple(beg1, beg2)
        ),
      boost::make_zip_iterator(
        boost::make_tuple(end1, end2)
        ),
      zip_func()
      );

A non-generic implementation of `zip_func` could look as follows:


      struct zip_func : 
        public std::unary_function<const boost::tuple<const double&, const int&>&, void>
      {
        void operator()(const boost::tuple<const double&, const int&>& t) const
        {
          m_f0(t.get<0>());
          m_f1(t.get<1>());
        }

      private:
        func_0 m_f0;
        func_1 m_f1;
      };

The second important application of the `zip_iterator` is as a building block
to make combining iterators. A combining iterator is an iterator
that parallel-iterates over several controlled sequences and, upon
dereferencing, returns the result of applying a functor to the values of the
sequences at the respective positions. This can now be achieved by using the
`zip_iterator` in conjunction with the `transform_iterator`. 

Suppose, for example, that you have two vectors of doubles, say 
`vect_1` and `vect_2`, and you need to expose to a client
a controlled sequence containing the products of the elements of 
`vect_1` and `vect_2`. Rather than placing these products
in a third vector, you can use a combining iterator that calculates the
products on the fly. Let us assume that `tuple_multiplies` is a
functor that works like `std::multiplies`, except that it takes
its two arguments packaged in a tuple. Then the two iterators 
`it_begin` and `it_end` defined below delimit a controlled
sequence containing the products of the elements of `vect_1` and
`vect_2`:

    typedef boost::tuple<
      std::vector<double>::const_iterator,
      std::vector<double>::const_iterator
      > the_iterator_tuple;

    typedef boost::zip_iterator<
      the_iterator_tuple
      > the_zip_iterator;

    typedef boost::transform_iterator<
      tuple_multiplies<double>,
      the_zip_iterator
      > the_transform_iterator;

    the_transform_iterator it_begin(
      the_zip_iterator(
        the_iterator_tuple(
          vect_1.begin(),
          vect_2.begin()
          )
        ),
      tuple_multiplies<double>()
      );

    the_transform_iterator it_end(
      the_zip_iterator(
        the_iterator_tuple(
          vect_1.end(),
          vect_2.end()
          )
        ),
      tuple_multiplies<double>()
      );

[endsect]

[section:zip_reference Reference]

[h2 Synopsis]

  template<typename IteratorTuple>
  class zip_iterator
  {  

  public:
    typedef /* see below */ reference;
    typedef reference value_type;
    typedef value_type* pointer;
    typedef /* see below */ difference_type;
    typedef /* see below */ iterator_category;

    zip_iterator();
    zip_iterator(IteratorTuple iterator_tuple);

    template<typename OtherIteratorTuple>
    zip_iterator(
          const zip_iterator<OtherIteratorTuple>& other
        , typename enable_if_convertible<
                OtherIteratorTuple
              , IteratorTuple>::type* = 0     // exposition only
    );

    const IteratorTuple& get_iterator_tuple() const;

  private:
    IteratorTuple m_iterator_tuple;     // exposition only
  };

  template<typename IteratorTuple> 
  zip_iterator<IteratorTuple> 
  make_zip_iterator(IteratorTuple t);

The `reference` member of `zip_iterator` is the type of the tuple
made of the reference types of the iterator types in the `IteratorTuple`
argument.

The `difference_type` member of `zip_iterator` is the `difference_type`
of the first of the iterator types in the `IteratorTuple` argument.

The `iterator_category` member of `zip_iterator` is convertible to the
minimum of the traversal categories of the iterator types in the `IteratorTuple`
argument. For example, if the `zip_iterator` holds only vector
iterators, then `iterator_category` is convertible to 
`boost::random_access_traversal_tag`. If you add a list iterator, then
`iterator_category` will be convertible to `boost::bidirectional_traversal_tag`,
but no longer to `boost::random_access_traversal_tag`.

[h2 Requirements]

All iterator types in the argument `IteratorTuple` shall model Readable Iterator.  

[h2 Concepts]

The resulting `zip_iterator` models Readable Iterator.

The fact that the `zip_iterator` models only Readable Iterator does not 
prevent you from modifying the values that the individual iterators point
to. The tuple returned by the `zip_iterator`'s `operator*` is a tuple 
constructed from the reference types of the individual iterators, not 
their value types. For example, if `zip_it` is a `zip_iterator` whose
first member iterator is an `std::vector<double>::iterator`, then the
following line will modify the value which the first member iterator of
`zip_it` currently points to:

    zip_it->get<0>() = 42.0;


Consider the set of standard traversal concepts obtained by taking
the most refined standard traversal concept modeled by each individual
iterator type in the `IteratorTuple` argument.The `zip_iterator` 
models the least refined standard traversal concept in this set.

`zip_iterator<IteratorTuple1>` is interoperable with
`zip_iterator<IteratorTuple2>` if and only if `IteratorTuple1`
is interoperable with `IteratorTuple2`.

[h2 Operations]

In addition to the operations required by the concepts modeled by
`zip_iterator`, `zip_iterator` provides the following
operations.

  zip_iterator();

[*Returns:] An instance of `zip_iterator` with `m_iterator_tuple`
  default constructed.


  zip_iterator(IteratorTuple iterator_tuple);

[*Returns:] An instance of `zip_iterator` with `m_iterator_tuple`
  initialized to `iterator_tuple`.


    template<typename OtherIteratorTuple>
    zip_iterator(
          const zip_iterator<OtherIteratorTuple>& other
        , typename enable_if_convertible<
                OtherIteratorTuple
              , IteratorTuple>::type* = 0     // exposition only
    );

[*Returns:] An instance of `zip_iterator` that is a copy of `other`.\n
[*Requires:] `OtherIteratorTuple` is implicitly convertible to `IteratorTuple`.


  const IteratorTuple& get_iterator_tuple() const;

[*Returns:] `m_iterator_tuple`


  reference operator*() const;

[*Returns:] A tuple consisting of the results of dereferencing all iterators in
  `m_iterator_tuple`.


  zip_iterator& operator++();

[*Effects:] Increments each iterator in `m_iterator_tuple`.\n
[*Returns:] `*this`


  zip_iterator& operator--();

[*Effects:] Decrements each iterator in `m_iterator_tuple`.\n
[*Returns:] `*this`

    template<typename IteratorTuple> 
    zip_iterator<IteratorTuple> 
    make_zip_iterator(IteratorTuple t);

[*Returns:] An instance of `zip_iterator<IteratorTuple>` with `m_iterator_tuple`
  initialized to `t`.

[endsect]

[endsect]