1[section:indirect Indirect Iterator] 2 3`indirect_iterator` adapts an iterator by applying an 4*extra* dereference inside of `operator*()`. For example, this 5iterator adaptor makes it possible to view a container of pointers 6(e.g. `list<foo*>`) as if it were a container of the pointed-to type 7(e.g. `list<foo>`). `indirect_iterator` depends on two 8auxiliary traits, `pointee` and `indirect_reference`, to 9provide support for underlying iterators whose `value_type` is 10not an iterator. 11 12[h2 Example] 13 14This example prints an array of characters, using 15`indirect_iterator` to access the array of characters through an 16array of pointers. Next `indirect_iterator` is used with the 17`transform` algorithm to copy the characters (incremented by one) to 18another array. A constant indirect iterator is used for the source and 19a mutable indirect iterator is used for the destination. The last part 20of the example prints the original array of characters, but this time 21using the `make_indirect_iterator` helper function. 22 23 24 char characters[] = "abcdefg"; 25 const int N = sizeof(characters)/sizeof(char) - 1; // -1 since characters has a null char 26 char* pointers_to_chars[N]; // at the end. 27 for (int i = 0; i < N; ++i) 28 pointers_to_chars[i] = &characters[i]; 29 30 // Example of using indirect_iterator 31 32 boost::indirect_iterator<char**, char> 33 indirect_first(pointers_to_chars), indirect_last(pointers_to_chars + N); 34 35 std::copy(indirect_first, indirect_last, std::ostream_iterator<char>(std::cout, ",")); 36 std::cout << std::endl; 37 38 39 // Example of making mutable and constant indirect iterators 40 41 char mutable_characters[N]; 42 char* pointers_to_mutable_chars[N]; 43 for (int j = 0; j < N; ++j) 44 pointers_to_mutable_chars[j] = &mutable_characters[j]; 45 46 boost::indirect_iterator<char* const*> mutable_indirect_first(pointers_to_mutable_chars), 47 mutable_indirect_last(pointers_to_mutable_chars + N); 48 boost::indirect_iterator<char* const*, char const> const_indirect_first(pointers_to_chars), 49 const_indirect_last(pointers_to_chars + N); 50 51 std::transform(const_indirect_first, const_indirect_last, 52 mutable_indirect_first, std::bind(std::plus<char>(), 1, std::placeholders::_1)); 53 54 std::copy(mutable_indirect_first, mutable_indirect_last, 55 std::ostream_iterator<char>(std::cout, ",")); 56 std::cout << std::endl; 57 58 59 // Example of using make_indirect_iterator() 60 61 std::copy(boost::make_indirect_iterator(pointers_to_chars), 62 boost::make_indirect_iterator(pointers_to_chars + N), 63 std::ostream_iterator<char>(std::cout, ",")); 64 std::cout << std::endl; 65 66 67The output is: 68 69[pre 70a,b,c,d,e,f,g, 71b,c,d,e,f,g,h, 72a,b,c,d,e,f,g, 73] 74 75The source code for this example can be found 76[example_link indirect_iterator_example.cpp..here]. 77 78 79[h2 Reference] 80 81[h3 Synopsis] 82 83 template < 84 class Iterator 85 , class Value = use_default 86 , class CategoryOrTraversal = use_default 87 , class Reference = use_default 88 , class Difference = use_default 89 > 90 class indirect_iterator 91 { 92 public: 93 typedef /* see below */ value_type; 94 typedef /* see below */ reference; 95 typedef /* see below */ pointer; 96 typedef /* see below */ difference_type; 97 typedef /* see below */ iterator_category; 98 99 indirect_iterator(); 100 indirect_iterator(Iterator x); 101 102 template < 103 class Iterator2, class Value2, class Category2 104 , class Reference2, class Difference2 105 > 106 indirect_iterator( 107 indirect_iterator< 108 Iterator2, Value2, Category2, Reference2, Difference2 109 > const& y 110 , typename enable_if_convertible<Iterator2, Iterator>::type* = 0 // exposition 111 ); 112 113 Iterator const& base() const; 114 reference operator*() const; 115 indirect_iterator& operator++(); 116 indirect_iterator& operator--(); 117 private: 118 Iterator m_iterator; // exposition 119 }; 120 121 122The member types of `indirect_iterator` are defined according to 123the following pseudo-code, where `V` is 124`iterator_traits<Iterator>::value_type` 125 126[pre 127 if (Value is use_default) then 128 typedef remove_const<pointee<V>::type>::type value_type; 129 else 130 typedef remove_const<Value>::type value_type; 131 132 if (Reference is use_default) then 133 if (Value is use_default) then 134 typedef indirect_reference<V>::type reference; 135 else 136 typedef Value& reference; 137 else 138 typedef Reference reference; 139 140 if (Value is use_default) then 141 typedef pointee<V>::type\* pointer; 142 else 143 typedef Value\* pointer; 144 145 if (Difference is use_default) 146 typedef iterator_traits<Iterator>::difference_type difference_type; 147 else 148 typedef Difference difference_type; 149 150 if (CategoryOrTraversal is use_default) 151 typedef *iterator-category* ( 152 iterator_traversal<Iterator>::type,`reference`,`value_type` 153 ) iterator_category; 154 else 155 typedef *iterator-category* ( 156 CategoryOrTraversal,`reference`,`value_type` 157 ) iterator_category; 158] 159 160 161[h3 Requirements] 162 163The expression `*v`, where `v` is an object of 164`iterator_traits<Iterator>::value_type`, shall be valid 165expression and convertible to `reference`. `Iterator` shall 166model the traversal concept indicated by `iterator_category`. 167`Value`, `Reference`, and `Difference` shall be chosen so 168that `value_type`, `reference`, and `difference_type` meet 169the requirements indicated by `iterator_category`. 170 171[blurb Note: there are further requirements on the 172`iterator_traits<Iterator>::value_type` if the `Value` 173parameter is not `use_default`, as implied by the algorithm for 174deducing the default for the `value_type` member.] 175 176[h3 Concepts] 177 178In addition to the concepts indicated by `iterator_category` 179and by `iterator_traversal<indirect_iterator>::type`, a 180specialization of `indirect_iterator` models the following 181concepts, Where `v` is an object of 182`iterator_traits<Iterator>::value_type`: 183 184Readable Iterator if `reference(*v)` is convertible to 185`value_type`. 186 187Writable Iterator if `reference(*v) = t` is a valid 188expression (where `t` is an object of type 189`indirect_iterator::value_type`) 190 191Lvalue Iterator if `reference` is a reference type. 192 193`indirect_iterator<X,V1,C1,R1,D1>` is interoperable with 194`indirect_iterator<Y,V2,C2,R2,D2>` if and only if `X` is 195interoperable with `Y`. 196 197[h3 Operations] 198 199In addition to the operations required by the concepts described 200above, specializations of `indirect_iterator` provide the 201following operations: 202 203 204 indirect_iterator(); 205 206[*Requires: ] `Iterator` must be Default Constructible.[br] 207[*Effects: ] Constructs an instance of `indirect_iterator` with 208 a default-constructed `m_iterator`. 209 210 211 indirect_iterator(Iterator x); 212 213[*Effects: ] Constructs an instance of `indirect_iterator` with 214 `m_iterator` copy constructed from `x`. 215 216 217 template < 218 class Iterator2, class Value2, unsigned Access, class Traversal 219 , class Reference2, class Difference2 220 > 221 indirect_iterator( 222 indirect_iterator< 223 Iterator2, Value2, Access, Traversal, Reference2, Difference2 224 > const& y 225 , typename enable_if_convertible<Iterator2, Iterator>::type* = 0 // exposition 226 ); 227 228[*Requires: ] `Iterator2` is implicitly convertible to `Iterator`.[br] 229[*Effects: ] Constructs an instance of `indirect_iterator` whose 230 `m_iterator` subobject is constructed from `y.base()`. 231 232 233 Iterator const& base() const; 234 235[*Returns: ] `m_iterator` 236 237 238 reference operator*() const; 239 240[*Returns: ] `**m_iterator` 241 242 243 indirect_iterator& operator++(); 244 245[*Effects: ] `++m_iterator`[br] 246[*Returns: ] `*this` 247 248 249 indirect_iterator& operator--(); 250 251[*Effects: ] `--m_iterator`[br] 252[*Returns: ] `*this` 253 254[endsect] 255