]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/iterator/doc/quickbook/adaptor.qbk
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / iterator / doc / quickbook / adaptor.qbk
1
2 [section:adaptor Iterator Adaptor]
3
4 The `iterator_adaptor` class template adapts some `Base` [#base]_
5 type to create a new iterator. Instantiations of `iterator_adaptor`
6 are derived from a corresponding instantiation of `iterator_facade`
7 and implement the core behaviors in terms of the `Base` type. In
8 essence, `iterator_adaptor` merely forwards all operations to an
9 instance of the `Base` type, which it stores as a member.
10
11 .. [#base] The term "Base" here does not refer to a base class and is
12 not meant to imply the use of derivation. We have followed the lead
13 of the standard library, which provides a base() function to access
14 the underlying iterator object of a `reverse_iterator` adaptor.
15
16 The user of `iterator_adaptor` creates a class derived from an
17 instantiation of `iterator_adaptor` and then selectively
18 redefines some of the core member functions described in the
19 `iterator_facade` core requirements table. The `Base` type need
20 not meet the full requirements for an iterator; it need only
21 support the operations used by the core interface functions of
22 `iterator_adaptor` that have not been redefined in the user's
23 derived class.
24
25 Several of the template parameters of `iterator_adaptor` default
26 to `use_default`. This allows the
27 user to make use of a default parameter even when she wants to
28 specify a parameter later in the parameter list. Also, the
29 defaults for the corresponding associated types are somewhat
30 complicated, so metaprogramming is required to compute them, and
31 `use_default` can help to simplify the implementation. Finally,
32 the identity of the `use_default` type is not left unspecified
33 because specification helps to highlight that the `Reference`
34 template parameter may not always be identical to the iterator's
35 `reference` type, and will keep users from making mistakes based on
36 that assumption.
37
38 [section:adaptor_reference Reference]
39
40 [h2 Synopsis]
41
42 template <
43 class Derived
44 , class Base
45 , class Value = use_default
46 , class CategoryOrTraversal = use_default
47 , class Reference = use_default
48 , class Difference = use_default
49 >
50 class iterator_adaptor
51 : public iterator_facade<Derived, *V'*, *C'*, *R'*, *D'*> // see details
52 {
53 friend class iterator_core_access;
54 public:
55 iterator_adaptor();
56 explicit iterator_adaptor(Base const& iter);
57 typedef Base base_type;
58 Base const& base() const;
59 protected:
60 typedef iterator_adaptor iterator_adaptor\_;
61 Base const& base_reference() const;
62 Base& base_reference();
63 private: // Core iterator interface for iterator_facade.
64 typename iterator_adaptor::reference dereference() const;
65
66 template <
67 class OtherDerived, class OtherIterator, class V, class C, class R, class D
68 >
69 bool equal(iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D> const& x) const;
70
71 void advance(typename iterator_adaptor::difference_type n);
72 void increment();
73 void decrement();
74
75 template <
76 class OtherDerived, class OtherIterator, class V, class C, class R, class D
77 >
78 typename iterator_adaptor::difference_type distance_to(
79 iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D> const& y) const;
80
81 private:
82 Base m_iterator; // exposition only
83 };
84
85 __ base_parameters_
86
87 .. _requirements:
88
89 [h2 Requirements]
90
91 `static_cast<Derived*>(iterator_adaptor*)` shall be well-formed.
92 The `Base` argument shall be Assignable and Copy Constructible.
93
94
95 .. _base_parameters:
96
97 [h2 Base Class Parameters]
98
99 The *V'*, *C'*, *R'*, and *D'* parameters of the `iterator_facade`
100 used as a base class in the summary of `iterator_adaptor`
101 above are defined as follows:
102
103 [pre
104 *V'* = if (Value is use_default)
105 return iterator_traits<Base>::value_type
106 else
107 return Value
108
109 *C'* = if (CategoryOrTraversal is use_default)
110 return iterator_traversal<Base>::type
111 else
112 return CategoryOrTraversal
113
114 *R'* = if (Reference is use_default)
115 if (Value is use_default)
116 return iterator_traits<Base>::reference
117 else
118 return Value&
119 else
120 return Reference
121
122 *D'* = if (Difference is use_default)
123 return iterator_traits<Base>::difference_type
124 else
125 return Difference
126 ]
127
128 [h2 Operations]
129
130 [h3 Public]
131
132
133 iterator_adaptor();
134
135 [*Requires:] The `Base` type must be Default Constructible.[br]
136 [*Returns:] An instance of `iterator_adaptor` with
137 `m_iterator` default constructed.
138
139
140 explicit iterator_adaptor(Base const& iter);
141
142 [*Returns:] An instance of `iterator_adaptor` with
143 `m_iterator` copy constructed from `iter`.
144
145 Base const& base() const;
146
147 [*Returns:] `m_iterator`
148
149
150 [h3 Protected]
151
152 Base const& base_reference() const;
153
154 [*Returns:] A const reference to `m_iterator`.
155
156
157 Base& base_reference();
158
159 [*Returns:] A non-const reference to `m_iterator`.
160
161 [h3 Private]
162
163 typename iterator_adaptor::reference dereference() const;
164
165 [*Returns:] `*m_iterator`
166
167
168 template <
169 class OtherDerived, class OtherIterator, class V, class C, class R, class D
170 >
171 bool equal(iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D> const& x) const;
172
173 [*Returns:] `m_iterator == x.base()`
174
175
176 void advance(typename iterator_adaptor::difference_type n);
177
178 [*Effects:] `m_iterator += n;`
179
180 void increment();
181
182 [*Effects:] `++m_iterator;`
183
184 void decrement();
185
186 [*Effects:] `--m_iterator;`
187
188
189 template <
190 class OtherDerived, class OtherIterator, class V, class C, class R, class D
191 >
192 typename iterator_adaptor::difference_type distance_to(
193 iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D> const& y) const;
194
195 [*Returns:] `y.base() - m_iterator`
196
197 [endsect]
198
199 [section:adaptor_tutorial Tutorial]
200
201 In this section we'll further refine the `node_iter` class
202 template we developed in the |fac_tut|_. If you haven't already
203 read that material, you should go back now and check it out because
204 we're going to pick up right where it left off.
205
206 .. |fac_tut| replace:: `iterator_facade` tutorial
207 .. _fac_tut: iterator_facade.html#tutorial-example
208
209 [blurb [*`node_base*` really *is* an iterator][br][br]
210 It's not really a very interesting iterator, since `node_base`
211 is an abstract class: a pointer to a `node_base` just points
212 at some base subobject of an instance of some other class, and
213 incrementing a `node_base*` moves it past this base subobject
214 to who-knows-where? The most we can do with that incremented
215 position is to compare another `node_base*` to it. In other
216 words, the original iterator traverses a one-element array.
217 ]
218
219 You probably didn't think of it this way, but the `node_base*`
220 object that underlies `node_iterator` is itself an iterator,
221 just like all other pointers. If we examine that pointer closely
222 from an iterator perspective, we can see that it has much in common
223 with the `node_iterator` we're building. First, they share most
224 of the same associated types (`value_type`, `reference`,
225 `pointer`, and `difference_type`). Second, even some of the
226 core functionality is the same: `operator*` and `operator==` on
227 the `node_iterator` return the result of invoking the same
228 operations on the underlying pointer, via the `node_iterator`\ 's
229 |dereference_and_equal|_). The only real behavioral difference
230 between `node_base*` and `node_iterator` can be observed when
231 they are incremented: `node_iterator` follows the
232 `m_next` pointer, while `node_base*` just applies an address offset.
233
234 .. |dereference_and_equal| replace:: `dereference` and `equal` member functions
235 .. _dereference_and_equal: iterator_facade.html#implementing-the-core-operations
236
237 It turns out that the pattern of building an iterator on another
238 iterator-like type (the `Base` [#base]_ type) while modifying
239 just a few aspects of the underlying type's behavior is an
240 extremely common one, and it's the pattern addressed by
241 `iterator_adaptor`. Using `iterator_adaptor` is very much like
242 using `iterator_facade`, but because iterator_adaptor tries to
243 mimic as much of the `Base` type's behavior as possible, we
244 neither have to supply a `Value` argument, nor implement any core
245 behaviors other than `increment`. The implementation of
246 `node_iter` is thus reduced to:
247
248 template <class Value>
249 class node_iter
250 : public boost::iterator_adaptor<
251 node_iter<Value> // Derived
252 , Value* // Base
253 , boost::use_default // Value
254 , boost::forward_traversal_tag // CategoryOrTraversal
255 >
256 {
257 private:
258 struct enabler {}; // a private type avoids misuse
259
260 public:
261 node_iter()
262 : node_iter::iterator_adaptor_(0) {}
263
264 explicit node_iter(Value* p)
265 : node_iter::iterator_adaptor_(p) {}
266
267 template <class OtherValue>
268 node_iter(
269 node_iter<OtherValue> const& other
270 , typename boost::enable_if<
271 boost::is_convertible<OtherValue*,Value*>
272 , enabler
273 >::type = enabler()
274 )
275 : node_iter::iterator_adaptor_(other.base()) {}
276
277 private:
278 friend class boost::iterator_core_access;
279 void increment() { this->base_reference() = this->base()->next(); }
280 };
281
282 Note the use of `node_iter::iterator_adaptor_` here: because
283 `iterator_adaptor` defines a nested `iterator_adaptor_` type
284 that refers to itself, that gives us a convenient way to refer to
285 the complicated base class type of `node_iter<Value>`. [Note:
286 this technique is known not to work with Borland C++ 5.6.4 and
287 Metrowerks CodeWarrior versions prior to 9.0]
288
289 You can see an example program that exercises this version of the
290 node iterators
291 [@../example/node_iterator3.cpp `here`].
292
293
294 In the case of `node_iter`, it's not very compelling to pass
295 `boost::use_default` as `iterator_adaptor` 's `Value`
296 argument; we could have just passed `node_iter` 's `Value`
297 along to `iterator_adaptor`, and that'd even be shorter! Most
298 iterator class templates built with `iterator_adaptor` are
299 parameterized on another iterator type, rather than on its
300 `value_type`. For example, `boost::reverse_iterator` takes an
301 iterator type argument and reverses its direction of traversal,
302 since the original iterator and the reversed one have all the same
303 associated types, `iterator_adaptor` 's delegation of default
304 types to its `Base` saves the implementor of
305 `boost::reverse_iterator` from writing:
306
307 std::iterator_traits<Iterator>::*some-associated-type*
308
309 at least four times.
310
311 We urge you to review the documentation and implementations of
312 |reverse_iterator|_ and the other Boost `specialized iterator
313 adaptors`__ to get an idea of the sorts of things you can do with
314 `iterator_adaptor`. In particular, have a look at
315 |transform_iterator|_, which is perhaps the most straightforward
316 adaptor, and also |counting_iterator|_, which demonstrates that
317 `iterator_adaptor`\ 's `Base` type needn't be an iterator.
318
319 .. |reverse_iterator| replace:: `reverse_iterator`
320 .. _reverse_iterator: reverse_iterator.html
321
322 .. |counting_iterator| replace:: `counting_iterator`
323 .. _counting_iterator: counting_iterator.html
324
325 .. |transform_iterator| replace:: `transform_iterator`
326 .. _transform_iterator: transform_iterator.html
327
328 __ index.html#specialized-adaptors
329
330
331 [endsect]
332
333 [endsect]