forked from boostorg/iterator
new file
[SVN r203]
This commit is contained in:
740
doc/iterator-categories.html
Normal file
740
doc/iterator-categories.html
Normal file
@@ -0,0 +1,740 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<!-- saved from url=(0022)http://internet.e-mail --><HTML><HEAD><TITLE>Improved Iterator Categories and Requirements</TITLE>
|
||||
<META content="text/html; charset=windows-1252" http-equiv=Content-Type>
|
||||
<META content="MSHTML 5.00.2919.6307" name=GENERATOR></HEAD>
|
||||
<BODY bgColor=#ffffff>
|
||||
<H1>
|
||||
<CENTER>Improved Iterator Categories and Requirements</CENTER></H1>
|
||||
<H2>Introduction</H2>The standard iterator categories and requirements are
|
||||
flawed because they use a single hierarchy of requirements to address two
|
||||
orthogonal issues: <B><I>iterator traversal</I></B> and <B><I>dereference return
|
||||
type</I></B>. 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.
|
||||
<P>
|
||||
<CENTER>
|
||||
<TABLE border=1>
|
||||
<TBODY>
|
||||
<TR>
|
||||
<TD>Output Iterator</TD>
|
||||
<TD><TT>*i = a</TT> </TD></TR>
|
||||
<TR>
|
||||
<TD>Input Iterator</TD>
|
||||
<TD><TT>*i</TT> is convertible to <TT>T</TT></TD></TR>
|
||||
<TR>
|
||||
<TD>Forward Iterator</TD>
|
||||
<TD><TT>*i</TT> is <TT>T&</TT> (or <TT>const T&</TT> once <A
|
||||
href="http://anubis.dkuug.dk/JTC1/SC22/WG21/docs/lwg-active.html#200">issue
|
||||
200</A> is resolved)</TD></TR>
|
||||
<TR>
|
||||
<TD>Random Access Iterator</TD>
|
||||
<TD><TT>i[n]</TT> is convertible to <TT>T</TT> (which is odd because the
|
||||
operational semantics say <TT>i[n]</TT> is equivalent to <TT>*(i + n)</TT>
|
||||
which would have a return type of <TT>T&</TT>) </TD></TR><A name=table:2>
|
||||
<CAPTION><B>Table 1.</B> Summary of current dereference return type
|
||||
requirements.</CAPTION></A></TABLE></CENTER>
|
||||
<H2>Examples of useful iterators that do not ``fit''</H2>
|
||||
<P>Because of the mixing of iterator traversal and dereference return type, many
|
||||
useful iterators can not be appropriately categorized. For example,
|
||||
<TT>vector<bool>::iterator</TT> is almost a random access iterator, but
|
||||
the return type is not <TT>bool&</TT> (see <A
|
||||
href="http://anubis.dkuug.dk/JTC1/SC22/WG21/docs/lwg-active.html#96">issue
|
||||
96</A> 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
|
||||
<TT>random_access_iterator_tag</TT> as its <TT>iterator_category</TT>. Also,
|
||||
<TT>vector<bool></TT> is not the only example of useful iterators that do
|
||||
not return true references: there is the often cited example of disk-based
|
||||
collections.
|
||||
<P>Another example is a counting iterator, an iterator the returns a sequence of
|
||||
integers when incremented and dereferenced (see <A
|
||||
href="http://www.boost.org/libs/utility/counting_iterator.htm"><TT>boost::counting_iterator</TT></A>).
|
||||
There are two ways to implement this iterator, 1) make the <TT>reference</TT>
|
||||
type be a true reference (a reference to an integer data member of the counting
|
||||
iterator) or 2) make the <TT>reference</TT> type be the same as the
|
||||
<TT>value_type</TT>. Option 1) runs into the problems discussed in <A
|
||||
href="http://anubis.dkuug.dk/JTC1/SC22/WG21/docs/lwg-active.html#198">Issue
|
||||
198</A>, 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.
|
||||
<P>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 <A
|
||||
href="http://www.boost.org/libs/utility/transform_iterator.htm"><TT>boost::transform_iterator</TT></A>).
|
||||
For unary functions such as <TT>std::times</TT> the return type of
|
||||
<TT>operator*</TT> clearly needs to be the <TT>result_type</TT> of the function
|
||||
object, which is typically not a reference. However, with the current iterator
|
||||
requirements, if you wrap <TT>int*</TT> with a transform iterator, you do not
|
||||
get a random access iterator as expected, but an input iterator.
|
||||
<P>A fourth example is found in the vertex and edge iterators of the <A
|
||||
href="http://www.boost.org/libs/graph/doc/table_of_contents.html">Boost Graph
|
||||
Library</A>. 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
|
||||
<TT>std::input_iterator_tag</TT>, which means that, strictly speaking, you could
|
||||
not use these iterators with algorithms like <TT>std::min_element()</TT>. As a
|
||||
temporary solution, we introduced the concept <A
|
||||
href="http://www.boost.org/libs/utility/MultiPassInputIterator.html">Multi-Pass
|
||||
Input Iterator</A> to describe the vertex and edge descriptors, but as the
|
||||
design notes for concept suggest, a better solution is needed.
|
||||
<P>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:
|
||||
<UL>
|
||||
<LI>Iterators are often miss-categorized.
|
||||
<LI>Algorithm requirements are more strict than necessary, because they can
|
||||
not separate out the need for random-access from the need for a true reference
|
||||
return type. </LI></UL>
|
||||
<H2>Proposal for new iterator categories and requirements</H2>The iterator
|
||||
requirements should be separated into two hierarchies. One set of concepts
|
||||
handles the return type semantics:
|
||||
<UL>
|
||||
<LI><A
|
||||
href="file:///C:/WINDOWS/TEMP/iterator-categories.html#concept:ReadableIterator">Readable
|
||||
Iterator</A>
|
||||
<LI><A
|
||||
href="file:///C:/WINDOWS/TEMP/iterator-categories.html#concept:WritableIterator">Writable
|
||||
Iterator</A>
|
||||
<LI><A
|
||||
href="file:///C:/WINDOWS/TEMP/iterator-categories.html#concept:SwappableIterator">Swappable
|
||||
Iterator</A>
|
||||
<LI><A
|
||||
href="file:///C:/WINDOWS/TEMP/iterator-categories.html#concept:ConstantLvalueIterator">Constant
|
||||
Lvalue Iterator</A>
|
||||
<LI><A
|
||||
href="file:///C:/WINDOWS/TEMP/iterator-categories.html#concept:MutableLvalueIterator">Mutable
|
||||
Lvalue Iterator</A> </LI></UL>The other set of concepts handles iterator
|
||||
traversal:
|
||||
<UL>
|
||||
<LI><A
|
||||
href="file:///C:/WINDOWS/TEMP/iterator-categories.html#concept:ForwardTraversalIterator">Forward
|
||||
Traversal Iterator</A>
|
||||
<LI><A
|
||||
href="file:///C:/WINDOWS/TEMP/iterator-categories.html#concept:BidirectionalTraversalIterator">Bidirectional
|
||||
Traversal Iterator</A>
|
||||
<LI><A
|
||||
href="file:///C:/WINDOWS/TEMP/iterator-categories.html#concept:RandomAccessTraversalIterator">Random
|
||||
Access Traversal Iterator</A> </LI></UL>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.
|
||||
<P>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.
|
||||
<H3>New categories and traits classes</H3>Each of the new iterator requirements
|
||||
will need a category tag. <PRE>namespace std {
|
||||
|
||||
// Return Type Categories
|
||||
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 Categories
|
||||
struct forward_traversal_tag { };
|
||||
struct bidirectional_traversal_tag : public forward_traversal_tag { };
|
||||
struct random_access_traversal_tag : public bidirectional_traversal_tag { };
|
||||
|
||||
}
|
||||
</PRE>And there will need to be a way to access these category tags using a
|
||||
traits mechanism. Adding new typedefs to <TT>std::iterator_traits</TT> is not an
|
||||
acceptable solution because that would break every existing iterator. Instead,
|
||||
we propose two new traits classes. It is important that these traits classes are
|
||||
<B>backward compatible</B>, that is, they should work with any iterator for
|
||||
which there is a valid definition of <TT>std::iterator_traits</TT>. This can be
|
||||
accomplished by making the default behavior of the traits classes map the
|
||||
<TT>iterator_category</TT> of the iterator to the appropriate return or
|
||||
traversal category. For new iterators, either specializations of these traits
|
||||
classes can be defined, or the iterator can provide nested typedefs, and inherit
|
||||
from <TT>new_iterator_base</TT> (which is just a signal to the traits class that
|
||||
it is a new iterator). As with <TT>std::iterator_traits</TT>, specializations
|
||||
for <TT>T*</TT> are provided. <PRE>namespace std {
|
||||
|
||||
struct new_iterator_base { };
|
||||
|
||||
template <typename Iterator>
|
||||
struct return_category
|
||||
{
|
||||
<B><I>// Pseudo-code</I></B>
|
||||
if (Iterator inherits from new_iterator_base) {
|
||||
typedef typename Iterator::return_category type;
|
||||
} else {
|
||||
typedef std::iterator_traits<Iterator> OldTraits;
|
||||
typedef typename OldTraits::iterator_category Cat;
|
||||
if (Cat inherits from std::forward_iterator_tag)
|
||||
if (is-const(T))
|
||||
typedef boost::constant_lvalue_iterator_tag type;
|
||||
else
|
||||
typedef boost::mutable_lvalue_iterator_tag type;
|
||||
else if (Cat inherits from std::input_iterator_tag)
|
||||
typedef boost::readable_iterator_tag type;
|
||||
else if (Cat inherits from std::output_iterator_tag)
|
||||
typedef boost::writable_iterator_tag type;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct return_category<T*>
|
||||
{
|
||||
<B><I>// Pseudo-code</I></B>
|
||||
if (is-const(T))
|
||||
typedef boost::constant_lvalue_iterator_tag type;
|
||||
else
|
||||
typedef boost::mutable_lvalue_iterator_tag type;
|
||||
};
|
||||
|
||||
template <typename Iterator>
|
||||
struct traversal_category
|
||||
{
|
||||
<B><I>// Pseudo-code</I></B>
|
||||
if (Iterator inherits from new_iterator_base) {
|
||||
typedef typename Iterator::traversal_category type;
|
||||
} else {
|
||||
typedef std::iterator_traits<Iterator> OldTraits;
|
||||
typedef typename OldTraits::iterator_category Cat;
|
||||
|
||||
if (Cat inherits from std::random_access_iterator_tag)
|
||||
typedef boost::random_access_traversal_tag type;
|
||||
else if (Cat inherits from std::bidirectional_iterator_tag)
|
||||
typedef boost::bidirectional_traversal_tag type;
|
||||
else if (Cat inherits from std::forward_iterator_tag)
|
||||
typedef boost::forward_traversal_tag type;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct traversal_category<T*>
|
||||
{
|
||||
typedef boost::random_access_traversal_tag type;
|
||||
};
|
||||
|
||||
}
|
||||
</PRE>
|
||||
<H2>Impact on the Standard Algorithms</H2>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 <TT>std::swap()</TT> will need to be replaced with
|
||||
<TT>std::iter_swap()</TT>, and <TT>std::iter_swap()</TT> will need to call
|
||||
<TT>std::swap()</TT>.
|
||||
<P>
|
||||
<CENTER>
|
||||
<TABLE border=1>
|
||||
<TBODY>
|
||||
<TR>
|
||||
<TH>Algorithm</TH>
|
||||
<TH>Requirement Change</TH></TR>
|
||||
<TR>
|
||||
<TD>find_end</TD>
|
||||
<TD rowSpan=12>Forward Iterator<BR>-> Forward Traversal Iterator and
|
||||
Readable Iterator </TD></TR>
|
||||
<TR>
|
||||
<TD>find_first_of</TD></TR>
|
||||
<TR>
|
||||
<TD>adjacent_find</TD></TR>
|
||||
<TR>
|
||||
<TD>search</TD></TR>
|
||||
<TR>
|
||||
<TD>search_n</TD></TR>
|
||||
<TR>
|
||||
<TD>rotate_copy</TD></TR>
|
||||
<TR>
|
||||
<TD>lower_bound</TD></TR>
|
||||
<TR>
|
||||
<TD>upper_bound</TD></TR>
|
||||
<TR>
|
||||
<TD>equal_range</TD></TR>
|
||||
<TR>
|
||||
<TD>binary_search</TD></TR>
|
||||
<TR>
|
||||
<TD>min_element</TD></TR>
|
||||
<TR>
|
||||
<TD>max_element</TD></TR>
|
||||
<TR>
|
||||
<TD>iter_swap</TD>
|
||||
<TD>Forward Iterator<BR>-> Swappable Iterator </TD></TR>
|
||||
<TR>
|
||||
<TD>fill</TD>
|
||||
<TD rowSpan=2>Forward Iterator<BR>-> Forward Traversal Iterator and
|
||||
Writable Iterator </TD></TR>
|
||||
<TR>
|
||||
<TD>generate</TD></TR>
|
||||
<TR>
|
||||
<TD>swap_ranges</TD>
|
||||
<TD rowSpan=2>Forward Iterator<BR>-> Forward Traversal Iterator and
|
||||
Swappable Iterator </TD></TR>
|
||||
<TR>
|
||||
<TD>rotate</TD></TR>
|
||||
<TR>
|
||||
<TD>replace</TD>
|
||||
<TD rowSpan=5>Forward Iterator<BR>-> Forward Traversal Iterator
|
||||
and<BR>Readable Iterator and Writable Iterator </TD>
|
||||
<TR>
|
||||
<TD>replace_if</TD></TR>
|
||||
<TR>
|
||||
<TD>remove</TD></TR>
|
||||
<TR>
|
||||
<TD>remove_if</TD></TR>
|
||||
<TR>
|
||||
<TD>unique</TD></TR>
|
||||
<TR>
|
||||
<TD>reverse</TD>
|
||||
<TD rowSpan=2>Bidirectional Iterator<BR>-> Bidirectional Traversal
|
||||
Iterator and Swappable Iterator </TD></TR>
|
||||
<TR>
|
||||
<TD>partition</TD></TR>
|
||||
<TR>
|
||||
<TD>copy_backwards</TD>
|
||||
<TD>Bidirectional Iterator<BR>-> Bidirectional Traversal Iterator and
|
||||
Readable Iterator<BR>Bidirectional Iterator<BR>-> Bidirectional
|
||||
Traversal Iterator and Writable Iterator </TD></TR>
|
||||
<TR>
|
||||
<TD>next_permutation</TD>
|
||||
<TD rowSpan=2>Bidirectional Iterator<BR>-> Bidirectional Traversal
|
||||
Iterator and <BR>Swappable Iterator and Readable Iterator </TD>
|
||||
<TR>
|
||||
<TD>prev_permutation</TD></TR>
|
||||
<TR>
|
||||
<TD>stable_partition</TD>
|
||||
<TD rowSpan=2>Bidirectional Iterator<BR>-> Bidirectional Traversal
|
||||
Iterator and <BR>Readable Iterator and Writable Iterator </TD>
|
||||
<TR>
|
||||
<TD>inplace_merge</TD></TR>
|
||||
<TR>
|
||||
<TD>reverse_copy</TD>
|
||||
<TD>Bidirectional Iterator<BR>-> Bidirectional Traversal Iterator and
|
||||
Readable Iterator </TD></TR>
|
||||
<TR>
|
||||
<TD>random_shuffle</TD>
|
||||
<TD rowSpan=9>Random Access Iterator<BR>-> Random Access Traversal
|
||||
Iterator and Swappable Iterator </TD></TR>
|
||||
<TR>
|
||||
<TD>sort</TD></TR>
|
||||
<TR>
|
||||
<TD>stable_sort</TD></TR>
|
||||
<TR>
|
||||
<TD>partial_sort</TD></TR>
|
||||
<TR>
|
||||
<TD>nth_element</TD></TR>
|
||||
<TR>
|
||||
<TD>push_heap</TD></TR>
|
||||
<TR>
|
||||
<TD>pop_heap</TD></TR>
|
||||
<TR>
|
||||
<TD>make_heap</TD></TR>
|
||||
<TR>
|
||||
<TD>sort_heap</TD></TR><A name=table:2>
|
||||
<CAPTION><B>Table 2.</B> Requirement changes for standard
|
||||
algorithms.</CAPTION></A></TABLE></CENTER>
|
||||
<H2>The New Iterator Requirements</H2>
|
||||
<H3>Notation</H3>
|
||||
<TABLE>
|
||||
<TBODY>
|
||||
<TR>
|
||||
<TD><TT>X</TT></TD>
|
||||
<TD>The iterator type.</TD></TR>
|
||||
<TR>
|
||||
<TD><TT>T</TT></TD>
|
||||
<TD>The value type of <TT>X</TT>, i.e.,
|
||||
<TT>std::iterator_traits<X>::value_type</TT>.</TD></TR>
|
||||
<TR>
|
||||
<TD><TT>x</TT>, <TT>y</TT></TD>
|
||||
<TD>An object of type <TT>X</TT>.</TD></TR>
|
||||
<TR>
|
||||
<TD><TT>t</TT></TD>
|
||||
<TD>An object of type <TT>T</TT>.</TD></TR></TBODY></TABLE>
|
||||
<P>
|
||||
<HR>
|
||||
<!--------------------------------------------------------------------------->
|
||||
<H3><A name=concept:ReadableIterator></A>Readable Iterator </H3>A Readable
|
||||
Iterator is an iterator that dereferences to produce an rvalue that is
|
||||
convertible to the <TT>value_type</TT> of the iterator.
|
||||
<H3>Associated Types</H3>
|
||||
<TABLE border=1>
|
||||
<TBODY>
|
||||
<TR>
|
||||
<TD>Value type</TD>
|
||||
<TD><TT>std::iterator_traits<X>::value_type</TT></TD>
|
||||
<TD>The type of the objects pointed to by the iterator.</TD></TR>
|
||||
<TR>
|
||||
<TD>Reference type</TD>
|
||||
<TD><TT>std::iterator_traits<X>::reference</TT></TD>
|
||||
<TD>The return type of dereferencing the iterator. This type must be
|
||||
convertible to <TT>T</TT>. </TD></TR>
|
||||
<TR>
|
||||
<TD>Return Category</TD>
|
||||
<TD><TT>std::return_category<X>::type</TT></TD>
|
||||
<TD>A type convertible to <TT>std::readable_iterator_tag</TT>
|
||||
</TD></TR></TBODY></TABLE>
|
||||
<H3>Refinement of</H3><A
|
||||
href="http://www.boost.org/libs/utility/CopyConstructible.html">Copy
|
||||
Constructible</A>
|
||||
<H3>Valid expressions</H3>
|
||||
<TABLE border=1>
|
||||
<TBODY>
|
||||
<TR>
|
||||
<TH>Name</TH>
|
||||
<TH>Expression</TH>
|
||||
<TH>Type requirements</TH>
|
||||
<TH>Return type</TH></TR>
|
||||
<TR>
|
||||
<TD>Dereference</TD>
|
||||
<TD><TT>*x</TT></TD>
|
||||
<TD> </TD>
|
||||
<TD><TT>std::iterator_traits<X>::reference</TT></TD></TR>
|
||||
<TR>
|
||||
<TD>Member access</TD>
|
||||
<TD><TT>x->m</TT></TD>
|
||||
<TD><TT>T</TT> is a type with a member named <TT>m</TT>.</TD>
|
||||
<TD>If <TT>m</TT> is a data member, the type of <TT>m</TT>. If <TT>m</TT>
|
||||
is a member function, the return type of <TT>m</TT>. </TD></TR></TBODY></TABLE>
|
||||
<P>
|
||||
<HR>
|
||||
<!--------------------------------------------------------------------------->
|
||||
<H3><A name=concept:WritableIterator></A>Writable Iterator </H3>A Writable
|
||||
Iterator is an iterator that can be used to store a value using the
|
||||
dereference-assignment expression.
|
||||
<H3>Definitions</H3>If <TT>x</TT> is an Writable Iterator of type <TT>X</TT>,
|
||||
then the expression <TT>*x = a;</TT> stores the value <TT>a</TT> into
|
||||
<TT>x</TT>. Note that <TT>operator=</TT>, like other C++ functions, may be
|
||||
overloaded; it may, in fact, even be a template function. In general, then,
|
||||
<TT>a</TT> may be any of several different types. A type <TT>A</TT> belongs to
|
||||
the <I>set of value types</I> of <TT>X</TT> if, for an object <TT>a</TT> of type
|
||||
<TT>A</TT>, <TT>*x = a;</TT> is well-defined and does not require performing any
|
||||
non-trivial conversions on <TT>a</TT>.
|
||||
<H3>Associated Types</H3>
|
||||
<TABLE border=1>
|
||||
<TBODY>
|
||||
<TR>
|
||||
<TD>Return Category</TD>
|
||||
<TD><TT>std::return_category<X>::type</TT></TD>
|
||||
<TD>A type convertible to <TT>std::writable_iterator_tag</TT>
|
||||
</TD></TR></TBODY></TABLE>
|
||||
<H3>Refinement of</H3><A
|
||||
href="http://www.boost.org/libs/utility/CopyConstructible.html">Copy
|
||||
Constructible</A>
|
||||
<H3>Valid expressions</H3>
|
||||
<TABLE border=1>
|
||||
<TBODY>
|
||||
<TR>
|
||||
<TH>Name</TH>
|
||||
<TH>Expression</TH>
|
||||
<TH>Return type</TH></TR>
|
||||
<TR>
|
||||
<TD>Dereference assignment</TD>
|
||||
<TD><TT>*x = a</TT></TD>
|
||||
<TD>unspecified</TD></TR></TBODY></TABLE>
|
||||
<P>
|
||||
<HR>
|
||||
<!--------------------------------------------------------------------------->
|
||||
<H3><A name=concept:SwappableIterator></A>Swappable Iterator </H3>A Swappable
|
||||
Iterator is an iterator whose dereferenced values can be swapped.
|
||||
<P>Note: the requirements for Swappable Iterator are dependent on the issues
|
||||
surrounding <TT>std::swap()</TT> being resolved. Here we assume that the issue
|
||||
will be resolved by allowing the overload of <TT>std::swap()</TT> for
|
||||
user-defined types.
|
||||
<P>Note: Readable Iterator and Writable Iterator combined implies Swappable
|
||||
Iterator because of the fully templated <TT>std::swap()</TT>. However, Swappable
|
||||
Iterator does not imply Readable Iterator nor Writable Iterator.
|
||||
<H3>Associated Types</H3>
|
||||
<TABLE border=1>
|
||||
<TBODY>
|
||||
<TR>
|
||||
<TD>Return Category</TD>
|
||||
<TD><TT>std::return_category<X>::type</TT></TD>
|
||||
<TD>A type convertible to <TT>std::swappable_iterator_tag</TT>
|
||||
</TD></TR></TBODY></TABLE>
|
||||
<H3>Valid expressions</H3>Of the two valid expressions listed below, only one
|
||||
<B>OR</B> the other is required. If <TT>std::iter_swap()</TT> is overloaded for
|
||||
<TT>X</TT> then <TT>std::swap()</TT> is not required. If
|
||||
<TT>std::iter_swap()</TT> is not overloaded for <TT>X</TT> then the default
|
||||
(fully templated) version is used, which will call <TT>std::swap()</TT> (this
|
||||
means changing the current requirements for <TT>std::iter_swap()</TT>).
|
||||
<P>
|
||||
<TABLE border=1>
|
||||
<TBODY>
|
||||
<TR>
|
||||
<TH>Name</TH>
|
||||
<TH>Expression</TH>
|
||||
<TH>Return type</TH></TR>
|
||||
<TR>
|
||||
<TD>Iterator Swap</TD>
|
||||
<TD><TT>std::iter_swap(x, y)</TT></TD>
|
||||
<TD>void</TD></TR>
|
||||
<TR>
|
||||
<TD>Dereference and Swap</TD>
|
||||
<TD><TT>std::swap(*x, *y)</TT></TD>
|
||||
<TD>void</TD></TR></TBODY></TABLE>
|
||||
<P>
|
||||
<HR>
|
||||
<!--------------------------------------------------------------------------->
|
||||
<H3><A name=concept:ConstantLvalueIterator></A>Constant Lvalue Iterator </H3>A
|
||||
Constant Lvalue Iterator is an iterator that dereferences to produce a const
|
||||
reference to the pointed-to object, i.e., the associated <TT>reference</TT> type
|
||||
is <TT>const T&</TT>. Changing the value of or destroying an iterator that
|
||||
models Constant Lvalue Iterator does not invalidate pointers and references
|
||||
previously obtained from that iterator.
|
||||
<H3>Refinement of</H3><A
|
||||
href="file:///C:/WINDOWS/TEMP/iterator-categories.html#concept:ReadableIterator">Readable
|
||||
Iterator</A>
|
||||
<H3>Associated Types</H3>
|
||||
<TABLE border=1>
|
||||
<TBODY>
|
||||
<TR>
|
||||
<TD>Reference type</TD>
|
||||
<TD><TT>std::iterator_traits<X>::reference</TT></TD>
|
||||
<TD>The return type of dereferencing the iterator, which must be <TT>const
|
||||
T&</TT>. </TD></TR><!-- I don't think this is needed
|
||||
<tr>
|
||||
<td>Pointer type</td>
|
||||
<td><tt>std::iterator_traits<X>::pointer</tt></td>
|
||||
<td>
|
||||
The pointer to the value type, which must be <tt>const T*</tt>.
|
||||
</td>
|
||||
</tr>
|
||||
-->
|
||||
<TR>
|
||||
<TD>Return Category</TD>
|
||||
<TD><TT>std::return_category<X>::type</TT></TD>
|
||||
<TD>A type convertible to <TT>std::constant_lvalue_iterator_tag</TT>
|
||||
</TD></TR></TBODY></TABLE><!-- these are not necessary now that we use reference as operator* return type
|
||||
<h3>Valid expressions</h3>
|
||||
|
||||
<Table border>
|
||||
<tr><TH>Name</TH><TH>Expression</TH><TH>Type requirements</TH><TH>Return type</TH></tr>
|
||||
<tr>
|
||||
<td>Dereference</td>
|
||||
<td><tt>*x</tt></td>
|
||||
<td> </td>
|
||||
<td><tt>std::iterator_traits<X>::reference</tt></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Member access</td>
|
||||
<td><tt>x->m</tt></td>
|
||||
<td><tt>T</tt> is a type with a member named <tt>m</tt>.</td>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
-->
|
||||
<P>
|
||||
<HR>
|
||||
<!--------------------------------------------------------------------------->
|
||||
<H3><A name=concept:MutableLvalueIterator></A>Mutable Lvalue Iterator </H3>A
|
||||
Mutable Lvalue Iterator is an iterator that dereferences to produce a reference
|
||||
to the pointed-to object. The associated <TT>reference</TT> type is
|
||||
<TT>T&</TT>. Changing the value of or destroying an iterator that models
|
||||
Mutable Lvalue Iterator does not invalidate pointers and references previously
|
||||
obtained from that iterator.
|
||||
<H3>Refinement of</H3><A
|
||||
href="file:///C:/WINDOWS/TEMP/iterator-categories.html#concept:ReadableIterator">Readable
|
||||
Iterator</A>, <A
|
||||
href="file:///C:/WINDOWS/TEMP/iterator-categories.html#concept:WritableIterator">Writable
|
||||
Iterator</A>, and <A
|
||||
href="file:///C:/WINDOWS/TEMP/iterator-categories.html#concept:SwappableIterator">Swappable
|
||||
Iterator</A>.
|
||||
<H3>Associated Types</H3>
|
||||
<TABLE border=1>
|
||||
<TBODY>
|
||||
<TR>
|
||||
<TD>Reference type</TD>
|
||||
<TD><TT>std::iterator_traits<X>::reference</TT></TD>
|
||||
<TD>The return type of dereferencing the iterator, which must be
|
||||
<TT>T&</TT>.</TD></TR><!-- I don't think this is necessary
|
||||
<tr>
|
||||
<td>Pointer type</td>
|
||||
<td><tt>std::iterator_traits<X>::pointer</tt></td>
|
||||
<td>
|
||||
The pointer to the value type, which is <tt>T*</tt>.
|
||||
</td>
|
||||
</tr>
|
||||
-->
|
||||
<TR>
|
||||
<TD>Return Category</TD>
|
||||
<TD><TT>std::return_category<X>::type</TT></TD>
|
||||
<TD>A type convertible to <TT>std::mutable_lvalue_iterator_tag</TT>
|
||||
</TD></TR></TBODY></TABLE><!-- no longer needed since the return type is specified as reference in the readable iterator
|
||||
<h3>Valid expressions</h3>
|
||||
|
||||
<Table border>
|
||||
<tr><TH>Name</TH><TH>Expression</TH><TH>Type requirements</TH><TH>Return type</TH></tr>
|
||||
<tr>
|
||||
<td>Dereference</td>
|
||||
<td><tt>*x</tt></td>
|
||||
<td> </td>
|
||||
<td><tt>std::iterator_traits<X>::reference</tt></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Member access</td>
|
||||
<td><tt>x->m</tt></td>
|
||||
<td><tt>T</tt> is a type with a member named <tt>m</tt>.</td>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
-->
|
||||
<P>
|
||||
<HR>
|
||||
<!--------------------------------------------------------------------------->
|
||||
<H3><A name=concept:ForwardTraversalIterator></A>Forward Traversal Iterator
|
||||
</H3>The Forward Iterator is an iterator that can be incremented. Also, it is
|
||||
permissible to make multiple passes through the iterator's range.
|
||||
<H3>Refinement of</H3><A
|
||||
href="http://www.boost.org/libs/utility/CopyConstructible.html">Copy
|
||||
Constructible</A>, <A
|
||||
href="http://www.boost.org/libs/utility/Assignable.html">Assignable</A>, <A
|
||||
href="http://www.sgi.com/tech/stl/DefaultConstructible.html">Default
|
||||
Constructible</A>, and <A
|
||||
href="http://www.sgi.com/tech/stl/EqualityComparable.html">Equality
|
||||
Comparable</A>
|
||||
<H3>Associated types</H3>
|
||||
<TABLE border=1>
|
||||
<TBODY>
|
||||
<TR>
|
||||
<TD>Difference Type</TD>
|
||||
<TD><TT>std::iterator_traits<X>::difference_type</TT></TD>
|
||||
<TD>A signed integral type used for representing distances between
|
||||
iterators that point into the same range. </TD></TR>
|
||||
<TR>
|
||||
<TD>Traversal Category</TD>
|
||||
<TD><TT>std::traversal_category<X>::type</TT></TD>
|
||||
<TD>A type convertible to <TT>std::forward_traversal_tag</TT>
|
||||
</TD></TR></TBODY></TABLE>
|
||||
<H3>Valid expressions</H3>
|
||||
<TABLE border=1>
|
||||
<TBODY>
|
||||
<TR>
|
||||
<TH>Name</TH>
|
||||
<TH>Expression</TH>
|
||||
<TH>Type requirements</TH>
|
||||
<TH>Return type</TH></TR>
|
||||
<TR>
|
||||
<TD>Preincrement</TD>
|
||||
<TD><TT>++i</TT></TD>
|
||||
<TD> </TD>
|
||||
<TD><TT>X&</TT></TD></TR>
|
||||
<TR>
|
||||
<TD>Postincrement</TD>
|
||||
<TD><TT>i++</TT></TD>
|
||||
<TD> </TD>
|
||||
<TD>convertible to <TT>const X&</TT></TD></TR></TBODY></TABLE>
|
||||
<P>
|
||||
<HR>
|
||||
<!--------------------------------------------------------------------------->
|
||||
<H3><A name=concept:BidirectionalTraversalIterator></A>Bidirectional Traversal
|
||||
Iterator </H3>An iterator that can be incremented and decremented.
|
||||
<H3>Refinement of</H3><A
|
||||
href="file:///C:/WINDOWS/TEMP/iterator-categories.html#concept:ForwardTraversalIterator">Forward
|
||||
Traversal Iterator</A>
|
||||
<H3>Associated types</H3>
|
||||
<TABLE border=1>
|
||||
<TBODY>
|
||||
<TR>
|
||||
<TD>Traversal Category</TD>
|
||||
<TD><TT>std::traversal_category<X>::type</TT></TD>
|
||||
<TD>A type convertible to <TT>std::bidirectional_traversal_tag</TT>
|
||||
</TD></TR></TBODY></TABLE>
|
||||
<H3>Valid expressions</H3>
|
||||
<TABLE border=1>
|
||||
<TBODY>
|
||||
<TR>
|
||||
<TH>Name</TH>
|
||||
<TH>Expression</TH>
|
||||
<TH>Type requirements</TH>
|
||||
<TH>Return type</TH></TR>
|
||||
<TR>
|
||||
<TD>Predecrement</TD>
|
||||
<TD><TT>--i</TT></TD>
|
||||
<TD> </TD>
|
||||
<TD><TT>X&</TT></TD></TR>
|
||||
<TR>
|
||||
<TD>Postdecrement</TD>
|
||||
<TD><TT>i--</TT></TD>
|
||||
<TD> </TD>
|
||||
<TD>convertible to <TT>const X&</TT></TD></TR></TBODY></TABLE>
|
||||
<P>
|
||||
<HR>
|
||||
<!--------------------------------------------------------------------------->
|
||||
<H3><A name=concept:RandomAccessTraversalIterator></A>Random Access Traversal
|
||||
Iterator </H3>An iterator that provides constant-time methods for moving forward
|
||||
and backward in arbitrary-sized steps.
|
||||
<H3>Refinement of</H3><A
|
||||
href="file:///C:/WINDOWS/TEMP/iterator-categories.html#concept:BidirectionalTraversalIterator">Bidirectional
|
||||
Traversal Iterator</A> and <A
|
||||
href="http://www.sgi.com/tech/stl/LessThanComparable.html">Less Than
|
||||
Comparable</A> where <TT><</TT> is a total ordering
|
||||
<H3>Associated types</H3>
|
||||
<TABLE border=1>
|
||||
<TBODY>
|
||||
<TR>
|
||||
<TD>Traversal Category</TD>
|
||||
<TD><TT>std::traversal_category<X>::type</TT></TD>
|
||||
<TD>A type convertible to <TT>std::random_access_traversal_tag</TT>
|
||||
</TD></TR></TBODY></TABLE>
|
||||
<H3>Valid expressions</H3>
|
||||
<TABLE border=1>
|
||||
<TBODY>
|
||||
<TR>
|
||||
<TH>Name</TH>
|
||||
<TH>Expression</TH>
|
||||
<TH>Type requirements</TH>
|
||||
<TH>Return type</TH></TR>
|
||||
<TR>
|
||||
<TD>Iterator addition</TD>
|
||||
<TD><TT>i += n</TT></TD>
|
||||
<TD> </TD>
|
||||
<TD><TT>X&</TT></TD></TR>
|
||||
<TR>
|
||||
<TD>Iterator addition</TD>
|
||||
<TD><TT>i + n</TT> or <TT>n + i</TT></TD>
|
||||
<TD> </TD>
|
||||
<TD><TT>X</TT></TD></TR>
|
||||
<TR>
|
||||
<TD>Iterator subtraction</TD>
|
||||
<TD><TT>i -= n</TT></TD>
|
||||
<TD> </TD>
|
||||
<TD><TT>X&</TT></TD></TR>
|
||||
<TR>
|
||||
<TD>Iterator subtraction</TD>
|
||||
<TD><TT>i - n</TT></TD>
|
||||
<TD> </TD>
|
||||
<TD><TT>X</TT></TD></TR>
|
||||
<TR>
|
||||
<TD>Difference</TD>
|
||||
<TD><TT>i - j</TT></TD>
|
||||
<TD> </TD>
|
||||
<TD><TT>std::iterator_traits<X>::difference_type</TT></TD></TR>
|
||||
<TR>
|
||||
<TD>Element operator</TD>
|
||||
<TD><TT>i[n]</TT></TD>
|
||||
<TD><TT>X</TT> must also be a model of <A
|
||||
href="file:///C:/WINDOWS/TEMP/iterator-categories.html#concept:ReadableIterator">Readable
|
||||
Iterator</A>. </TD>
|
||||
<TD><TT>std::iterator_traits<X>::reference</TT></TD></TR>
|
||||
<TR>
|
||||
<TD>Element assignment</TD>
|
||||
<TD><TT>i[n] = t</TT></TD>
|
||||
<TD><TT>X</TT> must also be a model of <A
|
||||
href="file:///C:/WINDOWS/TEMP/iterator-categories.html#concept:WritableIterator">Writable
|
||||
Iterator</A>.</TD>
|
||||
<TD>unspecified</TD></TR></TBODY></TABLE>
|
||||
<P>
|
||||
<HR>
|
||||
<!-- LocalWords: HTML BGCOLOR FFFFFF TR TD Siek HREF mailto jsiek
|
||||
--><!-- LocalWords: lsc edu tt const href http anubis dkuug dk JTC SC WG docs lt
|
||||
--><!-- LocalWords: lwg html bool gt Sutter's htm Lvalue namespace std struct
|
||||
--><!-- LocalWords: lvalue typename OldTraits reusability min iter prev inplace
|
||||
--><!-- LocalWords: rvalue templated Preincrement Postincrement Predecrement
|
||||
--><!-- LocalWords: Postdecrement
|
||||
--></BODY></HTML>
|
Reference in New Issue
Block a user