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