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