• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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