]>
Commit | Line | Data |
---|---|---|
1 | ||
2 | [section:indirect Indirect Iterator] | |
3 | ||
4 | `indirect_iterator` adapts an iterator by applying an | |
5 | *extra* dereference inside of `operator*()`. For example, this | |
6 | iterator adaptor makes it possible to view a container of pointers | |
7 | (e.g. `list<foo*>`) as if it were a container of the pointed-to type | |
8 | (e.g. `list<foo>`). `indirect_iterator` depends on two | |
9 | auxiliary traits, `pointee` and `indirect_reference`, to | |
10 | provide support for underlying iterators whose `value_type` is | |
11 | not an iterator. | |
12 | ||
13 | [h2 Example] | |
14 | ||
15 | This example prints an array of characters, using | |
16 | `indirect_iterator` to access the array of characters through an | |
17 | array of pointers. Next `indirect_iterator` is used with the | |
18 | `transform` algorithm to copy the characters (incremented by one) to | |
19 | another array. A constant indirect iterator is used for the source and | |
20 | a mutable indirect iterator is used for the destination. The last part | |
21 | of the example prints the original array of characters, but this time | |
22 | using the `make_indirect_iterator` helper function. | |
23 | ||
24 | ||
25 | char characters[] = "abcdefg"; | |
26 | const int N = sizeof(characters)/sizeof(char) - 1; // -1 since characters has a null char | |
27 | char* pointers_to_chars[N]; // at the end. | |
28 | for (int i = 0; i < N; ++i) | |
29 | pointers_to_chars[i] = &characters[i]; | |
30 | ||
31 | // Example of using indirect_iterator | |
32 | ||
33 | boost::indirect_iterator<char**, char> | |
34 | indirect_first(pointers_to_chars), indirect_last(pointers_to_chars + N); | |
35 | ||
36 | std::copy(indirect_first, indirect_last, std::ostream_iterator<char>(std::cout, ",")); | |
37 | std::cout << std::endl; | |
38 | ||
39 | ||
40 | // Example of making mutable and constant indirect iterators | |
41 | ||
42 | char mutable_characters[N]; | |
43 | char* pointers_to_mutable_chars[N]; | |
44 | for (int j = 0; j < N; ++j) | |
45 | pointers_to_mutable_chars[j] = &mutable_characters[j]; | |
46 | ||
47 | boost::indirect_iterator<char* const*> mutable_indirect_first(pointers_to_mutable_chars), | |
48 | mutable_indirect_last(pointers_to_mutable_chars + N); | |
49 | boost::indirect_iterator<char* const*, char const> const_indirect_first(pointers_to_chars), | |
50 | const_indirect_last(pointers_to_chars + N); | |
51 | ||
52 | std::transform(const_indirect_first, const_indirect_last, | |
53 | mutable_indirect_first, std::bind1st(std::plus<char>(), 1)); | |
54 | ||
55 | std::copy(mutable_indirect_first, mutable_indirect_last, | |
56 | std::ostream_iterator<char>(std::cout, ",")); | |
57 | std::cout << std::endl; | |
58 | ||
59 | ||
60 | // Example of using make_indirect_iterator() | |
61 | ||
62 | std::copy(boost::make_indirect_iterator(pointers_to_chars), | |
63 | boost::make_indirect_iterator(pointers_to_chars + N), | |
64 | std::ostream_iterator<char>(std::cout, ",")); | |
65 | std::cout << std::endl; | |
66 | ||
67 | ||
68 | The output is: | |
69 | ||
70 | a,b,c,d,e,f,g, | |
71 | b,c,d,e,f,g,h, | |
72 | a,b,c,d,e,f,g, | |
73 | ||
74 | ||
75 | The source code for this example can be found | |
76 | [@../example/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 | ||
122 | The member types of `indirect_iterator` are defined according to | |
123 | the 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 | ||
163 | The expression `*v`, where `v` is an object of | |
164 | `iterator_traits<Iterator>::value_type`, shall be valid | |
165 | expression and convertible to `reference`. `Iterator` shall | |
166 | model the traversal concept indicated by `iterator_category`. | |
167 | `Value`, `Reference`, and `Difference` shall be chosen so | |
168 | that `value_type`, `reference`, and `difference_type` meet | |
169 | the requirements indicated by `iterator_category`. | |
170 | ||
171 | [blurb Note: there are further requirements on the | |
172 | `iterator_traits<Iterator>::value_type` if the `Value` | |
173 | parameter is not `use_default`, as implied by the algorithm for | |
174 | deducing the default for the `value_type` member.] | |
175 | ||
176 | [h3 Concepts] | |
177 | ||
178 | In addition to the concepts indicated by `iterator_category` | |
179 | and by `iterator_traversal<indirect_iterator>::type`, a | |
180 | specialization of `indirect_iterator` models the following | |
181 | concepts, Where `v` is an object of | |
182 | `iterator_traits<Iterator>::value_type`: | |
183 | ||
184 | Readable Iterator if `reference(*v)` is convertible to | |
185 | `value_type`. | |
186 | ||
187 | Writable Iterator if `reference(*v) = t` is a valid | |
188 | expression (where `t` is an object of type | |
189 | `indirect_iterator::value_type`) | |
190 | ||
191 | Lvalue 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 | |
195 | interoperable with `Y`. | |
196 | ||
197 | [h3 Operations] | |
198 | ||
199 | In addition to the operations required by the concepts described | |
200 | above, specializations of `indirect_iterator` provide the | |
201 | following 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] |