2 [section:adaptor Iterator Adaptor]
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.
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.
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
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
38 [section:adaptor_reference Reference]
45 , class Value = use_default
46 , class CategoryOrTraversal = use_default
47 , class Reference = use_default
48 , class Difference = use_default
50 class iterator_adaptor
51 : public iterator_facade<Derived, *V'*, *C'*, *R'*, *D'*> // see details
53 friend class iterator_core_access;
56 explicit iterator_adaptor(Base const& iter);
57 typedef Base base_type;
58 Base const& base() const;
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;
67 class OtherDerived, class OtherIterator, class V, class C, class R, class D
69 bool equal(iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D> const& x) const;
71 void advance(typename iterator_adaptor::difference_type n);
76 class OtherDerived, class OtherIterator, class V, class C, class R, class D
78 typename iterator_adaptor::difference_type distance_to(
79 iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D> const& y) const;
82 Base m_iterator; // exposition only
91 `static_cast<Derived*>(iterator_adaptor*)` shall be well-formed.
92 The `Base` argument shall be Assignable and Copy Constructible.
97 [h2 Base Class Parameters]
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:
104 *V'* = if (Value is use_default)
105 return iterator_traits<Base>::value_type
109 *C'* = if (CategoryOrTraversal is use_default)
110 return iterator_traversal<Base>::type
112 return CategoryOrTraversal
114 *R'* = if (Reference is use_default)
115 if (Value is use_default)
116 return iterator_traits<Base>::reference
122 *D'* = if (Difference is use_default)
123 return iterator_traits<Base>::difference_type
135 [*Requires:] The `Base` type must be Default Constructible.[br]
136 [*Returns:] An instance of `iterator_adaptor` with
137 `m_iterator` default constructed.
140 explicit iterator_adaptor(Base const& iter);
142 [*Returns:] An instance of `iterator_adaptor` with
143 `m_iterator` copy constructed from `iter`.
145 Base const& base() const;
147 [*Returns:] `m_iterator`
152 Base const& base_reference() const;
154 [*Returns:] A const reference to `m_iterator`.
157 Base& base_reference();
159 [*Returns:] A non-const reference to `m_iterator`.
163 typename iterator_adaptor::reference dereference() const;
165 [*Returns:] `*m_iterator`
169 class OtherDerived, class OtherIterator, class V, class C, class R, class D
171 bool equal(iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D> const& x) const;
173 [*Returns:] `m_iterator == x.base()`
176 void advance(typename iterator_adaptor::difference_type n);
178 [*Effects:] `m_iterator += n;`
182 [*Effects:] `++m_iterator;`
186 [*Effects:] `--m_iterator;`
190 class OtherDerived, class OtherIterator, class V, class C, class R, class D
192 typename iterator_adaptor::difference_type distance_to(
193 iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D> const& y) const;
195 [*Returns:] `y.base() - m_iterator`
199 [section:adaptor_tutorial Tutorial]
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.
206 .. |fac_tut| replace:: `iterator_facade` tutorial
207 .. _fac_tut: iterator_facade.html#tutorial-example
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.
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.
234 .. |dereference_and_equal| replace:: `dereference` and `equal` member functions
235 .. _dereference_and_equal: iterator_facade.html#implementing-the-core-operations
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:
248 template <class Value>
250 : public boost::iterator_adaptor<
251 node_iter<Value> // Derived
253 , boost::use_default // Value
254 , boost::forward_traversal_tag // CategoryOrTraversal
258 struct enabler {}; // a private type avoids misuse
262 : node_iter::iterator_adaptor_(0) {}
264 explicit node_iter(Value* p)
265 : node_iter::iterator_adaptor_(p) {}
267 template <class OtherValue>
269 node_iter<OtherValue> const& other
270 , typename boost::enable_if<
271 boost::is_convertible<OtherValue*,Value*>
275 : node_iter::iterator_adaptor_(other.base()) {}
278 friend class boost::iterator_core_access;
279 void increment() { this->base_reference() = this->base()->next(); }
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]
289 You can see an example program that exercises this version of the
291 [@../example/node_iterator3.cpp `here`].
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:
307 std::iterator_traits<Iterator>::*some-associated-type*
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.
319 .. |reverse_iterator| replace:: `reverse_iterator`
320 .. _reverse_iterator: reverse_iterator.html
322 .. |counting_iterator| replace:: `counting_iterator`
323 .. _counting_iterator: counting_iterator.html
325 .. |transform_iterator| replace:: `transform_iterator`
326 .. _transform_iterator: transform_iterator.html
328 __ index.html#specialized-adaptors