mirror of
https://github.com/boostorg/iterator.git
synced 2025-07-24 01:47:17 +02:00
Move from boost-sandbox
[SVN r18959]
This commit is contained in:
BIN
doc/access.png
Normal file
BIN
doc/access.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 11 KiB |
BIN
doc/access2old.png
Normal file
BIN
doc/access2old.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 41 KiB |
188
doc/default.css
Normal file
188
doc/default.css
Normal file
@ -0,0 +1,188 @@
|
||||
/*
|
||||
:Author: David Goodger
|
||||
:Contact: goodger@users.sourceforge.net
|
||||
:date: $Date$
|
||||
:version: $Revision$
|
||||
:copyright: This stylesheet has been placed in the public domain.
|
||||
|
||||
Default cascading style sheet for the HTML output of Docutils.
|
||||
*/
|
||||
|
||||
.first {
|
||||
margin-top: 0 }
|
||||
|
||||
.last {
|
||||
margin-bottom: 0 }
|
||||
|
||||
a.toc-backref {
|
||||
text-decoration: none ;
|
||||
color: black }
|
||||
|
||||
dd {
|
||||
margin-bottom: 0.5em }
|
||||
|
||||
div.abstract {
|
||||
margin: 2em 5em }
|
||||
|
||||
div.abstract p.topic-title {
|
||||
font-weight: bold ;
|
||||
text-align: center }
|
||||
|
||||
div.attention, div.caution, div.danger, div.error, div.hint,
|
||||
div.important, div.note, div.tip, div.warning {
|
||||
margin: 2em ;
|
||||
border: medium outset ;
|
||||
padding: 1em }
|
||||
|
||||
div.attention p.admonition-title, div.caution p.admonition-title,
|
||||
div.danger p.admonition-title, div.error p.admonition-title,
|
||||
div.warning p.admonition-title {
|
||||
color: red ;
|
||||
font-weight: bold ;
|
||||
font-family: sans-serif }
|
||||
|
||||
div.hint p.admonition-title, div.important p.admonition-title,
|
||||
div.note p.admonition-title, div.tip p.admonition-title {
|
||||
font-weight: bold ;
|
||||
font-family: sans-serif }
|
||||
|
||||
div.dedication {
|
||||
margin: 2em 5em ;
|
||||
text-align: center ;
|
||||
font-style: italic }
|
||||
|
||||
div.dedication p.topic-title {
|
||||
font-weight: bold ;
|
||||
font-style: normal }
|
||||
|
||||
div.figure {
|
||||
margin-left: 2em }
|
||||
|
||||
div.footer, div.header {
|
||||
font-size: smaller }
|
||||
|
||||
div.system-messages {
|
||||
margin: 5em }
|
||||
|
||||
div.system-messages h1 {
|
||||
color: red }
|
||||
|
||||
div.system-message {
|
||||
border: medium outset ;
|
||||
padding: 1em }
|
||||
|
||||
div.system-message p.system-message-title {
|
||||
color: red ;
|
||||
font-weight: bold }
|
||||
|
||||
div.topic {
|
||||
margin: 2em }
|
||||
|
||||
h1.title {
|
||||
text-align: center }
|
||||
|
||||
h2.subtitle {
|
||||
text-align: center }
|
||||
|
||||
hr {
|
||||
width: 75% }
|
||||
|
||||
ol.simple, ul.simple {
|
||||
margin-bottom: 1em }
|
||||
|
||||
ol.arabic {
|
||||
list-style: decimal }
|
||||
|
||||
ol.loweralpha {
|
||||
list-style: lower-alpha }
|
||||
|
||||
ol.upperalpha {
|
||||
list-style: upper-alpha }
|
||||
|
||||
ol.lowerroman {
|
||||
list-style: lower-roman }
|
||||
|
||||
ol.upperroman {
|
||||
list-style: upper-roman }
|
||||
|
||||
p.caption {
|
||||
font-style: italic }
|
||||
|
||||
p.credits {
|
||||
font-style: italic ;
|
||||
font-size: smaller }
|
||||
|
||||
p.label {
|
||||
white-space: nowrap }
|
||||
|
||||
p.topic-title {
|
||||
font-weight: bold }
|
||||
|
||||
pre.address {
|
||||
margin-bottom: 0 ;
|
||||
margin-top: 0 ;
|
||||
font-family: serif ;
|
||||
font-size: 100% }
|
||||
|
||||
pre.line-block {
|
||||
font-family: serif ;
|
||||
font-size: 100% }
|
||||
|
||||
pre.literal-block, pre.doctest-block {
|
||||
margin-left: 2em ;
|
||||
margin-right: 2em ;
|
||||
background-color: #eeeeee }
|
||||
|
||||
span.classifier {
|
||||
font-family: sans-serif ;
|
||||
font-style: oblique }
|
||||
|
||||
span.classifier-delimiter {
|
||||
font-family: sans-serif ;
|
||||
font-weight: bold }
|
||||
|
||||
span.interpreted {
|
||||
font-family: sans-serif }
|
||||
|
||||
span.option-argument {
|
||||
font-style: italic }
|
||||
|
||||
span.pre {
|
||||
white-space: pre }
|
||||
|
||||
span.problematic {
|
||||
color: red }
|
||||
|
||||
table {
|
||||
margin-top: 0.5em ;
|
||||
margin-bottom: 0.5em }
|
||||
|
||||
table.citation {
|
||||
border-left: solid thin gray ;
|
||||
padding-left: 0.5ex }
|
||||
|
||||
table.docinfo {
|
||||
margin: 2em 4em }
|
||||
|
||||
table.footnote {
|
||||
border-left: solid thin black ;
|
||||
padding-left: 0.5ex }
|
||||
|
||||
td, th {
|
||||
padding-left: 0.5em ;
|
||||
padding-right: 0.5em ;
|
||||
vertical-align: top }
|
||||
|
||||
th.docinfo-name, th.field-name {
|
||||
font-weight: bold ;
|
||||
text-align: left ;
|
||||
white-space: nowrap }
|
||||
|
||||
h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt {
|
||||
font-size: 100% }
|
||||
|
||||
tt {
|
||||
background-color: #eeeeee }
|
||||
|
||||
ul.auto-toc {
|
||||
list-style-type: none }
|
1598
doc/facade-and-adaptor.rst
Normal file
1598
doc/facade-and-adaptor.rst
Normal file
File diff suppressed because it is too large
Load Diff
822
doc/iterator-categories.html
Normal file
822
doc/iterator-categories.html
Normal file
@ -0,0 +1,822 @@
|
||||
<!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>
|
731
doc/new-iter-concepts.rst
Normal file
731
doc/new-iter-concepts.rst
Normal file
@ -0,0 +1,731 @@
|
||||
++++++++++++++++++++++
|
||||
New Iterator Concepts
|
||||
++++++++++++++++++++++
|
||||
|
||||
: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: $Date$
|
||||
:Number: N1477=03-0060
|
||||
:copyright: Copyright Dave Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved
|
||||
|
||||
.. _`Boost Consulting`: http://www.boost-consulting.com
|
||||
.. _`Open Systems Lab`: http://www.osl.iu.edu
|
||||
.. _`Institute for Transport Railway Operation and Construction`: http://www.ive.uni-hannover.de
|
||||
|
||||
: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_.
|
||||
|
||||
.. contents:: Table of Contents
|
||||
|
||||
.. _n1297: http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2001/n1297.html
|
||||
|
||||
============
|
||||
Motivation
|
||||
============
|
||||
|
||||
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) |
|
||||
+------------------------+-------------------------------------------------------------------------+
|
||||
|
||||
.. _issue 200: http://anubis.dkuug.dk/JTC1/SC22/WG21/docs/lwg-active.html#200
|
||||
.. _issue 299: http://anubis.dkuug.dk/JTC1/SC22/WG21/docs/lwg-active.html#299
|
||||
|
||||
|
||||
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``.
|
||||
|
||||
.. _issue 96: http://anubis.dkuug.dk/JTC1/SC22/WG21/docs/lwg-active.html#96
|
||||
|
||||
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.
|
||||
|
||||
.. _`transform_iterator`: http://www.boost.org/libs/utility/transform_iterator.htm
|
||||
|
||||
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.
|
||||
|
||||
.. _Boost Graph Library: http://www.boost.org/libs/graph/doc/table_of_contents.html
|
||||
.. _Multi-Pass Input Iterator: http://www.boost.org/libs/utility/MultiPassInputIterator.html
|
||||
|
||||
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:
|
||||
|
||||
- Iterators are often mis-categorized.
|
||||
|
||||
- Algorithm requirements are more strict than necessary, because they
|
||||
cannot separate the need for random access or bidirectional
|
||||
traversal from the need for a true reference return type.
|
||||
|
||||
|
||||
========================
|
||||
Impact on the Standard
|
||||
========================
|
||||
|
||||
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.
|
||||
|
||||
.. I think we need to say something about the resolution to allow
|
||||
convertibility to any of the old-style tags as a TR issue (hope it
|
||||
made it). -DWA
|
||||
|
||||
.. Hmm, not sure I understand. Are you talking about whether a
|
||||
standards conforming input iterator is allowed to have
|
||||
a tag that is not input_iterator_tag but that
|
||||
is convertible to input_iterator_tag? -JGS
|
||||
|
||||
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 -> Forward Traversal Iterator and Readable Iterator and Writable Iterator
|
||||
``remove, remove_if, unique``
|
||||
|
||||
Forward Iterator -> Single Pass Iterator and Readable Iterator and Writable Iterator
|
||||
``replace, replace_if``
|
||||
|
||||
Bidirectional Iterator -> Bidirectional Traversal Iterator and Swappable Iterator
|
||||
``reverse``
|
||||
|
||||
Bidirectional Iterator -> Bidirectional Traversal Iterator and Readable and Swappable Iterator
|
||||
``partition``
|
||||
|
||||
Bidirectional Iterator (1) -> Bidirectional Traversal Iterator and Readable Iterator,
|
||||
Bidirectional Iterator (2) -> Bidirectional Traversal Iterator and Writable Iterator
|
||||
``copy_backwards``
|
||||
|
||||
Bidirectional Iterator -> Bidirectional Traversal Iterator and Swappable Iterator and Readable Iterator
|
||||
``next_permutation, prev_permutation``
|
||||
|
||||
Bidirectional Iterator -> Bidirectional Traversal Iterator and Readable Iterator and Writable Iterator
|
||||
``stable_partition, inplace_merge``
|
||||
|
||||
Bidirectional Iterator -> Bidirectional Traversal Iterator and Readable Iterator
|
||||
``reverse_copy``
|
||||
|
||||
Random Access Iterator -> Random Access Traversal Iterator and Readable and Swappable Iterator
|
||||
``random_shuffle, sort, stable_sort, partial_sort, nth_element, push_heap, pop_heap
|
||||
make_heap, sort_heap``
|
||||
|
||||
Input Iterator (2) -> Incrementable Iterator and Readable Iterator
|
||||
``equal``
|
||||
|
||||
Input Iterator (2) -> Incrementable Iterator and Readable Iterator
|
||||
``transform``
|
||||
|
||||
========
|
||||
Design
|
||||
========
|
||||
|
||||
The iterator requirements are be separated into two hierarchies. One
|
||||
set of concepts handles the syntax and semantics of value access:
|
||||
|
||||
- Readable Iterator
|
||||
- Writable Iterator
|
||||
- Swappable Iterator
|
||||
- Readable Lvalue Iterator
|
||||
- Writable Lvalue Iterator
|
||||
|
||||
The refinement relationships among these iterator concepts are given
|
||||
in the following diagram.
|
||||
|
||||
.. image:: access.png
|
||||
|
||||
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:
|
||||
|
||||
- Incrementable Iterator
|
||||
- Single Pass Iterator
|
||||
- Forward Traversal Iterator
|
||||
- Bidirectional Traversal Iterator
|
||||
- Random Access Traversal Iterator
|
||||
|
||||
The refinement relationships for the traversal concepts are in the
|
||||
following diagram.
|
||||
|
||||
.. image:: traversal.png
|
||||
|
||||
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.
|
||||
|
||||
.. image:: oldeqnew.png
|
||||
|
||||
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).
|
||||
|
||||
|
||||
===============
|
||||
Proposed Text
|
||||
===============
|
||||
|
||||
Addition to [lib.iterator.requirements]
|
||||
=======================================
|
||||
|
||||
Iterator Value Access Concepts [lib.iterator.value.access]
|
||||
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
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``.
|
||||
|
||||
.. _Readable Iterator:
|
||||
|
||||
Readable Iterators [lib.readable.iterators]
|
||||
-------------------------------------------
|
||||
|
||||
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`` |
|
||||
+--------------------------------------+---------------------------------------------------+-----------------------------------------------------------------+
|
||||
|
||||
|
||||
.. _Writable Iterator:
|
||||
|
||||
Writable Iterators [lib.writable.iterators]
|
||||
-------------------------------------------
|
||||
|
||||
A class or built-in type ``X`` models the *Writable Iterator* concept
|
||||
if the following expressions are valid and respect the stated
|
||||
semantics.
|
||||
|
||||
.. A type ``T`` belongs to the *set of value types* of ``X``
|
||||
if, for an object ``v`` of type ``T``, ``*a = v`` is valid.
|
||||
|
||||
** This appears to be a mutual recursion which ends up meaning
|
||||
nothing. Kill the assertion column?
|
||||
|
||||
Separate but related question: Is a writable iterator required
|
||||
to have a meaningful value_type? If not, we need to use a
|
||||
different name from ``v`` in this table -DWA
|
||||
|
||||
+------------------------------------------------------------------------------------------------------------------------------+
|
||||
| Writable Iterator Requirements (in addition to CopyConstructible) |
|
||||
+--------------------------------------+------------------------------------------+--------------------------------------------+
|
||||
| Expression | Return Type | Assertion/Note/Precondition/Postcondition |
|
||||
+======================================+==========================================+============================================+
|
||||
| ``access_category<X>::type`` | Convertible to ``writable_iterator_tag`` | |
|
||||
+--------------------------------------+------------------------------------------+--------------------------------------------+
|
||||
| ``*a = v`` | | .. ** pre: The type of ``v`` is in the set |
|
||||
| | | of value types of ``X`` |
|
||||
+--------------------------------------+------------------------------------------+--------------------------------------------+
|
||||
|
||||
|
||||
Swappable Iterators [lib.swappable.iterators]
|
||||
---------------------------------------------
|
||||
|
||||
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 | Assertion/Note/Precondition/Postcondition |
|
||||
+====================================+=============+=============================================+
|
||||
| ``iter_swap(a, b)`` | ``void`` | post: the pointed to values are exchanged |
|
||||
+------------------------------------+-------------+---------------------------------------------+
|
||||
|
||||
[*Note:* An iterator that is a model of the *Readable* and *Writable Iterator* concepts
|
||||
is also a model of *Swappable Iterator*. *--end note*]
|
||||
|
||||
|
||||
Readable Lvalue Iterators [lib.readable.lvalue.iterators]
|
||||
---------------------------------------------------------
|
||||
|
||||
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/Note/Precondition/Postcondition |
|
||||
+====================================+=================================================+===========================================================+
|
||||
| ``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`` | |
|
||||
+------------------------------------+-------------------------------------------------+-----------------------------------------------------------+
|
||||
|
||||
|
||||
Writable Lvalue Iterators [lib.writable.lvalue.iterators]
|
||||
---------------------------------------------------------
|
||||
|
||||
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 | Assertion/Note/Precondition/Postcondition |
|
||||
+======================================+==================================================+============================================================+
|
||||
| ``iterator_traits<X>::reference`` | ``iterator_traits<X>::value_type&`` | |
|
||||
+--------------------------------------+--------------------------------------------------+------------------------------------------------------------+
|
||||
| ``access_category<X>::type`` | Convertible to ``writable_lvalue_iterator_tag`` | |
|
||||
+--------------------------------------+--------------------------------------------------+------------------------------------------------------------+
|
||||
|
||||
|
||||
Iterator Traversal Concepts [lib.iterator.traversal]
|
||||
++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
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``.
|
||||
|
||||
|
||||
Incrementable Iterators [lib.incrementable.iterators]
|
||||
-----------------------------------------------------
|
||||
|
||||
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/Note/Precondition/Postcondition |
|
||||
+======================================+==================================================+============================================================+
|
||||
| ``++r`` | ``X&`` | ``&r == &++r`` |
|
||||
+--------------------------------------+--------------------------------------------------+------------------------------------------------------------+
|
||||
| ``r++`` | convertible to ``const X&`` | ``{ X tmp = r; ++r; return tmp; }`` |
|
||||
+--------------------------------------+--------------------------------------------------+------------------------------------------------------------+
|
||||
| ``traversal_category<X>::type`` | | Convertible to ``incrementable_iterator_tag`` |
|
||||
+--------------------------------------+--------------------------------------------------+------------------------------------------------------------+
|
||||
|
||||
|
||||
Single Pass Iterators [lib.single.pass.iterators]
|
||||
-------------------------------------------------
|
||||
|
||||
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/Note/Precondition/Postcondition/Semantics |
|
||||
+==================================+=========================+=========================================================================================+
|
||||
| ``++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`` |
|
||||
+----------------------------------+-------------------------+-----------------------------------------------------------------------------------------+
|
||||
|
||||
|
||||
Forward Traversal Iterators [lib.forward.traversal.iterators]
|
||||
-------------------------------------------------------------
|
||||
|
||||
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/Precondition/Postcondition/Semantics |
|
||||
+==========================================+==============+========================================================================+
|
||||
| ``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`` |
|
||||
+------------------------------------------+--------------+------------------------------------------------------------------------+
|
||||
|
||||
|
||||
Bidirectional Traversal Iterators [lib.bidirectional.traversal.iterators]
|
||||
-------------------------------------------------------------------------
|
||||
|
||||
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/Note/Precondition/Postcondition/Semantics |
|
||||
+=========================================+=============+=====================================================+
|
||||
| ``--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 |``{ X tmp = r; --r; return tmp; }`` |
|
||||
| |to ``const | |
|
||||
| |X&`` | |
|
||||
+-----------------------------------------+-------------+-----------------------------------------------------+
|
||||
| ``traversal_category<X>::type`` | | Convertible to |
|
||||
| | | ``bidirectional_traversal_iterator_tag`` |
|
||||
| | | |
|
||||
+-----------------------------------------+-------------+-----------------------------------------------------+
|
||||
|
||||
|
||||
Random Access Traversal Iterators [lib.random.access.traversal.iterators]
|
||||
-------------------------------------------------------------------------
|
||||
|
||||
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/Note/Pre/Post-condition |
|
||||
+================================+=======================================+==========================+========================================+
|
||||
|``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) : |pre: there exists a value ``n`` of |
|
||||
| | |-distance(b,a)`` |``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``|
|
||||
+--------------------------------+---------------------------------------+--------------------------+----------------------------------------+
|
||||
|
||||
|
||||
|
||||
Addition to [lib.iterator.synopsis]
|
||||
===================================
|
||||
|
||||
::
|
||||
|
||||
// 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 {};
|
||||
|
||||
Addition to [lib.iterator.traits]
|
||||
=================================
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
|
||||
|
||||
..
|
||||
LocalWords: Abrahams Siek Witt const bool Sutter's WG int UL LI href Lvalue
|
||||
LocalWords: ReadableIterator WritableIterator SwappableIterator cv pre iter
|
||||
LocalWords: ConstantLvalueIterator MutableLvalueIterator CopyConstructible TR
|
||||
LocalWords: ForwardTraversalIterator BidirectionalTraversalIterator lvalue
|
||||
LocalWords: RandomAccessTraversalIterator dereferenceable Incrementable tmp
|
||||
LocalWords: incrementable xxx min prev inplace png oldeqnew AccessTag struct
|
||||
LocalWords: TraversalTag typename lvalues DWA Hmm JGS
|
BIN
doc/oldeqnew.png
Normal file
BIN
doc/oldeqnew.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 33 KiB |
BIN
doc/traversal.png
Normal file
BIN
doc/traversal.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.9 KiB |
Reference in New Issue
Block a user