From 9db269bb5b5bfdd269428a4cc3c3ca4fb1a65b2a Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 13 Jul 2003 21:50:30 +0000 Subject: [PATCH] iterator-categories.html is obsolete. [SVN r19103] --- doc/iterator-categories.html | 822 ----------------------------------- 1 file changed, 822 deletions(-) delete mode 100644 doc/iterator-categories.html diff --git a/doc/iterator-categories.html b/doc/iterator-categories.html deleted file mode 100644 index eb76523..0000000 --- a/doc/iterator-categories.html +++ /dev/null @@ -1,822 +0,0 @@ - -Improved Iterator Categories and Requirements - - - -

-
Improved Iterator Categories and Requirements

-

Introduction

The standard iterator categories and requirements are -flawed because they use a single hierarchy of requirements to address two -orthogonal issues: iterator traversal and dereference return -type. The current iterator requirement hierarchy is mainly geared -towards iterator traversal (hence the category names), while requirements that -address dereference return type sneak in at various places. The following table -gives a summary of the current dereference return type 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 Iteratori[n] is convertible to T (which is odd because the - operational semantics say i[n] is equivalent to *(i + n) - which would have a return type of T&)
Table 1. Summary of current dereference return type - requirements.
-

Examples of useful iterators that do not ``fit''

-

Because of the mixing of iterator traversal and dereference return type, 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 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. Also, -vector<bool> is not the only example of useful iterators that do -not return true references: there is the often cited example of disk-based -collections. -

Another example is a counting iterator, an iterator the returns a sequence of -integers when incremented and dereferenced (see boost::counting_iterator). -There are two ways to implement this iterator, 1) make the reference -type be a true reference (a reference to an integer data member of the counting -iterator) or 2) make the reference type be the same as the -value_type. Option 1) runs into the problems discussed in Issue -198, the reference will not be valid after the iterator is destroyed. Option -2) is therefore a better choice, but then we have a counting iterator that -cannot be a random access iterator. -

Yet another example is a transform iterator, an iterator adaptor that applies -a unary function object to the dereference value of the wrapped iterator (see boost::transform_iterator). -For unary functions such as std::times the return type of -operator* clearly needs to be the result_type of the function -object, which is typically not a reference. However, with the current iterator -requirements, if you wrap int* with a transform iterator, you do not -get a random access iterator as expected, but an input iterator. -

A fourth 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 -std::input_iterator_tag, which means that, strictly speaking, you could -not use these iterators with algorithms like std::min_element(). As a -temporary solution, we introduced the concept Multi-Pass -Input Iterator to describe the vertex and edge descriptors, but as the -design notes for 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: -

-

Proposal for new iterator categories and requirements

The iterator -requirements should be separated into two hierarchies. One set of concepts -handles the return type semantics: -The other set of concepts handles iterator -traversal: - - -

The current Input Iterator and Output Iterator requirements will -continue to be used as is. Note that Input Iterator implies Readable -Iterator and Output Iterator implies Writable Iterator.

- -

Note: we considered defining a Single-Pass Iterator, which could be -combined with Readable or Writable Iterator to replace the Input and -Output Iterator requirements. We rejected this idea because there are -several differences between Input and Output Iterators that make it -hard to merge them: Input Iterator requires Equality Comparable while -Output Iterator does not and Input Iterator requires Assignable while -Output Iterator does not.

- -

New category tags and traits classes

- -

The new iterator categories will require new tag classes.

- -
namespace std {
-
-  // Returns Category Tags
-  struct readable_iterator_tag { };
-  struct writable_iterator_tag { };
-  struct swappable_iterator_tag { };
-  struct mutable_lvalue_iterator_tag : virtual public writable_iterator_tag,
-    virtual public readable_iterator_tag { };
-  struct constant_lvalue_iterator_tag : public readable_iterator_tag { };
-
-  // Traversal Category Tags
-  struct input_traversal_tag { };
-  struct output_traversal_tag { };
-  struct forward_traversal_tag { };
-  struct bidirectional_traversal_tag : public forward_traversal_tag { };
-  struct random_access_traversal_tag : public bidirectional_traversal_tag { };
-
-}
-
- -

Access to the return and traversal tags will be through the -following two traits classes, which have a member typedef named -type that provides the tag type. We explain the -definitions of these classes later.

- -
-  template <typename Iterator>
-  struct return_category; // contains: typedef ... type;
-
-  template <typename Iterator>
-  struct traversal_category; // contains: typedef ... type;
-
- -

We want it to be convenient for programmers to create iterators -that satisfy both the old and new iterator requirements. Therefore -the following class is provided as a way to create tags for use as the -old iterator_category typedef within -iterator_traits. - -

namespace std {
-  template <class ReturnTag, class TraversalTag>
-  struct iterator_tag : cvt_iterator_category<ReturnTag, TraversalTag>::type
-  {
-    typedef ReturnTag returns;
-    typedef TraversalTag traversal;
-  };
-
- -

The cvt_iterator_category template computes the -appropriate old iterator category based on the return and traversal -category.

- -
namespace std {
-  template <class RC, class TC>
-  struct cvt_iterator_category
-  {
-    // Pseudo-code, <= means inherits or same type
-    if (RC <= constant_lvalue_iterator_tag || RC <= mutable_lvalue_iterator_tag) {
-      if (TC <= random_access_traversal_tag)
-        typedef random_access_iterator_tag type;
-      else if (TC <= bidirectional_traversal_tag)
-        typedef bidirectional_iterator_tag type;
-      else if (TC <= forward_traversal_tag)
-        typedef forward_iterator_tag type;
-      else
-        error;
-   } else if (RC <= readable_iterator_tag && RC <= input_traversal_tag)
-     typedef input_iterator_tag type;
-   else if (RC <= writable_iterator_tag && output_traversal_tag)
-     typedef output_iterator_tag type;
-   else
-     error;
-  };
-}
-
- -

The following is an example of a new iterator class using the -iterator_tag class to create its iterator_category -member typedef.

- -
-struct my_iterator {
-  typedef std::iterator_tag<std::readable_iterator_tag, 
-    std::random_access_traversal_tag> iterator_category;
-  ...
-};
-
- -We also want old iterators to work with new algorithms, that is, -algorithms that use the new iterator categories. We facilitate this by -defining the return_category and traversal_category -in such a way as they can be used with both old and new iterators. -For old iterators, the appropriate return and traversal categories are -computed based on the old iterator category. For new iterators, the -return and traversal tags are extracted from within the -iterator_category tag. - - -
-  template <typename Iterator>
-  class return_category
-  {
-    // Pseudo-code
-    typedef iterator_traits<Iterator>::iterator_category tag;
-    typedef iterator_traits<Iterator>::value_type T;
-  public:
-    if (exists(tag::returns)) // must be a new iterator
-      typedef tag::returns type;
-    else if (tag <= forward_iterator_tag) {
-      if (is-const(T))
-        typedef constant_lvalue_iterator_tag type;
-      else
-        typedef mutable_lvalue_iterator_tag type;
-    } else if (tag <= input_iterator_tag)
-      typedef readable_iterator_tag type;
-    else if (tag <= output_iterator_tag)
-      typedef writable_iterator_tag type;
-    else
-      error;
-  };
-
-  template <typename T>
-  struct return_category<T*>
-  {
-    // Pseudo-code
-    if (is-const(T))
-      typedef boost::constant_lvalue_iterator_tag type;
-    else
-      typedef boost::mutable_lvalue_iterator_tag type;
-  };
-
-  template <typename Iterator>
-  class traversal_category
-  {
-    typedef iterator_traits<Iterator>::iterator_category tag;
-  public:
-    // Pseudo-code
-    if (exists(tag::traversal)) // must be a new iterator
-      typedef tag::traversal type;
-    else if (tag <= random_access_iterator_tag)
-      typedef random_access_traversal_tag type;
-    else if (tag <= bidirectional_iterator_tag)
-      typedef bidirectional_traversal_tag type;
-    else if (tag <= is_forward_iterator_tag)
-      typedef forward_traversal_tag type;
-    else if (tag <= input_iterator_tag)
-      typedef input_traversal_tag type;
-    else if (tag <= out_iterator_tag)
-      typedef output_traversal_tag type;
-    else
-      error;
-  };
-
-  template <typename T>
-  struct traversal_category<T*>
-  {
-    typedef random_access_traversal_tag type;
-  };
-
- -

Impact on the Standard Algorithms

- -

Many of the standard algorithms place more requirements than -necessary on their iterator parameters due to the coarseness of the -current iterator categories. By using the new iterator categories a -better fit can be achieved, thereby increasing the reusability of the -algorithms. These changes will not affect user-code, though they will -require changes by standard implementers: dispatching should be based -on the new categories, and in places return values may need to be -handled more carefully. In particular, uses of std::swap() -will need to be replaced with std::iter_swap(), and -std::iter_swap() will need to call std::swap().

- -

-

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
AlgorithmRequirement Change
find_endForward Iterator
-> Forward Traversal Iterator and - Readable Iterator
find_first_of
adjacent_find
search
search_n
rotate_copy
lower_bound
upper_bound
equal_range
binary_search
min_element
max_element
iter_swapForward Iterator
-> Swappable Iterator
fillForward Iterator
-> Forward Traversal Iterator and - Writable Iterator
generate
swap_rangesForward Iterator
-> Forward Traversal Iterator and - Swappable Iterator
rotate
replaceForward Iterator
-> Forward Traversal Iterator - and
Readable Iterator and Writable Iterator
replace_if
remove
remove_if
unique
reverseBidirectional Iterator
-> Bidirectional Traversal - Iterator and Swappable Iterator
partition
copy_backwardsBidirectional Iterator
-> Bidirectional Traversal Iterator and - Readable Iterator
Bidirectional Iterator
-> Bidirectional - Traversal Iterator and Writable Iterator
next_permutationBidirectional Iterator
-> Bidirectional Traversal - Iterator and
Swappable Iterator and Readable Iterator
prev_permutation
stable_partitionBidirectional Iterator
-> Bidirectional Traversal - Iterator and
Readable Iterator and Writable Iterator
inplace_merge
reverse_copyBidirectional Iterator
-> Bidirectional Traversal Iterator and - Readable Iterator
random_shuffleRandom Access Iterator
-> Random Access Traversal - Iterator and Swappable Iterator
sort
stable_sort
partial_sort
nth_element
push_heap
pop_heap
make_heap
sort_heap
Table 2. Requirement changes for standard - algorithms.
-

The New Iterator Requirements

-

Notation

- - - - - - - - - - - - - -
XThe iterator type.
TThe value type of X, i.e., - std::iterator_traits<X>::value_type.
x, yAn object of type X.
tAn object of type T.
-

-


- -

Readable Iterator

A Readable -Iterator is an iterator that dereferences to produce an rvalue that is -convertible to the value_type of the iterator. -

Associated Types

- - - - - - - - - - - - - -
Value typestd::iterator_traits<X>::value_typeThe type of the objects pointed to by the iterator.
Reference typestd::iterator_traits<X>::referenceThe return type of dereferencing the iterator. This type must be - convertible to T.
Return Categorystd::return_category<X>::typeA type convertible to std::readable_iterator_tag -
-

Refinement of

Copy -Constructible -

Valid expressions

- - - - - - - - - - - - - - - - -
NameExpressionType requirementsReturn type
Dereference*x std::iterator_traits<X>::reference
Member accessx->mT is a type with a member named m.If m is a data member, the type of m. If m - is a member function, the return type of m.
-

-


- -

Writable Iterator

A Writable -Iterator is an iterator that can be used to store a value using the -dereference-assignment expression. -

Definitions

If x is an Writable Iterator of type X, -then the expression *x = a; stores the value a into -x. Note that operator=, like other C++ functions, may be -overloaded; it may, in fact, even be a template function. In general, then, -a may be any of several different types. A type A belongs to -the set of value types of X if, for an object a of type -A, *x = a; is well-defined and does not require performing any -non-trivial conversions on a. -

Associated Types

- - - - - -
Return Categorystd::return_category<X>::typeA type convertible to std::writable_iterator_tag -
-

Refinement of

Copy -Constructible -

Valid expressions

- - - - - - - - - -
NameExpressionReturn type
Dereference assignment*x = aunspecified
-

-


- -

Swappable Iterator

A Swappable -Iterator is an iterator whose dereferenced values can be swapped. -

Note: the requirements for Swappable Iterator are dependent on the issues -surrounding std::swap() being resolved. Here we assume that the issue -will be resolved by allowing the overload of std::swap() for -user-defined types. -

Note: Readable Iterator and Writable Iterator combined implies Swappable -Iterator because of the fully templated std::swap(). However, Swappable -Iterator does not imply Readable Iterator nor Writable Iterator. -

Associated Types

- - - - - -
Return Categorystd::return_category<X>::typeA type convertible to std::swappable_iterator_tag -
-

Valid expressions

Of the two valid expressions listed below, only one -OR the other is required. If std::iter_swap() is overloaded for -X then std::swap() is not required. If -std::iter_swap() is not overloaded for X then the default -(fully templated) version is used, which will call std::swap() (this -means changing the current requirements for std::iter_swap()). -

- - - - - - - - - - - - - -
NameExpressionReturn type
Iterator Swapstd::iter_swap(x, y)void
Dereference and Swapstd::swap(*x, *y)void
-

-


- -

Constant Lvalue Iterator

A -Constant Lvalue Iterator is an iterator that dereferences to produce a const -reference to the pointed-to object, i.e., the associated reference type -is const T&. Changing the value of or destroying an iterator that -models Constant Lvalue Iterator does not invalidate pointers and references -previously obtained from that iterator. -

Refinement of

Readable -Iterator -

Associated Types

- - - - - - - - - -
Reference typestd::iterator_traits<X>::referenceThe return type of dereferencing the iterator, which must be const - T&.
Return Categorystd::return_category<X>::typeA type convertible to std::constant_lvalue_iterator_tag -
-

-


- -

Mutable Lvalue Iterator

A -Mutable Lvalue Iterator is an iterator that dereferences to produce a reference -to the pointed-to object. The associated reference type is -T&. Changing the value of or destroying an iterator that models -Mutable Lvalue Iterator does not invalidate pointers and references previously -obtained from that iterator. -

Refinement of

Readable -Iterator, Writable -Iterator, and Swappable -Iterator. -

Associated Types

- - - - - - - - - -
Reference typestd::iterator_traits<X>::referenceThe return type of dereferencing the iterator, which must be - T&.
Return Categorystd::return_category<X>::typeA type convertible to std::mutable_lvalue_iterator_tag -
-

-


- -

Forward Traversal Iterator -

The Forward Iterator is an iterator that can be incremented. Also, it is -permissible to make multiple passes through the iterator's range. -

Refinement of

Copy -Constructible, Assignable, Default -Constructible, and Equality -Comparable -

Associated types

- - - - - - - - - -
Difference Typestd::iterator_traits<X>::difference_typeA signed integral type used for representing distances between - iterators that point into the same range.
Traversal Categorystd::traversal_category<X>::typeA type convertible to std::forward_traversal_tag -
-

Valid expressions

- - - - - - - - - - - - - - - - -
NameExpressionType requirementsReturn type
Preincrement++i X&
Postincrementi++ convertible to const X&
-

-


- -

Bidirectional Traversal -Iterator

An iterator that can be incremented and decremented. -

Refinement of

Forward -Traversal Iterator -

Associated types

- - - - - -
Traversal Categorystd::traversal_category<X>::typeA type convertible to std::bidirectional_traversal_tag -
-

Valid expressions

- - - - - - - - - - - - - - - - -
NameExpressionType requirementsReturn type
Predecrement--i X&
Postdecrementi-- convertible to const X&
-

-


- -

Random Access Traversal -Iterator

An iterator that provides constant-time methods for moving forward -and backward in arbitrary-sized steps. -

Refinement of

Bidirectional -Traversal Iterator and Less Than -Comparable where < is a total ordering -

Associated types

- - - - - -
Traversal Categorystd::traversal_category<X>::typeA type convertible to std::random_access_traversal_tag -
-

Valid expressions

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameExpressionType requirementsReturn type
Iterator additioni += n X&
Iterator additioni + n or n + i X
Iterator subtractioni -= n X&
Iterator subtractioni - n X
Differencei - j std::iterator_traits<X>::difference_type
Element operatori[n]X must also be a model of Readable - Iterator. std::iterator_traits<X>::reference
Element assignmenti[n] = tX must also be a model of Writable - Iterator.unspecified
-

-


-