mirror of
https://github.com/boostorg/iterator.git
synced 2025-05-09 23:23:54 +00:00
Move from boost-sandbox
[SVN r18959]
This commit is contained in:
parent
53eb5346de
commit
80d9e8e4c1
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 |
1
example/Jamfile
Normal file
1
example/Jamfile
Normal file
@ -0,0 +1 @@
|
||||
unit-test ia1 : reverse_iterator.cpp : <sysinclude>../../.. <sysinclude>$(BOOST) ;
|
16
example/reverse_iterator.cpp
Normal file
16
example/reverse_iterator.cpp
Normal file
@ -0,0 +1,16 @@
|
||||
#include <boost/iterator/iterator_adaptors.hpp>
|
||||
#include <boost/cstdlib.hpp>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <algorithm>
|
||||
|
||||
int main()
|
||||
{
|
||||
int x[] = { 1, 2, 3, 4 };
|
||||
boost::reverse_iterator<int*, int, int&, int*,
|
||||
boost::iterator_tag<boost::mutable_lvalue_iterator_tag, boost::random_access_traversal_tag>
|
||||
, std::ptrdiff_t> first(x + 4), last(x);
|
||||
std::copy(first, last, std::ostream_iterator<int>(std::cout, " "));
|
||||
std::cout << std::endl;
|
||||
return 0;
|
||||
}
|
338
include/boost/iterator/detail/categories.hpp
Normal file
338
include/boost/iterator/detail/categories.hpp
Normal file
@ -0,0 +1,338 @@
|
||||
// (C) Copyright Thomas Witt 2002. Permission to copy, use, modify,
|
||||
// sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
|
||||
#ifndef BOOST_ITERATOR_DETAIL_CATEGORIES_HPP
|
||||
# define BOOST_ITERATOR_DETAIL_CATEGORIES_HPP
|
||||
|
||||
# include <boost/config.hpp>
|
||||
# include <boost/iterator/detail/config_def.hpp>
|
||||
|
||||
# include <boost/detail/workaround.hpp>
|
||||
|
||||
# include <boost/type_traits/is_convertible.hpp>
|
||||
# include <boost/type_traits/is_same.hpp>
|
||||
|
||||
# include <boost/mpl/if.hpp>
|
||||
# include <boost/mpl/apply_if.hpp>
|
||||
# include <boost/mpl/identity.hpp>
|
||||
# include <boost/mpl/bool.hpp>
|
||||
# include <boost/mpl/or.hpp>
|
||||
# include <boost/mpl/and.hpp>
|
||||
|
||||
# include <iterator>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
// faked new old-style categories needed to make new->old mapping
|
||||
// work
|
||||
namespace detail
|
||||
{
|
||||
struct null_category_tag {};
|
||||
struct input_output_iterator_tag : std::input_iterator_tag, std::output_iterator_tag {};
|
||||
}
|
||||
|
||||
//
|
||||
// Access Categories
|
||||
//
|
||||
struct readable_iterator_tag
|
||||
{
|
||||
typedef std::input_iterator_tag max_category;
|
||||
};
|
||||
|
||||
struct writable_iterator_tag
|
||||
{
|
||||
typedef std::output_iterator_tag max_category;
|
||||
};
|
||||
|
||||
struct swappable_iterator_tag
|
||||
{
|
||||
typedef detail::null_category_tag max_category;
|
||||
};
|
||||
|
||||
struct readable_writable_iterator_tag
|
||||
: virtual readable_iterator_tag
|
||||
, virtual writable_iterator_tag
|
||||
, virtual swappable_iterator_tag
|
||||
{
|
||||
typedef detail::input_output_iterator_tag max_category;
|
||||
};
|
||||
|
||||
struct readable_lvalue_iterator_tag
|
||||
: virtual readable_iterator_tag
|
||||
{
|
||||
typedef std::random_access_iterator_tag max_category;
|
||||
};
|
||||
|
||||
struct writable_lvalue_iterator_tag
|
||||
: virtual public readable_writable_iterator_tag
|
||||
, virtual public readable_lvalue_iterator_tag
|
||||
{
|
||||
typedef std::random_access_iterator_tag max_category;
|
||||
};
|
||||
|
||||
//
|
||||
// Traversal Categories
|
||||
//
|
||||
struct incrementable_traversal_tag
|
||||
{
|
||||
typedef std::output_iterator_tag max_category;
|
||||
};
|
||||
|
||||
struct single_pass_traversal_tag
|
||||
: incrementable_traversal_tag
|
||||
{
|
||||
typedef detail::input_output_iterator_tag max_category;
|
||||
};
|
||||
|
||||
struct forward_traversal_tag
|
||||
: single_pass_traversal_tag
|
||||
{
|
||||
typedef std::forward_iterator_tag max_category;
|
||||
};
|
||||
|
||||
struct bidirectional_traversal_tag
|
||||
: forward_traversal_tag
|
||||
{
|
||||
typedef std::bidirectional_iterator_tag max_category;
|
||||
};
|
||||
|
||||
struct random_access_traversal_tag
|
||||
: bidirectional_traversal_tag
|
||||
{
|
||||
typedef std::random_access_iterator_tag max_category;
|
||||
};
|
||||
|
||||
struct error_iterator_tag { };
|
||||
|
||||
namespace detail
|
||||
{
|
||||
//
|
||||
// Tag detection meta functions
|
||||
//
|
||||
|
||||
// I bet this is defined somewhere else. Let's wait and see.
|
||||
struct error_type;
|
||||
|
||||
# ifndef BOOST_NO_IS_CONVERTIBLE
|
||||
|
||||
// True iff T is a tag "derived" from Tag
|
||||
template <class Tag, class T>
|
||||
struct is_tag
|
||||
: mpl::or_<
|
||||
is_convertible<T, Tag>
|
||||
|
||||
// Because we can't actually get forward_iterator_tag to
|
||||
// derive from input_output_iterator_tag, we need this
|
||||
// case.
|
||||
, mpl::and_<
|
||||
is_convertible<T,std::forward_iterator_tag>
|
||||
, is_convertible<detail::input_output_iterator_tag,Tag>
|
||||
>
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
# else
|
||||
template <class Tag, class T>
|
||||
struct is_tag;
|
||||
# endif
|
||||
|
||||
// Generate specializations which will allow us to find
|
||||
// null_category_tag as a minimum old-style category for new-style
|
||||
// iterators which don't have an actual old-style category. We
|
||||
// need that so there is a valid base class for all new-style
|
||||
// iterators.
|
||||
# define BOOST_OLD_ITERATOR_CATEGORY(category) \
|
||||
template <> \
|
||||
struct is_tag <detail::null_category_tag, std::category> \
|
||||
: mpl::true_ {};
|
||||
|
||||
BOOST_OLD_ITERATOR_CATEGORY(input_iterator_tag)
|
||||
BOOST_OLD_ITERATOR_CATEGORY(output_iterator_tag)
|
||||
BOOST_OLD_ITERATOR_CATEGORY(forward_iterator_tag)
|
||||
BOOST_OLD_ITERATOR_CATEGORY(bidirectional_iterator_tag)
|
||||
BOOST_OLD_ITERATOR_CATEGORY(random_access_iterator_tag)
|
||||
# undef BOOST_OLD_ITERATOR_CATEGORY
|
||||
|
||||
template <>
|
||||
struct is_tag<detail::input_output_iterator_tag,std::forward_iterator_tag>
|
||||
: mpl::true_
|
||||
{
|
||||
};
|
||||
|
||||
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
template <class T>
|
||||
struct is_tag<T,T> : mpl::true_
|
||||
{};
|
||||
|
||||
# ifdef BOOST_NO_IS_CONVERTIBLE
|
||||
// Workarounds for CWPro7 which can't detect derivation at
|
||||
// compile-time.
|
||||
|
||||
// Fact of life: we can only detect tag refinement relationships
|
||||
// among predefined tags.
|
||||
//
|
||||
// Algorithm:
|
||||
// is_tag(T,U) ->
|
||||
// T == U
|
||||
// || (exists d in derived_from(T) such that is_tag(d, U))
|
||||
//
|
||||
// T == U case is handled above
|
||||
|
||||
// false by default
|
||||
template <class Tag, class T>
|
||||
struct is_tag_impl : mpl::false_
|
||||
{};
|
||||
|
||||
// The generalized template dispatches to is_tag_impl because
|
||||
// is_tag<T,T> and is_tag<some_tag,T> are equally specialized.
|
||||
// This technique simulates making is_tag<T,T> more-specialized.
|
||||
template <class Tag, class T>
|
||||
struct is_tag
|
||||
: is_tag_impl<Tag, T>
|
||||
{};
|
||||
|
||||
# define BOOST_ITERATOR_DERIVED_TAG1(base, derived) \
|
||||
BOOST_ITERATOR_DERIVED_TAG1_AUX(base, _, derived)
|
||||
|
||||
# define BOOST_ITERATOR_DERIVED_TAG1_AUX(base, underscore, derived) \
|
||||
template<class T> \
|
||||
struct is_tag_impl<base##underscore##tag, T> \
|
||||
: is_tag<derived##underscore##tag, T> \
|
||||
{ \
|
||||
};
|
||||
|
||||
// Old-style tag relations
|
||||
template<class T>
|
||||
struct is_tag_impl<detail::null_category_tag, T>
|
||||
: mpl::or_<
|
||||
is_tag<std::output_iterator_tag, T>
|
||||
, is_tag<std::input_iterator_tag, T>
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
BOOST_ITERATOR_DERIVED_TAG1(std::output_iterator, detail::input_output_iterator)
|
||||
BOOST_ITERATOR_DERIVED_TAG1(std::input_iterator, detail::input_output_iterator)
|
||||
BOOST_ITERATOR_DERIVED_TAG1(detail::input_output_iterator, std::forward_iterator)
|
||||
BOOST_ITERATOR_DERIVED_TAG1(std::forward_iterator, std::bidirectional_iterator)
|
||||
BOOST_ITERATOR_DERIVED_TAG1(std::bidirectional_iterator, std::random_access_iterator)
|
||||
|
||||
// Access tag relations
|
||||
BOOST_ITERATOR_DERIVED_TAG1(readable_lvalue_iterator, writable_lvalue_iterator)
|
||||
BOOST_ITERATOR_DERIVED_TAG1(swappable_iterator, readable_writable_iterator)
|
||||
BOOST_ITERATOR_DERIVED_TAG1(readable_writable_iterator, writable_lvalue_iterator)
|
||||
|
||||
template<class T>
|
||||
struct is_tag_impl<readable_iterator_tag, T>
|
||||
: mpl::or_<
|
||||
is_tag<readable_lvalue_iterator_tag, T>
|
||||
, is_tag<readable_writable_iterator_tag, T>
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
BOOST_ITERATOR_DERIVED_TAG1(writable_iterator, readable_writable_iterator)
|
||||
|
||||
// Traversal tag relations
|
||||
BOOST_ITERATOR_DERIVED_TAG1(bidirectional_traversal, random_access_traversal)
|
||||
BOOST_ITERATOR_DERIVED_TAG1(forward_traversal, bidirectional_traversal)
|
||||
BOOST_ITERATOR_DERIVED_TAG1(single_pass_traversal, forward_traversal)
|
||||
BOOST_ITERATOR_DERIVED_TAG1(incrementable_traversal, single_pass_traversal)
|
||||
|
||||
# endif // BOOST_NO_IS_CONVERTIBLE workarounds
|
||||
|
||||
# endif // ndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
|
||||
template <class Tag, class Known, class Else>
|
||||
struct known_tag
|
||||
: mpl::apply_if<is_tag<Known,Tag>, mpl::identity<Known>, Else>
|
||||
{};
|
||||
|
||||
template <class Tag>
|
||||
struct max_known_traversal_tag
|
||||
: known_tag<
|
||||
Tag, random_access_traversal_tag
|
||||
, known_tag<
|
||||
Tag, bidirectional_traversal_tag
|
||||
, known_tag<
|
||||
Tag, forward_traversal_tag
|
||||
, known_tag<
|
||||
Tag, single_pass_traversal_tag
|
||||
, known_tag<
|
||||
Tag, incrementable_traversal_tag
|
||||
, error_iterator_tag
|
||||
>
|
||||
>
|
||||
>
|
||||
>
|
||||
>
|
||||
{};
|
||||
|
||||
// Doesn't cope with these odd combinations: readable+swappable,
|
||||
// writable+swappable. That doesn't matter for the sake of
|
||||
// new-style tag base computation, which is all it's used for
|
||||
// anyway.
|
||||
template <class Tag>
|
||||
struct max_known_access_tag
|
||||
: known_tag<
|
||||
Tag, writable_lvalue_iterator_tag
|
||||
, known_tag<
|
||||
Tag, readable_lvalue_iterator_tag
|
||||
, known_tag<
|
||||
Tag, readable_writable_iterator_tag
|
||||
, known_tag<
|
||||
Tag, writable_iterator_tag
|
||||
, known_tag<
|
||||
Tag, readable_iterator_tag
|
||||
, mpl::apply_if<
|
||||
is_tag<Tag, swappable_iterator_tag>
|
||||
, mpl::identity<null_category_tag>
|
||||
, error_iterator_tag
|
||||
>
|
||||
>
|
||||
>
|
||||
>
|
||||
>
|
||||
>
|
||||
{};
|
||||
|
||||
//
|
||||
// Returns the minimum category type or error_type
|
||||
// if T1 and T2 are unrelated.
|
||||
//
|
||||
// For compilers not supporting is_convertible this only
|
||||
// works with the new boost return and traversal category
|
||||
// types. The exact boost _types_ are required. No derived types
|
||||
// will work.
|
||||
//
|
||||
//
|
||||
template <class T1, class T2>
|
||||
struct minimum_category
|
||||
: mpl::apply_if<
|
||||
is_tag<T1,T2>
|
||||
, mpl::identity<T1>
|
||||
, mpl::if_<
|
||||
is_tag<T2, T1>
|
||||
, T2
|
||||
, error_type
|
||||
>
|
||||
>
|
||||
{};
|
||||
|
||||
# if BOOST_WORKAROUND(BOOST_MSVC, <= 1200)
|
||||
// Deal with ETI
|
||||
template <> struct minimum_category<int, int> { typedef minimum_category type; };
|
||||
# endif
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#include <boost/iterator/detail/config_undef.hpp>
|
||||
|
||||
#endif // BOOST_ITERATOR_DETAIL_CATEGORIES_HPP
|
104
include/boost/iterator/detail/config_def.hpp
Normal file
104
include/boost/iterator/detail/config_def.hpp
Normal file
@ -0,0 +1,104 @@
|
||||
// (C) Copyright David Abrahams 2002.
|
||||
// (C) Copyright Jeremy Siek 2002.
|
||||
// (C) Copyright Thomas Witt 2002.
|
||||
// Permission to copy, use, modify,
|
||||
// sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
|
||||
// no include guard multiple inclusion intended
|
||||
|
||||
//
|
||||
// This is a temporary workaround until the bulk of this is
|
||||
// available in boost config.
|
||||
// 23/02/03 thw
|
||||
//
|
||||
|
||||
#include <boost/config.hpp> // for prior
|
||||
#include <boost/detail/workaround.hpp>
|
||||
|
||||
#define BOOST_ITERATOR_CONFIG_DEF // if you get an error here, you have nested config_def #inclusion.
|
||||
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) \
|
||||
|| BOOST_WORKAROUND(__GNUC__, <= 2 && __GNUC_MINOR__ <= 95) \
|
||||
|| BOOST_WORKAROUND(__MWERKS__, <= 0x3000) \
|
||||
|| BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
|
||||
# define BOOST_NO_SFINAE // "Substitution Failure Is Not An Error not implemented"
|
||||
|
||||
# if 0 // test code
|
||||
template <bool x>
|
||||
struct bar
|
||||
{
|
||||
typedef int type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct bar<false>
|
||||
{
|
||||
};
|
||||
|
||||
|
||||
template <class T>
|
||||
struct foo : bar<(sizeof(T) == 1)>
|
||||
{
|
||||
};
|
||||
|
||||
template <class T>
|
||||
char* f(int, typename foo<T>::type = 0) { return 0; }
|
||||
|
||||
template <class T>
|
||||
int f(...) { return 0; }
|
||||
|
||||
char* x = f<char>(0);
|
||||
int y = f<char[2]>(0);
|
||||
|
||||
int main()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
# endif
|
||||
|
||||
#endif
|
||||
|
||||
#if BOOST_WORKAROUND(__MWERKS__, <=0x2407)
|
||||
# define BOOST_NO_IS_CONVERTIBLE // "is_convertible doesn't work for simple types"
|
||||
#endif
|
||||
|
||||
#if BOOST_WORKAROUND(__GNUC__, BOOST_TESTED_AT(3)) || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
|
||||
# define BOOST_NO_IS_CONVERTIBLE_TEMPLATE // The following program fails to compile:
|
||||
|
||||
# if 0 // test code
|
||||
template <class T>
|
||||
struct foo
|
||||
{
|
||||
foo(T);
|
||||
|
||||
template <class U>
|
||||
foo(foo<U> const& other) : p(other.p) { }
|
||||
|
||||
T p;
|
||||
};
|
||||
|
||||
bool x = boost::is_convertible<foo<int const*>, foo<int*> >::value;
|
||||
# endif
|
||||
|
||||
#endif
|
||||
|
||||
#if BOOST_WORKAROUND(__GNUC__, == 2 && __GNUC_MINOR__ == 95) \
|
||||
|| BOOST_WORKAROUND(__MWERKS__, <= 0x2407) \
|
||||
|| BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
|
||||
# define BOOST_ITERATOR_NO_MPL_AUX_HAS_XXX // "MPL's has_xxx facility doesn't work"
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_NO_SFINAE) || defined(BOOST_NO_IS_CONVERTIBLE) || defined(BOOST_NO_IS_CONVERTIBLE_TEMPLATE)
|
||||
# define BOOST_NO_STRICT_ITERATOR_INTEROPERABILITY
|
||||
#endif
|
||||
|
||||
# if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
|
||||
# define BOOST_ARG_DEPENDENT_TYPENAME typename
|
||||
# else
|
||||
# define BOOST_ARG_DEPENDENT_TYPENAME
|
||||
# endif
|
||||
|
||||
// no include guard multiple inclusion intended
|
26
include/boost/iterator/detail/config_undef.hpp
Normal file
26
include/boost/iterator/detail/config_undef.hpp
Normal file
@ -0,0 +1,26 @@
|
||||
// (C) Copyright Thomas Witt 2002.
|
||||
// Permission to copy, use, modify,
|
||||
// sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
|
||||
// no include guard multiple inclusion intended
|
||||
|
||||
//
|
||||
// This is a temporary workaround until the bulk of this is
|
||||
// available in boost config.
|
||||
// 23/02/03 thw
|
||||
//
|
||||
|
||||
#undef BOOST_NO_SFINAE
|
||||
#undef BOOST_NO_IS_CONVERTIBLE
|
||||
#undef BOOST_NO_IS_CONVERTIBLE_TEMPLATE
|
||||
#undef BOOST_NO_STRICT_ITERATOR_INTEROPERABILITY
|
||||
#undef BOOST_ARG_DEPENDENT_TYPENAME
|
||||
|
||||
#ifdef BOOST_ITERATOR_CONFIG_DEF
|
||||
# undef BOOST_ITERATOR_CONFIG_DEF
|
||||
#else
|
||||
# error missing or nested #include config_def
|
||||
#endif
|
88
include/boost/iterator/detail/enable_if.hpp
Normal file
88
include/boost/iterator/detail/enable_if.hpp
Normal file
@ -0,0 +1,88 @@
|
||||
// (C) Copyright David Abrahams 2002.
|
||||
// (C) Copyright Jeremy Siek 2002.
|
||||
// (C) Copyright Thomas Witt 2002.
|
||||
// Permission to copy, use, modify,
|
||||
// sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef BOOST_ENABLE_IF_23022003THW_HPP
|
||||
#define BOOST_ENABLE_IF_23022003THW_HPP
|
||||
|
||||
#include <boost/detail/workaround.hpp>
|
||||
#include <boost/mpl/identity.hpp>
|
||||
|
||||
#include <boost/iterator/detail/config_def.hpp>
|
||||
|
||||
//
|
||||
// Boost iterators uses its own enable_if cause we need
|
||||
// special semantics for deficient compilers.
|
||||
// 23/02/03 thw
|
||||
//
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
//
|
||||
// Base machinery for all kinds of enable if
|
||||
//
|
||||
template<bool>
|
||||
struct enabled
|
||||
{
|
||||
template<typename T>
|
||||
struct base
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
};
|
||||
|
||||
//
|
||||
// For compilers that don't support "Substitution Failure Is Not An Error"
|
||||
// enable_if falls back to always enabled. See comments
|
||||
// on operator implementation for consequences.
|
||||
//
|
||||
template<>
|
||||
struct enabled<false>
|
||||
{
|
||||
template<typename T>
|
||||
struct base
|
||||
{
|
||||
#ifdef BOOST_NO_SFINAE
|
||||
|
||||
typedef T type;
|
||||
|
||||
// This way to do it would give a nice error message containing
|
||||
// invalid overload, but has the big disadvantage that
|
||||
// there is no reference to user code in the error message.
|
||||
//
|
||||
// struct invalid_overload;
|
||||
// typedef invalid_overload type;
|
||||
//
|
||||
#endif
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
template <class Cond,
|
||||
class Return>
|
||||
struct enable_if
|
||||
# if !defined(BOOST_NO_SFINAE) && !defined(BOOST_NO_IS_CONVERTIBLE)
|
||||
: enabled<(Cond::value)>::template base<Return>
|
||||
# else
|
||||
: mpl::identity<Return>
|
||||
# endif
|
||||
{
|
||||
# if BOOST_WORKAROUND(BOOST_MSVC, <= 1200)
|
||||
typedef Return type;
|
||||
# endif
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#include <boost/iterator/detail/config_undef.hpp>
|
||||
|
||||
#endif // BOOST_ENABLE_IF_23022003THW_HPP
|
Loading…
x
Reference in New Issue
Block a user