diff --git a/doc/facade-and-adaptor.html b/doc/facade-and-adaptor.html new file mode 100755 index 0000000..996ea4c --- /dev/null +++ b/doc/facade-and-adaptor.html @@ -0,0 +1,2042 @@ + + + +
+ + +Author: | +David Abrahams, Jeremy Siek, Thomas Witt |
---|---|
Contact: | +dave@boost-consulting.com, jsiek@osl.iu.edu, witt@ive.uni-hannover.de |
Organization: | +Boost Consulting, Indiana University Open Systems +Lab, University of Hanover Institute for Transport +Railway Operation and Construction |
Date: | +2003-07-12 |
Number: | This document is a revised version of the official N1476=03-0059 | +
Copyright: | +Copyright Dave Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved |
abstract: | We propose a set of class templates that help programmers +build standard-conforming iterators, both from scratch and +by adapting other iterators. | +
---|
Iterators play an important role in modern C++ programming. The +iterator is the central abstraction of the algorithms of the Standard +Library, allowing algorithms to be re-used in in a wide variety of +contexts. The C++ Standard Library contains a wide variety of useful +iterators. Every one of the standard containers comes with constant +and mutable iterators 2, and also reverse versions of those +same iterators which traverse the container in the opposite direction. +The Standard also supplies istream_iterator and +ostream_iterator for reading from and writing to streams, +insert_iterator, front_insert_iterator and +back_insert_iterator for inserting elements into containers, and +raw_storage_iterator for initializing raw memory [7].
+Despite the many iterators supplied by the Standard Library, obvious +and useful iterators are missing, and creating new iterator types is +still a common task for C++ programmers. The literature documents +several of these, for example line_iterator [3] and Constant_iterator +[9]. The iterator abstraction is so powerful that we expect +programmers will always need to invent new iterator types.
+Although it is easy to create iterators that almost conform to the +standard, the iterator requirements contain subtleties which can make +creating an iterator which actually conforms quite difficult. +Further, the iterator interface is rich, containing many operators +that are technically redundant and tedious to implement. To automate +the repetitive work of constructing iterators, we propose +iterator_facade, an iterator base class template which provides +the rich interface of standard iterators and delegates its +implementation to member functions of the derived class. In addition +to reducing the amount of code necessary to create an iterator, the +iterator_facade also provides compile-time error detection. +Iterator implementation mistakes that often go unnoticed are turned +into compile-time errors because the derived class implementation must +match the expectations of the iterator_facade.
+A common pattern of iterator construction is the adaptation of one +iterator to form a new one. The functionality of an iterator is +composed of four orthogonal aspects: traversal, indirection, equality +comparison and distance measurement. Adapting an old iterator to +create a new one often saves work because one can reuse one aspect of +functionality while redefining the other. For example, the Standard +provides reverse_iterator, which adapts any Bidirectional Iterator +by inverting its direction of traversal. As with plain iterators, +iterator adaptors defined outside the Standard have become commonplace +in the literature:
+[1] | We use the term concept to mean a set of requirements +that a type must satisfy to be used with a particular template +parameter. |
[2] | The term mutable iterator refers to iterators over objects that +can be changed by assigning to the dereferenced iterator, while +constant iterator refers to iterators over objects that cannot be +modified. |
To fulfill the need for constructing adaptors, we propose the +iterator_adaptor class template. Instantiations of +iterator_adaptor serve as a base classes for new iterators, +providing the default behavior of forwarding all operations to the +underlying iterator. The user can selectively replace these features +in the derived iterator class. This proposal also includes a number +of more specialized adaptors, such as the transform_iterator that +applies some user-specified function during the dereference of the +iterator.
+This proposal is purely an addition to the C++ standard library. +However, note that this proposal relies on the proposal for New +Iterator Concepts.
+This proposal is formulated in terms of the new iterator concepts +as proposed in n1477, since user-defined and especially adapted +iterators suffer from the well known categorization problems that are +inherent to the current iterator categories.
+This proposal does not strictly depend on proposal n1477, as there +is a direct mapping between new and old categories. This proposal +could be reformulated using this mapping if n1477 was not accepted.
+The question of iterator interoperability is poorly addressed in the +current standard. There are currently two defect reports that are +concerned with interoperability issues.
+Issue 179 concerns the fact that mutable container iterator types +are only required to be convertible to the corresponding constant +iterator types, but objects of these types are not required to +interoperate in comparison or subtraction expressions. This situation +is tedious in practice and out of line with the way built in types +work. This proposal implements the proposed resolution to issue +179, as most standard library implementations do nowadays. In other +words, if an iterator type A has an implicit or user defined +conversion to an iterator type B, the iterator types are interoperable +and the usual set of operators are available.
+Issue 280 concerns the current lack of interoperability between +reverse iterator types. The proposed new reverse_iterator template +fixes the issues raised in 280. It provides the desired +interoperability without introducing unwanted overloads.
+While the iterator interface is rich, there is a core subset of the +interface that is necessary for all the functionality. We have +identified the following core behaviors for iterators:
+In addition to the behaviors listed above, the core interface elements +include the associated types exposed through iterator traits: +value_type, reference, difference_type, and +iterator_category.
+Iterator facade uses the Curiously Recurring Template Pattern (CRTP) +[Cop95] so that the user can specify the behavior of +iterator_facade in a derived class. Former designs used policy +objects to specify the behavior. The proposal does not use policy +objects for several reasons:
++++
+- the creation and eventual copying of the policy object may create +overhead that can be avoided with the current approach.
+- The policy object approach does not allow for custom constructors +on the created iterator types, an essential feature if +iterator_facade should be used in other library +implementations.
+- Without the use of CRTP, the standard requirement that an +iterator's operator++ returns the iterator type itself means +that all iterators generated by iterator_facade would be +instantiations of iterator_facade. Cumbersome type generator +metafunctions would be needed to build new parameterized +iterators, and a separate iterator_adaptor layer would be +impossible.
+
The user of iterator_facade derives his iterator class from an +instantiation of iterator_facade which takes the derived iterator +class as the first template parameter. The order of the other +template parameters to iterator_facade have been carefully chosen +to take advantage of useful defaults. For example, when defining a +constant lvalue iterator, the user can pass a const-qualified version +of the iterator's value_type as iterator_facade's Value +parameter and omit the Reference parameter which follows.
+The derived iterator class must define member functions implementing +the iterator's core behaviors. The following table describes +expressions which are required to be valid depending on the category +of the derived iterator type. These member functions are described +briefly below and in more detail in the iterator facade +requirements.
+++ ++
++ + ++ + + + + Expression +Effects ++ i.dereference() +Access the value referred to ++ i.equal(j) +Compare for equality with j ++ i.increment() +Advance by one position ++ i.decrement() +Retreat by one position ++ i.advance(n) +Advance by n positions ++ + i.distance_to(j) +Measure the distance to j +
In addition to implementing the core interface functions, an iterator +derived from iterator_facade typically defines several +constructors. To model any of the standard iterator concepts, the +iterator must at least have a copy constructor. Also, if the iterator +type X is meant to be automatically interoperate with another +iterator type Y (as with constant and mutable iterators) then +there must be an implicit conversion from X to Y or from Y +to X (but not both), typically implemented as a conversion +constructor. Finally, if the iterator is to model Forward Traversal +Iterator or a more-refined iterator concept, a default constructor is +required.
+iterator_facade and the operator implementations need to be able +to access the core member functions in the derived class. Making the +core member functions public would expose an implementation detail to +the user. This proposal frees the public interface of the derived +iterator type from any implementation detail.
+Preventing direct access to the core member functions has two +advantages. First, there is no possibility for the user to accidently +use a member function of the iterator when a member of the value_type +was intended. This has been an issue with smart pointer +implementations in the past. The second and main advantage is that +library implementers can freely exchange a hand-rolled iterator +implementation for one based on iterator_facade without fear of +breaking code that was accessing the public core member functions +directly.
+In a naive implementation, keeping the derived class' core member +functions private would require it to grant friendship to +iterator_facade and each of the seven operators. In order to +reduce the burden of limiting access, this proposal provides +iterator_core_access, a class that acts as a gateway to the core +member functions in the derived iterator class. The author of the +derived class only needs to grant friendship to +iterator_core_access to make his core member functions available +to the library.
+ + +iterator_core_access will be typically implemented as an empty +class containing only private static member functions which invoke the +iterator core member functions. There is, however, no need to +standardize the gateway protocol. Note that even if +iterator_core_access used public member functions it would not +open a safety loophole, as every core member function preserves the +invariants of the iterator.
+The indexing operator for a generalized iterator presents special +challenges. A random access iterator's operator[] is only +required to return something convertible to its value_type. +Requiring that it return an lvalue would rule out currently-legal +random-access iterators which hold the referenced value in a data +member (e.g. counting_iterator), because *(p+n) is a reference +into the temporary iterator p+n, which is destroyed when +operator[] returns.
+Writable iterators built with iterator_facade implement the +semantics required by the preferred resolution to issue 299 and +adopted by proposal n1477: the result of p[n] is a proxy object +containing a copy of p+n, and p[n] = x is equivalent to *(p ++ n) = x. This approach will work properly for any random-access +iterator regardless of the other details of its implementation. A +user who knows more about the implementation of her iterator is free +to implement an operator[] which returns an lvalue in the derived +iterator class; it will hide the one supplied by iterator_facade +from clients of her iterator.
+The reference type of a readable iterator (and today's input +iterator) need not in fact be a reference, so long as it is +convertible to the iterator's value_type. When the value_type +is a class, however, it must still be possible to access members +through operator->. Therefore, an iterator whose reference +type is not in fact a reference must return a proxy containing a copy +of the referenced value from its operator->.
+This proposal does not explicitly specify the return type for +operator-> and operator[]. Instead it requires each +iterator_facade instantiation to meet the requirements of its +iterator_category.
+The iterator_adaptor class template adapts some Base 3 +type to create a new iterator. Instantiations of iterator_adaptor +are derived from a corresponding instantiation of iterator_facade +and implement the core behaviors in terms of the Base type. In +essence, iterator_adaptor merely forwards all operations to an +instance of the Base type, which it stores as a member.
+[3] | The term "Base" here does not refer to a base class and is +not meant to imply the use of derivation. We have followed the lead +of the standard library, which provides a base() function to access +the underlying iterator object of a reverse_iterator adaptor. |
The user of iterator_adaptor creates a class derived from an +instantiation of iterator_adaptor and then selectively +redefines some of the core member functions described in the table +above. The Base type need not meet the full requirements for an +iterator. It need only support the operations used by the core +interface functions of iterator_adaptor that have not been +redefined in the user's derived class.
+Several of the template parameters of iterator_adaptor default to +use_default. This allows the user to make use of a default +parameter even when the user wants to specify a parameter later in the +parameter list. Also, the defaults for the corresponding associated +types are fairly complicated, so metaprogramming is required to +compute them, and use_default can help to simplify the +implementation. Finally, use_default is not left unspecified +because specification helps to highlight that the Reference +template parameter may not always be identical to the iterator's +reference type, and will keep users making mistakes based on that +assumption.
+This proposal also contains several examples of specialized adaptors +which were easily implemented using iterator_adaptor:
+Based on examples in the Boost library, users have generated many new +adaptors, among them a permutation adaptor which applies some +permutation to a random access iterator, and a strided adaptor, which +adapts a random access iterator by multiplying its unit of motion by a +constant factor. In addition, the Boost Graph Library (BGL) uses +iterator adaptors to adapt other graph libraries, such as LEDA [10] +and Stanford GraphBase [8], to the BGL interface (which requires C++ +Standard compliant iterators).
++struct use_default; + +struct iterator_core_access { /* implementation detail */ }; + +template < + class Derived + , class Value + , class AccessCategory + , class TraversalCategory + , class Reference = Value& + , class Difference = ptrdiff_t +> +class iterator_facade; + +template < + class Derived + , class Base + , class Value = use_default + , class Category = use_default + , class Reference = use_default + , class Difference = use_default +> +class iterator_adaptor; + +template < + class Iterator + , class Value = use_default + , class Category = use_default + , class Reference = use_default + , class Difference = use_default +> +class indirect_iterator; + +template <class Iterator> +class reverse_iterator; + +template < + class UnaryFunction + , class Iterator + , class Reference = use_default + , class Value = use_default +> +class transform_iterator; + +template <class Predicate, class Iterator> +class filter_iterator; + +template < + class Incrementable + , class Category = use_default + , class Difference = use_default +> +class counting_iterator + +template <class UnaryFunction> +class function_output_iterator; ++
iterator_facade is a base class template which implements the +interface of standard iterators in terms of a few core functions +and associated types, to be supplied by a derived iterator class.
++template < + class Derived + , class Value + , class AccessCategory + , class TraversalCategory + , class Reference = /* see below */ + , class Difference = ptrdiff_t +> +class iterator_facade { +public: + typedef remove_cv<Value>::type value_type; + typedef Reference reference; + typedef /* see description of operator-> */ pointer; + typedef Difference difference_type; + typedef iterator_tag<AccessCategory, TraversalCategory> iterator_category; + + reference operator*() const; + /* see below */ operator->() const; + /* see below */ operator[](difference_type n) const; + Derived& operator++(); + Derived operator++(int); + Derived& operator--(); + Derived operator--(int); + Derived& operator+=(difference_type n); + Derived& operator-=(difference_type n); + Derived operator-(difference_type n) const; +}; + +// Comparison operators +template <class Dr1, class V1, class AC1, class TC1, class R1, class D1, + class Dr2, class V2, class AC2, class TC2, class R2, class D2> +typename enable_if_interoperable<Dr1, Dr2, bool>::type // exposition +operator ==(iterator_facade<Dr1, V1, AC1, TC1, R1, D1> const& lhs, + iterator_facade<Dr2, V2, AC2, TC2, R2, D2> const& rhs); + +template <class Dr1, class V1, class AC1, class TC1, class R1, class D1, + class Dr2, class V2, class AC2, class TC2, class R2, class D2> +typename enable_if_interoperable<Dr1, Dr2, bool>::type +operator !=(iterator_facade<Dr1, V1, AC1, TC1, R1, D1> const& lhs, + iterator_facade<Dr2, V2, AC2, TC2, R2, D2> const& rhs); + +template <class Dr1, class V1, class AC1, class TC1, class R1, class D1, + class Dr2, class V2, class AC2, class TC2, class R2, class D2> +typename enable_if_interoperable<Dr1, Dr2, bool>::type +operator <(iterator_facade<Dr1, V1, AC1, TC1, R1, D1> const& lhs, + iterator_facade<Dr2, V2, AC2, TC2, R2, D2> const& rhs); + +template <class Dr1, class V1, class AC1, class TC1, class R1, class D1, + class Dr2, class V2, class AC2, class TC2, class R2, class D2> +typename enable_if_interoperable<Dr1, Dr2, bool>::type +operator <=(iterator_facade<Dr1, V1, AC1, TC1, R1, D1> const& lhs, + iterator_facade<Dr2, V2, AC2, TC2, R2, D2> const& rhs); + +template <class Dr1, class V1, class AC1, class TC1, class R1, class D1, + class Dr2, class V2, class AC2, class TC2, class R2, class D2> +typename enable_if_interoperable<Dr1, Dr2, bool>::type +operator >(iterator_facade<Dr1, V1, AC1, TC1, R1, D1> const& lhs, + iterator_facade<Dr2, V2, AC2, TC2, R2, D2> const& rhs); + +template <class Dr1, class V1, class AC1, class TC1, class R1, class D1, + class Dr2, class V2, class AC2, class TC2, class R2, class D2> +typename enable_if_interoperable<Dr1, Dr2, bool>::type +operator >=(iterator_facade<Dr1, V1, AC1, TC1, R1, D1> const& lhs, + iterator_facade<Dr2, V2, AC2, TC2, R2, D2> const& rhs); + +template <class Dr1, class V1, class AC1, class TC1, class R1, class D1, + class Dr2, class V2, class AC2, class TC2, class R2, class D2> +typename enable_if_interoperable<Dr1, Dr2, bool>::type +operator >=(iterator_facade<Dr1, V1, AC1, TC1, R1, D1> const& lhs, + iterator_facade<Dr2, V2, AC2, TC2, R2, D2> const& rhs); + +// Iterator difference +template <class Dr1, class V1, class AC1, class TC1, class R1, class D1, + class Dr2, class V2, class AC2, class TC2, class R2, class D2> +typename enable_if_interoperable<Dr1, Dr2, bool>::type +operator -(iterator_facade<Dr1, V1, AC1, TC1, R1, D1> const& lhs, + iterator_facade<Dr2, V2, AC2, TC2, R2, D2> const& rhs); + +// Iterator addition +template <class Derived, class V, class AC, class TC, class R, class D> +Derived operator+ (iterator_facade<Derived, V, AC, TC, R, D> const&, + typename Derived::difference_type n) ++
[Note: The enable_if_interoperable template used above is for exposition +purposes. The member operators should be only be in an overload set +provided the derived types Dr1 and Dr2 are interoperable, by +which we mean they are convertible to each other. The +enable_if_interoperable approach uses SFINAE to take the operators +out of the overload set when the types are not interoperable.]
+ +The Derived template parameter must be a class derived from +iterator_facade.
+The default for the Reference parameter is Value& if the +access category for iterator_facade is implicitly convertible to +writable_iterator_tag, and const Value& otherwise.
+The following table describes the other requirements on the +Derived parameter. Depending on the resulting iterator's +iterator_category, a subset of the expressions listed in the table +are required to be valid. The operations in the first column must be +accessible to member functions of class iterator_core_access.
+In the table below, X is the derived iterator type, a is an +object of type X, b and c are objects of type const X, +n is an object of X::difference_type, y is a constant +object of a single pass iterator type interoperable with X, and z +is a constant object of a random access traversal iterator type +interoperable with X.
+Expression | +Return Type | +Assertion/Note | +Required to implement +Iterator Concept(s) | +
---|---|---|---|
c.dereference() | +X::reference | ++ | Readable Iterator, Writable +Iterator | +
c.equal(b) | +convertible to bool | +true iff b and c are +equivalent. | +Single Pass Iterator | +
c.equal(y) | +convertible to bool | +true iff c and y refer to the +same position. Implements c == y +and c != y. | +Single Pass Iterator | +
a.advance(n) | +unused | ++ | Random Access Traversal +Iterator | +
a.increment() | +unused | ++ | Incrementable Iterator | +
a.decrement() | +unused | ++ | Bidirectional Traversal +Iterator | +
c.distance_to(b) | +convertible to +X::difference_type | +equivalent to distance(c, b) | +Random Access Traversal +Iterator | +
c.distance_to(z) | +convertible to +X::difference_type | +equivalent to distance(c, z). +Implements c - z, c < z, c +<= z, c > z, and c >= c. | +Random Access Traversal +Iterator | +
The operations in this section are described in terms of operations on +the core interface of Derived which may be inaccessible +(i.e. private). The implementation should access these operations +through member functions of class iterator_core_access.
+reference operator*() const;
+Returns: | static_cast<Derived const*>(this)->dereference() | +
---|
operator->() const; (see below)
+Returns: | If X::reference is a reference type, returns an object +of type X::pointer equal to: ++&static_cast<Derived const*>(this)->dereference() ++ Otherwise returns an object of unspecified type such that, given an +object a of type X, a->m is equivalent to (w = *a, +w.m) for some temporary object w of type X::value_type. +The type X::pointer is Value* if the access category for +X is implicitly convertible to writable_iterator_tag, and +Value const* otherwise. + |
+
---|
unspecified operator[](difference_type n) const;
+Returns: | an object convertible to X::reference and holding a copy +p of a+n such that, for a constant object v of type +X::value_type, X::reference(a[n] = v) is equivalent +to p = v. | +
---|
Derived& operator++();
+Effects: | +static_cast<Derived*>(this)->increment(); +return *this; ++ |
+
---|
Derived operator++(int);
+Effects: | +Derived tmp(static_cast<Derived const*>(this)); +++*this; +return tmp; ++ |
+
---|
Derived& operator--();
+Effects: | +static_cast<Derived*>(this)->decrement(); +return *this; ++ |
+
---|
Derived operator--(int);
+Effects: | +Derived tmp(static_cast<Derived const*>(this)); +--*this; +return tmp; ++ |
+
---|
Derived& operator+=(difference_type n);
+Effects: | +static_cast<Derived*>(this)->advance(n); +return *this; ++ |
+
---|
Derived& operator-=(difference_type n);
+Effects: | +static_cast<Derived*>(this)->advance(-n); +return *this; ++ |
+
---|
Derived operator-(difference_type n) const;
+Effects: | Derived tmp(static_cast<Derived const*>(this)); +return tmp -= n; | +
---|---|
Returns: | static_cast<Derived const*>(this)->advance(-n); | +
The iterator_adaptor is a base class template derived from an +instantiation of iterator_facade. The core interface functions +expected by iterator_facade are implemented in terms of the +iterator_adaptor's Base template parameter. A class derived +from iterator_adaptor typically redefines some of the core +interface functions to adapt the behavior of the Base type. +Whether the derived class models any of the standard iterator concepts +depends on the operations supported by the Base type and which +core interface functions of iterator_facade are redefined in the +Derived class.
++template < + class Derived + , class Base + , class Value = use_default + , class Category = use_default + , class Reference = use_default + , class Difference = use_default +> +class iterator_adaptor + : public iterator_facade<Derived, /* see details ...*/> +{ + friend class iterator_core_access; + public: + iterator_adaptor(); + explicit iterator_adaptor(Base iter); + Base base() const; + protected: + Base const& base_reference() const; + Base& base_reference(); + private: // Core iterator interface for iterator_facade. + typename iterator_adaptor::reference dereference() const; + + template < + class OtherDerived, class OtherIterator, class V, class C, class R, class D + > + bool equal(iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D> const& x) const; + + void advance(typename iterator_adaptor::difference_type n); + void increment(); + void decrement(); + + template < + class OtherDerived, class OtherIterator, class V, class C, class R, class D + > + typename iterator_adaptor::difference_type distance_to( + iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D> const& y) const; + + private: + Base m_iterator; +}; ++
The Derived template parameter must be a derived class of +iterator_adaptor. The Base type must implement the expressions +involving m_iterator in the specifications of those private member +functions of iterator_adaptor that are not redefined by the +Derived class and that are needed to model the concept +corresponding to the chosen Category according to the requirements +of iterator_facade. The rest of the template parameters specify +the types for the member typedefs in iterator_facade. The +following pseudo-code specifies the traits types for +iterator_adaptor.
++if (Value == use_default) + value_type = iterator_traits<Base>::value_type; +else + value_type = remove_cv<Value>::type; + +if (Reference == use_default) { + if (Value == use_default) + reference = iterator_traits<Base>::reference; + else + reference = Value&; +} else + reference = Reference; + +if (Distance == use_default) + difference_type = iterator_traits<Base>::difference_type; +else + difference_type = Distance; + +if (Category == use_default) + iterator_category = iterator_tag< + access_category< + iterator< iterator_traits<Base>::iterator_category, + Value, + Distance, + Value*, + Reference > >, + traversal_category< + iterator< iterator_traits<Base>::iterator_category, + Value, + Distance, + Value*, + Reference > > +else + iterator_category = Category; ++ +
iterator_adaptor();
+Requires: | The Base type must be Default Constructible. | +
---|---|
Returns: | An instance of iterator_adaptor with +m_iterator default constructed. | +
explicit iterator_adaptor(Base iter);
+Returns: | An instance of iterator_adaptor with +m_iterator copy constructed from iter. | +
---|
Base base() const;
+Returns: | m_iterator | +
---|
Base const& base_reference() const;
+Returns: | A const reference to m_iterator. | +
---|
Base& base_reference();
+Returns: | A non-const reference to m_iterator. | +
---|
typename iterator_adaptor::reference dereference() const;
+Returns: | *m_iterator | +
---|
+template < +class OtherDerived, class OtherIterator, class V, class C, class R, class D +> +bool equal(iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D> const& x) const; ++
Returns: | m_iterator == x.base() | +
---|
void advance(typename iterator_adaptor::difference_type n);
+Effects: | m_iterator += n; | +
---|
void increment();
+Effects: | ++m_iterator; | +
---|
void decrement();
+Effects: | --m_iterator; | +
---|
+template < + class OtherDerived, class OtherIterator, class V, class C, class R, class D +> +typename iterator_adaptor::difference_type distance_to( + iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D> const& y) const; ++
Returns: | y.base() - m_iterator | +
---|
[Note: The enable_if_convertible<X,Y>::type expression used in +this section is for exposition purposes. The converting constructors +for specialized adaptors should be only be in an overload set provided +that an object of type X is implicitly convertible to an object of +type Y. The enable_if_convertible approach uses SFINAE to +take the constructor out of the overload set when the types are not +implicitly convertible.]
+The indirect iterator adapts an iterator by applying an extra +dereference inside of operator*(). For example, this iterator +adaptor makes it possible to view a container of pointers +(e.g. list<foo*>) as if it were a container of the pointed-to type +(e.g. list<foo>) .
+ ++template < + class Iterator + , class Value = use_default + , class Category = use_default + , class Reference = use_default + , class Difference = use_default +> +class indirect_iterator + : public iterator_adaptor</* see discussion */> +{ + friend class iterator_core_access; + public: + indirect_iterator(); + indirect_iterator(Iterator x); + template < + class Iterator2, class Value2, class Category2 + , class Reference2, class Difference2 + > + indirect_iterator( + indirect_iterator< + Iterator2, Value2, Category2, Reference2, Difference2 + > const& y + , typename enable_if_convertible<Iterator2, Iterator>::type* = 0 // exposition + ); +private: // as-if specification + typename indirect_iterator::reference dereference() const + { + return **this->base(); + } +}; ++
The value_type of the Iterator template parameter should +itself be dereferenceable. The return type of the operator* for +the value_type must be the same type as the Reference template +parameter. The Value template parameter will be the value_type +for the indirect_iterator, unless Value is const. If Value +is const X, then value_type will be non- const X. The +default for Value is
++iterator_traits< iterator_traits<Iterator>::value_type >::value_type ++
If the default is used for Value, then there must be a valid +specialization of iterator_traits for the value type of the base +iterator.
+The Reference parameter will be the reference type of the +indirect_iterator. The default is Value&.
+The Category parameter is the iterator_category type for the +indirect_iterator. The default is +iterator_traits<Iterator>::iterator_category.
+The indirect iterator will model the most refined standard traversal +concept that is modeled by the Iterator type. The indirect +iterator will model the most refined standard access concept that is +modeled by the value type of Iterator.
+indirect_iterator();
+Requires: | Iterator must be Default Constructible. | +
---|---|
Returns: | An instance of indirect_iterator with +a default constructed base object. | +
indirect_iterator(Iterator x);
+Returns: | An instance of indirect_iterator with +the iterator_adaptor subobject copy constructed from x. | +
---|
+template < + class Iterator2, class Value2, class Category2 + , class Reference2, class Difference2 +> +indirect_iterator( + indirect_iterator< + Iterator2, Value2, Category2, Reference2, Difference2 + > const& y + , typename enable_if_convertible<Iterator2, Iterator>::type* = 0 // exposition +); ++
Requires: | Iterator2 is implicitly convertible to Iterator. | +
---|---|
Returns: | An instance of indirect_iterator that is a copy of y. | +
The reverse iterator adaptor flips the direction of a base iterator's +motion. Invoking operator++() moves the base iterator backward and +invoking operator--() moves the base iterator forward.
++template <class Iterator> +class reverse_iterator : + public iterator_adaptor< reverse_iterator<Iterator>, Iterator > +{ + friend class iterator_core_access; +public: + reverse_iterator() {} + explicit reverse_iterator(Iterator x) ; + + template<class OtherIterator> + reverse_iterator( + reverse_iterator<OtherIterator> const& r + , typename enable_if_convertible<OtherIterator, Iterator>::type* = 0 // exposition + ); + +private: // as-if specification + typename reverse_iterator::reference dereference() const { return *prior(this->base()); } + + void increment() { --this->base_reference(); } + void decrement() { ++this->base_reference(); } + + void advance(typename reverse_iterator::difference_type n) + { + this->base_reference() += -n; + } + + template <class OtherIterator> + typename reverse_iterator::difference_type + distance_to(reverse_iterator<OtherIterator> const& y) const + { + return this->base_reference() - y.base(); + } + +}; ++
The base Iterator must be a model of Bidirectional Traversal +Iterator. The resulting reverse_iterator will be a model of the +most refined standard traversal and access concepts that are modeled +by Iterator.
+reverse_iterator();
+Requires: | Iterator must be Default Constructible. | +
---|---|
Returns: | An instance of reverse_iterator with a +default constructed base object. | +
explicit reverse_iterator(Iterator x);
+Returns: | An instance of reverse_iterator with a +base object copy constructed from x. | +
---|
+template<class OtherIterator> +reverse_iterator( + reverse_iterator<OtherIterator> const& r + , typename enable_if_convertible<OtherIterator, Iterator>::type* = 0 // exposition +); ++
Requires: | OtherIterator is implicitly convertible to Iterator. | +
---|---|
Returns: | An instance of reverse_iterator that is a copy of r. | +
The transform iterator adapts an iterator by applying some function +object to the result of dereferencing the iterator. In other words, +the operator* of the transform iterator first dereferences the +base iterator, passes the result of this to the function object, and +then returns the result.
++template <class AdaptableUnaryFunction, + class Iterator, + class Reference = use_default, + class Value = use_default> +class transform_iterator + : public iterator_adaptor</* see discussion */> +{ + friend class iterator_core_access; +public: + transform_iterator(); + transform_iterator(Iterator const& x, AdaptableUnaryFunction f); + + template<class OtherIterator, class R2, class V2> + transform_iterator( + transform_iterator<AdaptableUnaryFunction, OtherIterator, R2, V2> const& t + , typename enable_if_convertible<OtherIterator, Iterator>::type* = 0 // exposition + ); + + AdaptableUnaryFunction functor() const; +private: + typename transform_iterator::value_type dereference() const; + AdaptableUnaryFunction m_f; +}; ++
The type AdaptableUnaryFunction must be Assignable, Copy +Constructible, and the expression f(x) must be valid where f +is an object of type AdaptableUnaryFunction, x is an object of +type AdaptableUnaryFunction::argument_type, and where the type of +f(x) must be AdaptableUnaryFunction::result_type.
+The type Iterator must at least model Readable Iterator. The +resulting transform_iterator models the most refined of the +following options that is also modeled by Iterator.
++++
+- Writable Lvalue Iterator if the result_type of the +AdaptableUnaryFunction is a non-const reference.
+- Readable Lvalue Iterator if the result_type is a const +reference.
+- Readable Iterator otherwise.
+
The transform_iterator models the most refined standard traversal +concept that is modeled by Iterator.
+The value_type of transform_iterator is +remove_reference<result_type>::type. The reference type is +result_type.
+transform_iterator();
+Returns: | An instance of transform_iterator with m_f +and m_iterator default constructed. | +
---|
transform_iterator(Iterator const& x, AdaptableUnaryFunction f);
+Returns: | An instance of transform_iterator with m_f +initialized to f and m_iterator initialized to x. | +
---|
+template<class OtherIterator, class R2, class V2> +transform_iterator( + transform_iterator<AdaptableUnaryFunction, OtherIterator, R2, V2> const& t + , typename enable_if_convertible<OtherIterator, Iterator>::type* = 0 // exposition +); ++
Returns: | An instance of transform_iterator that is a copy of t. | +
---|---|
Requires: | OtherIterator is implicitly convertible to Iterator. | +
AdaptableUnaryFunction functor() const;
+Returns: | m_f | +
---|
typename transform_iterator::value_type dereference() const;
+Returns: | m_f(transform_iterator::dereference()); | +
---|
The filter iterator adaptor creates a view of an iterator range in +which some elements of the range are skipped over. A predicate +function object controls which elements are skipped. When the +predicate is applied to an element, if it returns true then the +element is retained and if it returns false then the element is +skipped over. When skipping over elements, it is necessary for the +filter adaptor to know when to stop so as to avoid going past the end +of the underlying range. Therefore the constructor of the filter +iterator takes two iterator parameters: the position for the filtered +iterator and the end of the range.
++template <class Predicate, class Iterator> +class filter_iterator + : public iterator_adaptor< + filter_iterator<Predicate, Iterator>, Iterator + , use_default + , /* see details */ + > +{ + public: + filter_iterator(); + filter_iterator(Predicate f, Iterator x, Iterator end = Iterator()); + filter_iterator(Iterator x, Iterator end = Iterator()); + template<class OtherIterator> + filter_iterator( + filter_iterator<Predicate, OtherIterator> const& t + , typename enable_if_convertible<OtherIterator, Iterator>::type* = 0 // exposition + ); + Predicate predicate() const; + Iterator end() const; + + private: // as-if specification + void increment() + { + ++(this->base_reference()); + satisfy_predicate(); + } + + void satisfy_predicate() + { + while (this->base() != this->m_end && !this->m_predicate(*this->base())) + ++(this->base_reference()); + } + + Predicate m_predicate; + Iterator m_end; +}; ++
The base Iterator parameter must be a model of Readable Iterator +and Single Pass Iterator. The resulting filter_iterator will be a +model of Forward Traversal Iterator if Iterator is, otherwise the +filter_iterator will be a model of Single Pass Iterator. The +access category of the filter_iterator will be the most refined +standard access category that is modeled by Iterator.
+ +The Predicate must be Assignable, Copy Constructible, and the +expression p(x) must be valid where p is an object of type +Predicate, x is an object of type +iterator_traits<Iterator>::value_type, and where the type of +p(x) must be convertible to bool.
+filter_iterator();
+Requires: | Predicate and Iterator must be Default Constructible. | +
---|---|
Returns: | a filter_iterator whose +predicate is a default constructed Predicate and +whose end is a default constructed Iterator. | +
filter_iterator(Predicate f, Iterator x, Iterator end = Iterator());
+Returns: | A filter_iterator at position x that filters according +to predicate f and that will not increment past end. | +
---|
filter_iterator(Iterator x, Iterator end = Iterator());
+Requires: | Predicate must be Default Constructible. | +
---|---|
Returns: | A filter_iterator at position x that filters +according to a default constructed Predicate +and that will not increment past end. | +
+template <class OtherIterator> +filter_iterator( + filter_iterator<Predicate, OtherIterator> const& t + , typename enable_if_convertible<OtherIterator, Iterator>::type* = 0 // exposition + );`` ++
Requires: | OtherIterator is implicitly convertible to Iterator. | +
---|---|
Returns: | A copy of iterator t. | +
Predicate predicate() const;
+Returns: | A copy of the predicate object used to construct *this. | +
---|
Iterator end() const;
+Returns: | The object end used to construct *this. | +
---|
The counting iterator adaptor implements dereference by returning a +reference to the base object. The other operations are implemented by +the base m_iterator, as per the inheritance from +iterator_adaptor.
++template <class Incrementable, class Category = use_default, class Difference = use_default> +class counting_iterator + : public iterator_adaptor< + counting_iterator<Incrementable, Category, Difference> + , Incrementable + , Incrementable + , /* see details for category */ + , Incrementable const& + , Incrementable const* + , /* distance = Difference or a signed integral type */> +{ + friend class iterator_core_access; + public: + counting_iterator(); + counting_iterator(counting_iterator const& rhs); + counting_iterator(Incrementable x); + private: + typename counting_iterator::reference dereference() const + { + return this->base_reference(); + } + }; ++
The Incrementable type must be Default Constructible, Copy +Constructible, and Assignable. The default distance is +an implementation defined signed integegral type.
+The resulting counting_iterator models Readable Lvalue Iterator.
+Furthermore, if you wish to create a counting iterator that is a Forward +Traversal Iterator, then the following expressions must be valid:
++Incrementable i, j; +++i // pre-increment +i == j // operator equal ++
If you wish to create a counting iterator that is a +Bidirectional Traversal Iterator, then pre-decrement is also required:
++--i ++
If you wish to create a counting iterator that is a Random Access +Traversal Iterator, then these additional expressions are also +required:
++counting_iterator::difference_type n; +i += n +n = i - j +i < j ++
counting_iterator();
+Returns: | A default constructed instance of counting_iterator. | +
---|
counting_iterator(counting_iterator const& rhs);
+Returns: | An instance of counting_iterator that is a copy of rhs. | +
---|
counting_iterator(Incrementable x);
+Returns: | An instance of counting_iterator with its base +object copy constructed from x. | +
---|
The function output iterator adaptor makes it easier to create custom +output iterators. The adaptor takes a unary function and creates a +model of Output Iterator. Each item assigned to the output iterator is +passed as an argument to the unary function. The motivation for this +iterator is that creating a conforming output iterator is non-trivial, +particularly because the proper implementation usually requires a +proxy object.
++template <class UnaryFunction> +class function_output_iterator { +public: + typedef iterator_tag< + writable_iterator_tag + , incrementable_traversal_tag + > iterator_category; + typedef void value_type; + typedef void difference_type; + typedef void pointer; + typedef void reference; + + explicit function_output_iterator(const UnaryFunction& f = UnaryFunction()); + + struct output_proxy { + output_proxy(UnaryFunction& f); + template <class T> output_proxy& operator=(const T& value); + }; + output_proxy operator*(); + function_output_iterator& operator++(); + function_output_iterator& operator++(int); +}; ++
The UnaryFunction must be Assignable, Copy Constructible, and the +expression f(x) must be valid, where f is an object of type +UnaryFunction and x is an object of a type accepted by f. +The resulting function_output_iterator is a model of the Writable +and Incrementable Iterator concepts.
+explicit function_output_iterator(const UnaryFunction& f = UnaryFunction());
+Returns: | An instance of function_output_iterator with +f stored as a data member. | +
---|
output_proxy operator*();
+Returns: | An instance of output_proxy constructed with +a copy of the unary function f. | +
---|
function_output_iterator& operator++();
+Returns: | *this | +
---|
function_output_iterator& operator++(int);
+Returns: | *this | +
---|
output_proxy(UnaryFunction& f);
+Returns: | An instance of output_proxy with f stored as +a data member. | +
---|
template <class T> output_proxy& operator=(const T& value);
+Effects: | +m_f(value); +return *this; ++ |
+
---|
[Cop95] | [Coplien, 1995] Coplien, J., Curiously Recurring Template +Patterns, C++ Report, February 1995, pp. 24-27. |
Author: | +David Abrahams, Jeremy Siek, Thomas Witt |
---|---|
Contact: | +dave@boost-consulting.com, jsiek@osl.iu.edu, witt@ive.uni-hannover.de |
Organization: | +Boost Consulting, Indiana University Open Systems Lab, University of Hanover Institute for Transport Railway Operation and Construction |
Date: | +2003-07-12 |
Number: | This document is a revised version of the official N1477=03-0060 | +
Copyright: | +Copyright Dave Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved |
Abstract: | We propose a new system of iterator concepts that treat +access and positioning independently. This allows the +concepts to more closely match the requirements +of algorithms and provides better categorizations +of iterators that are used in practice. This proposal +is a revision of paper n1297. | +
---|
The standard iterator categories and requirements are flawed because +they use a single hierarchy of concepts to address two orthogonal +issues: iterator traversal and value access. As a result, many +algorithms with requirements expressed in terms of the iterator +categories are too strict. Also, many real-world iterators can not be +accurately categorized. A proxy-based iterator with random-access +traversal, for example, may only legally have a category of "input +iterator", so generic algorithms are unable to take advantage of its +random-access capabilities. The current iterator concept hierarchy is +geared towards iterator traversal (hence the category names), while +requirements that address value access sneak in at various places. The +following table gives a summary of the current value access +requirements in the iterator categories.
+Output Iterator | +*i = a | +
Input Iterator | +*i is convertible to T | +
Forward Iterator | +*i is T& (or const T& once issue 200 +is resolved) | +
Random Access Iterator | +i[n] is convertible to T (also i[n] = t +is required for mutable iterators once issue 299 +is resolved) | +
Because iterator traversal and value access are mixed together in a +single hierarchy, many useful iterators can not be appropriately +categorized. For example, vector<bool>::iterator is almost a +random access iterator, but the return type is not bool& (see +issue 96 and Herb Sutter's paper J16/99-0008 = WG21 +N1185). Therefore, the iterators of vector<bool> only meet the +requirements of input iterator and output iterator. This is so +nonintuitive that at least one implementation erroneously assigns +random_access_iterator_tag as its iterator_category.
+Another difficult-to-categorize iterator is the transform iterator, an +adaptor which applies a unary function object to the dereferenced +value of the some underlying iterator (see transform_iterator). +For unary functions such as times, the return type of +operator* clearly needs to be the result_type of the function +object, which is typically not a reference. Because random access +iterators are required to return lvalues from operator*, if you +wrap int* with a transform iterator, you do not get a random +access iterator as might be expected, but an input iterator.
+A third example is found in the vertex and edge iterators of the +Boost Graph Library. These iterators return vertex and edge +descriptors, which are lightweight handles created on-the-fly. They +must be returned by-value. As a result, their current standard +iterator category is input_iterator_tag, which means that, +strictly speaking, you could not use these iterators with algorithms +like min_element(). As a temporary solution, the concept +Multi-Pass Input Iterator was introduced to describe the vertex and +edge descriptors, but as the design notes for the concept suggest, a +better solution is needed.
+In short, there are many useful iterators that do not fit into the +current standard iterator categories. As a result, the following bad +things happen:
+The new iterator concepts are backward-compatible with the old +iterator requirements, and old iterators are forward-compatible with +the new iterator concepts. That is to say, iterators that satisfy the +old requirements also satisfy appropriate concepts in the new system, +and iterators modeling the new concepts will automatically satisfy the +appropriate old requirements.
+ + +The algorithms in the standard library benefit from the new iterator +concepts because the new concepts provide a more accurate way to +express their type requirements. The result is algorithms that are +usable in more situations and have fewer type requirements. The +following lists the proposed changes to the type requirements of +algorithms.
+Forward Iterator -> Forward Traversal Iterator and Readable Iterator
++find_end, adjacent_find, search, search_n, rotate_copy, lower_bound, upper_bound, equal_range, binary_search, min_element, max_element+
Forward Iterator (1) -> Single Pass Iterator and Readable Iterator +Forward Iterator (2) -> Forward Traversal Iterator and Readable Iterator
++find_first_of+
Forward Iterator -> Readable Iterator and Writable Iterator
++iter_swap+
Forward Iterator -> Single Pass Iterator and Writable Iterator
++fill, generate+
Forward Iterator -> Forward Traversal Iterator and Swappable Iterator
++rotate+
Forward Iterator (1) -> Swappable Iterator and Single Pass Iterator +Forward Iterator (2) -> Swappable Iterator and Incrementable Iterator
++swap_ranges+
Forward Iterator -> Single Pass Iterator and Readable Iterator and Writable Iterator
++replace, replace_if+
Bidirectional Iterator (1) -> Bidirectional Traversal Iterator and Readable Iterator, +Bidirectional Iterator (2) -> Bidirectional Traversal Iterator and Writable Iterator
++copy_backwards+
The iterator requirements are be separated into two hierarchies. One +set of concepts handles the syntax and semantics of value access:
+The refinement relationships among these iterator concepts are given +in the following diagram.
+The access concepts describe requirements related to operator* and +operator->, including the value_type, reference, and +pointer associated types.
+The other set of concepts handles traversal:
+The refinement relationships for the traversal concepts are in the +following diagram.
+In addition to the iterator movement operators, such as +operator++, the traversal concepts also include requirements on +position comparison such as operator== and operator<. The +reason for the fine grain slicing of the concepts into the +Incrementable and Single Pass is to provide concepts that are exact +matches with the original input and output iterator requirements.
+The relationship between the new iterator concepts and the old are +given in the following diagram.
+Like the old iterator requirements, we provide tags for purposes of +dispatching. There are two hierarchies of tags, one for the access +concepts and one for the traversal concepts. We provide an access +mechanism for mapping iterator types to these new tags. Our design +reuses iterator_traits<Iter>::iterator_category as the access +mechanism. To enable this, a pair of access and traversal tags are +combined into a single type using the following iterator_tag class.
++template <class AccessTag, class TraversalTag> +struct iterator_tag : /* appropriate old category or categories */ +{ + typedef AccessTag access; + typedef TraversalTag traversal; +}; ++
The iterator_tag class template is derived from the appropriate +iterator tag or tags from the old requirements based on the new-style +tags passed as template parameters. The algorithm for determining the +old tag or tags from the new tags picks the least-refined old concepts +that include all of the requirements of the access and traversal +concepts (that is, the closest fit), if any such category exists. For +example, a the category tag for a Readable Single Pass Iterator will +always be derived from input_iterator_tag, while the category tag +for a Single Pass Iterator that is both Readable and Writable will be +derived from both input_iterator_tag and output_iterator_tag.
+We also provide two helper classes that make it convenient to obtain +the access and traversal tags of an iterator. These helper classes +work both for iterators whose iterator_category is +iterator_tag and also for iterators using the original iterator +categories.
++template <class Iterator> struct access_category { typedef ... type; }; +template <class Iterator> struct traversal_category { typedef ... type; }; ++
The most difficult design decision concerned the operator[]. The +direct approach for specifying operator[] would have a return type +of reference; the same as operator*. However, going in this +direction would mean that an iterator satisfying the old Random Access +Iterator requirements would not necessarily be a model of Readable or +Writable Lvalue Iterator. Instead we have chosen a design that +matches the preferred resolution of issue 299: operator[] is +only required to return something convertible to the value_type +(for a Readable Iterator), and is required to support assignment +i[n] = t (for a Writable Iterator).
+In the tables below, X is an iterator type, a is a constant +object of type X, T is +std::iterator_traits<X>::value_type, and v is a constant +object of type T.
+A class or built-in type X models the Readable Iterator concept +for the value type T if the following expressions are valid and +respect the stated semantics. U is the type of any specified +member of type T.
++++
++ + ++ + + + Readable Iterator Requirements (in addition to CopyConstructible) ++ + + Expression +Return Type +Assertion/Note/Precondition/Postcondition ++ iterator_traits<X>::value_type +T +Any non-reference, non-cv-qualified type ++ iterator_traits<X>::reference +Convertible to +iterator_traits<X>::value_type ++ + access_category<X>::type +Convertible to +readable_iterator_tag ++ + *a +iterator_traits<X>::reference +pre: a is dereferenceable. If a == +b then *a is equivalent to *b ++ + a->m +U& +pre: (*a).m is well-defined. +Equivalent to (*a).m +
A class or built-in type X models the Writable Iterator concept +if the following expressions are valid and respect the stated +semantics.
+ +A class or built-in type X models the Swappable Iterator concept +if the following expressions are valid and respect the stated +semantics.
++++
++ + ++ + + + Swappable Iterator Requirements (in addition to CopyConstructible) ++ + + Expression +Return Type +Postcondition ++ + iter_swap(a, b) +void +post: the pointed to values are exchanged +
The Readable Lvalue Iterator concept adds the requirement that the +reference type be a reference to the value type of the iterator.
++++
++ + ++ + + + Readable Lvalue Iterator Requirements (in addition to Readable Iterator) ++ + + Expression +Return Type +Assertion ++ iterator_traits<X>::reference +T& +T is cv +iterator_traits<X>::value_type +where cv is an optional +cv-qualification ++ + access_category<X>::type +Convertible to +readable_lvalue_iterator_tag ++
The Writable Lvalue Iterator concept adds the requirement that the +reference type be a non-const reference to the value type of the +iterator.
++++
++ + ++ + + Writable Lvalue Iterator Requirements (in addition to Readable Lvalue Iterator) ++ + + Expression +Return Type ++ iterator_traits<X>::reference +iterator_traits<X>::value_type& ++ + access_category<X>::type +Convertible to writable_lvalue_iterator_tag +
In the tables below, X is an iterator type, a and b are +constant objects of type X, r and s are mutable objects of +type X, T is std::iterator_traits<X>::value_type, and +v is a constant object of type T.
+A class or built-in type X models the Incrementable Iterator +concept if the following expressions are valid and respect the stated +semantics.
++++
++ + ++ + + + Incrementable Iterator Requirements (in addition to Assignable, Copy Constructible) ++ + + Expression +Return Type +Assertion/Semantics ++ ++r +X& +&r == &++r ++ r++ +X +{ X tmp = r; ++r; return tmp; } ++ + traversal_category<X>::type +Convertible to incrementable_iterator_tag ++
A class or built-in type X models the Single Pass Iterator +concept if the following expressions are valid and respect the stated +semantics.
++++
++ + ++ + + + Single Pass Iterator Requirements (in addition to Incrementable Iterator and Equality Comparable) ++ + + Expression +Return Type +Assertion/Semantics/Pre-/Post-condition ++ ++r +X& +pre: r is dereferenceable; post: +r is dereferenceable or r is +past-the-end ++ a == b +convertible to bool +== is an equivalence relation over +its domain ++ a != b +convertible to bool +!(a == b) ++ + traversal_category<X>::type +Convertible to +single_pass_iterator_tag ++
A class or built-in type X models the Forward Traversal Iterator +concept if the following expressions are valid and respect the stated +semantics.
++++
++ + ++ + + + Forward Traversal Iterator Requirements (in addition to Single Pass Iterator) ++ + + Expression +Return Type +Assertion/Note ++ X u; +X& +note: u may have a +singular value. ++ ++r +X& +r == s and r is +dereferenceable implies +++r == ++s. ++ iterator_traits<X>::difference_type +A signed integral type representing +the distance between iterators ++ + + traversal_category<X>::type +Convertible to +forward_traversal_iterator_tag ++
A class or built-in type X models the Bidirectional Traversal +Iterator concept if the following expressions are valid and respect +the stated semantics.
++++
++ + ++ + + + Bidirectional Traversal Iterator Requirements (in addition to Forward Traversal Iterator) ++ + + Expression +Return Type +Assertion/Semantics/Pre-/Post-condition ++ --r +X& +pre: there exists s such that r +== ++s. post: s is +dereferenceable. --(++r) == r. +--r == --s implies r == s. &r +== &--r. ++ r-- +convertible to const X& +{ X tmp = r; --r; return tmp; } ++ + traversal_category<X>::type +Convertible to +bidirectional_traversal_iterator_tag ++
A class or built-in type X models the Random Access Traversal +Iterator concept if the following expressions are valid and respect +the stated semantics. In the table below, Distance is +iterator_traits<X>::difference_type and n represents a +constant object of type Distance.
++++
++ + ++ + + + + Random Access Traversal Iterator Requirements (in addition to Bidirectional Traversal Iterator) ++ + + Expression +Return Type +Operational Semantics +Assertion/Precondition ++ r += n +X& ++ +{ + Distance m = n; + if (m >= 0) + while (m--) + ++r; + else + while (m++) + --r; + return r; +} +++ + a + n, n + a +X +{ X tmp = a; return +tmp += n; } ++ + r -= n +X& +return r += -n ++ + a - n +X +{ X tmp = a; return +tmp -= n; } ++ + b - a +Distance +a < b ? +distance(a,b) : +-distance(b,a) +pre: there exists a value +n of Distance such +that a + n == b. b == +a + (b - a). ++ a[n] +convertible to T +*(a + n) +pre: a is a readable +iterator ++ a[n] = v +convertible to T +*(a + n) = v +pre: a is a writable +iterator ++ a < b +convertible to bool +b - a > 0 +< is a total ordering +relation ++ a > b +convertible to bool +b < a +> is a total ordering +relation ++ a >= b +convertible to bool +!(a < b) ++ + a <= b +convertible to bool +!(a > b) ++ + + traversal_category<X>::type +Convertible to +random_access_traversal_iterator_tag ++ +
+// lib.iterator.traits, traits and tags +template <class Iterator> struct access_category; +template <class Iterator> struct traversal_category; + +template <class AccessTag, class TraversalTag> +struct iterator_tag : /* appropriate old category or categories */ { + typedef AccessTag access; + typedef TraversalTag traversal; +}; + +struct readable_iterator_tag { }; +struct writable_iterator_tag { }; +struct swappable_iterator_tag { }; +struct readable_writable_iterator_tag + : virtual readable_iterator_tag + , virtual writable_iterator_tag + , virtual swappable_iterator_tag { }; +struct readable_lvalue_iterator_tag { }; +struct writable_lvalue_iterator_tag + : virtual public readable_writable_iterator_tag + , virtual public readable_lvalue_iterator_tag { }; + +struct incrementable_iterator_tag { }; +struct single_pass_iterator_tag : incrementable_iterator_tag { }; +struct forward_traversal_tag : single_pass_iterator_tag { }; +struct bidirectional_traversal_tag : forward_traversal_tag { }; +struct random_access_traversal_tag : bidirectional_traversal_tag { }; + +struct null_category_tag { }; +struct input_output_iterator_tag : input_iterator_tag, output_iterator_tag {}; ++
The iterator_tag class template is an iterator category tag that +encodes the access and traversal tags in addition to being compatible +with the original iterator tags. The iterator_tag class inherits +from one of the original iterator tags according to the following +pseudo-code.
++inherit-category(access-tag, traversal-tag) = + if (access-tag is convertible to readable_lvalue_iterator_tag) { + if (traversal-tag is convertible to random_access_traversal_tag) + return random_access_iterator_tag; + else if (traversal-tag is convertible to bidirectional_traversal_tag) + return bidirectional_iterator_tag; + else if (traversal-tag is convertible to forward_traversal_tag) + return forward_iterator_tag; + else if (traversal-tag is convertible to single_pass_traversal_tag) + if (access-tag is convertible to writable_iterator_tag) + return input_output_iterator_tag; + else + return input_iterator_tag; + else if (access-tag is convertible to writable_iterator_tag) + return output_iterator_tag; + else + return null_category_tag; + } else if (access-tag is convertible to readable_writable_iterator_tag + and traversal-tag is convertible to single_pass_iterator_tag) + return input_output_iterator_tag; + else if (access-tag is convertible to readable_iterator_tag + and traversal-tag is convertible to single_pass_iterator_tag) + return input_iterator_tag; + else if (access-tag is convertible to writable_iterator_tag + and traversal-tag is convertible to incrementable_iterator_tag) + return output_iterator_tag; + else + return null_category_tag; ++
The access_category and traversal_category class templates are +traits classes. For iterators whose +iterator_traits<Iter>::iterator_category type is iterator_tag, +the access_category and traversal_category traits access the +access and traversal member types within iterator_tag. +For iterators whose iterator_traits<Iter>::iterator_category type +is not iterator_tag and instead is a tag convertible to one of the +original tags, the appropriate traversal and access tags is deduced. +The following pseudo-code describes the algorithm.
++access-category(Iterator) = + cat = iterator_traits<Iterator>::iterator_category; + if (cat == iterator_tag<Access,Traversal>) + return Access; + else if (cat is convertible to forward_iterator_tag) { + if (iterator_traits<Iterator>::reference is a const reference) + return readable_lvalue_iterator_tag; + else + return writable_lvalue_iterator_tag; + } else if (cat is convertible to input_iterator_tag) + return readable_iterator_tag; + else if (cat is convertible to output_iterator_tag) + return writable_iterator_tag; + else + return null_category_tag; + +traversal-category(Iterator) = + cat = iterator_traits<Iterator>::iterator_category; + if (cat == iterator_tag<Access,Traversal>) + return Traversal; + else if (cat is convertible to random_access_iterator_tag) + return random_access_traversal_tag; + else if (cat is convertible to bidirectional_iterator_tag) + return bidirectional_traversal_tag; + else if (cat is convertible to forward_iterator_tag) + return forward_traversal_tag; + else if (cat is convertible to input_iterator_tag) + return single_pass_iterator_tag; + else if (cat is convertible to output_iterator_tag) + return incrementable_iterator_tag; + else + return null_category_tag; ++
The following specializations provide the access and traversal +category tags for pointer types.
++template <typename T> +struct access_category<const T*> +{ + typedef readable_lvalue_iterator_tag type; +}; +template <typename T> +struct access_category<T*> +{ + typedef writable_lvalue_iterator_tag type; +}; + +template <typename T> +struct traversal_category<T*> +{ + typedef random_access_traversal_tag type; +}; ++ +