adaptor.qbk 11 KB

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