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