mirror of
https://github.com/boostorg/iterator.git
synced 2025-05-11 13:33:56 +00:00
823 lines
30 KiB
HTML
823 lines
30 KiB
HTML
<!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>
|
|
|
|
<P>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>
|
|
|
|
<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.</P>
|
|
|
|
<H3>New category tags and traits classes</H3>
|
|
|
|
<P>The new iterator categories will require new tag classes.</P>
|
|
|
|
<PRE>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 { };
|
|
|
|
}
|
|
</PRE>
|
|
|
|
<P>Access to the return and traversal tags will be through the
|
|
following two traits classes, which have a member typedef named
|
|
<TT>type</TT> that provides the tag type. We explain the
|
|
definitions of these classes later.</P>
|
|
|
|
<PRE>
|
|
template <typename Iterator>
|
|
struct return_category; // contains: typedef ... type;
|
|
|
|
template <typename Iterator>
|
|
struct traversal_category; // contains: typedef ... type;
|
|
</PRE>
|
|
|
|
<P>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 <TT>iterator_category</TT> typedef within
|
|
<TT>iterator_traits</TT>.
|
|
|
|
<PRE>namespace std {
|
|
template <class ReturnTag, class TraversalTag>
|
|
struct iterator_tag : cvt_iterator_category<ReturnTag, TraversalTag>::type
|
|
{
|
|
typedef ReturnTag returns;
|
|
typedef TraversalTag traversal;
|
|
};
|
|
</PRE>
|
|
|
|
<P>The <TT>cvt_iterator_category</TT> template computes the
|
|
appropriate old iterator category based on the return and traversal
|
|
category.</P>
|
|
|
|
<PRE>namespace std {
|
|
template <class RC, class TC>
|
|
struct cvt_iterator_category
|
|
{
|
|
<B><I>// Pseudo-code, <= means inherits or same type</I></B>
|
|
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;
|
|
};
|
|
}
|
|
</PRE>
|
|
|
|
<P>The following is an example of a new iterator class using the
|
|
<TT>iterator_tag</TT> class to create its <TT>iterator_category</TT>
|
|
member typedef.</P>
|
|
|
|
<PRE>
|
|
struct my_iterator {
|
|
typedef std::iterator_tag<std::readable_iterator_tag,
|
|
std::random_access_traversal_tag> iterator_category;
|
|
...
|
|
};
|
|
</PRE>
|
|
|
|
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 <TT>return_category</TT> and <TT>traversal_category</TT>
|
|
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
|
|
<TT>iterator_category</TT> tag.
|
|
|
|
|
|
<PRE>
|
|
template <typename Iterator>
|
|
class return_category
|
|
{
|
|
<B><I>// Pseudo-code</I></B>
|
|
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*>
|
|
{
|
|
<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>
|
|
class traversal_category
|
|
{
|
|
typedef iterator_traits<Iterator>::iterator_category tag;
|
|
public:
|
|
<B><I>// Pseudo-code</I></B>
|
|
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;
|
|
};
|
|
</PRE>
|
|
|
|
<H2>Impact on the Standard Algorithms</H2>
|
|
|
|
<P>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>
|
|
|
|
<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>
|