Move from boost-sandbox

[SVN r18959]
This commit is contained in:
Joel de Guzman 2003-07-07 14:20:34 +00:00
parent 53eb5346de
commit 80d9e8e4c1
14 changed files with 3912 additions and 0 deletions

BIN
doc/access.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
doc/access2old.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

188
doc/default.css Normal file
View 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

File diff suppressed because it is too large Load Diff

View 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&amp;</TT> (or <TT>const T&amp;</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&amp;</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&lt;bool&gt;::iterator</TT> is almost a random access iterator, but
the return type is not <TT>bool&amp;</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&lt;bool&gt;</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 &lt;typename Iterator&gt;
struct return_category; // contains: typedef ... type;
template &lt;typename Iterator&gt;
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 &lt;class ReturnTag, class TraversalTag&gt;
struct iterator_tag : cvt_iterator_category&lt;ReturnTag, TraversalTag&gt;::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 &lt;class RC, class TC&gt;
struct cvt_iterator_category
{
<B><I>// Pseudo-code, &lt;= means inherits or same type</I></B>
if (RC &lt;= constant_lvalue_iterator_tag || RC &lt;= mutable_lvalue_iterator_tag) {
if (TC &lt;= random_access_traversal_tag)
typedef random_access_iterator_tag type;
else if (TC &lt;= bidirectional_traversal_tag)
typedef bidirectional_iterator_tag type;
else if (TC &lt;= forward_traversal_tag)
typedef forward_iterator_tag type;
else
error;
} else if (RC &lt;= readable_iterator_tag && RC &lt;= input_traversal_tag)
typedef input_iterator_tag type;
else if (RC &lt;= 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&lt;std::readable_iterator_tag,
std::random_access_traversal_tag&gt; 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 &lt;typename Iterator&gt;
class return_category
{
<B><I>// Pseudo-code</I></B>
typedef iterator_traits&lt;Iterator&gt;::iterator_category tag;
typedef iterator_traits&lt;Iterator&gt;::value_type T;
public:
if (exists(tag::returns)) // must be a new iterator
typedef tag::returns type;
else if (tag &lt;= forward_iterator_tag) {
if (is-const(T))
typedef constant_lvalue_iterator_tag type;
else
typedef mutable_lvalue_iterator_tag type;
} else if (tag &lt;= input_iterator_tag)
typedef readable_iterator_tag type;
else if (tag &lt;= output_iterator_tag)
typedef writable_iterator_tag type;
else
error;
};
template &lt;typename T&gt;
struct return_category&lt;T*&gt;
{
<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 &lt;typename Iterator&gt;
class traversal_category
{
typedef iterator_traits&lt;Iterator&gt;::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 &lt;= random_access_iterator_tag)
typedef random_access_traversal_tag type;
else if (tag &lt;= bidirectional_iterator_tag)
typedef bidirectional_traversal_tag type;
else if (tag &lt;= is_forward_iterator_tag)
typedef forward_traversal_tag type;
else if (tag &lt;= input_iterator_tag)
typedef input_traversal_tag type;
else if (tag &lt;= out_iterator_tag)
typedef output_traversal_tag type;
else
error;
};
template &lt;typename T&gt;
struct traversal_category&lt;T*&gt;
{
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>-&gt; 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>-&gt; Swappable Iterator </TD></TR>
<TR>
<TD>fill</TD>
<TD rowSpan=2>Forward Iterator<BR>-&gt; Forward Traversal Iterator and
Writable Iterator </TD></TR>
<TR>
<TD>generate</TD></TR>
<TR>
<TD>swap_ranges</TD>
<TD rowSpan=2>Forward Iterator<BR>-&gt; Forward Traversal Iterator and
Swappable Iterator </TD></TR>
<TR>
<TD>rotate</TD></TR>
<TR>
<TD>replace</TD>
<TD rowSpan=5>Forward Iterator<BR>-&gt; 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>-&gt; Bidirectional Traversal
Iterator and Swappable Iterator </TD></TR>
<TR>
<TD>partition</TD></TR>
<TR>
<TD>copy_backwards</TD>
<TD>Bidirectional Iterator<BR>-&gt; Bidirectional Traversal Iterator and
Readable Iterator<BR>Bidirectional Iterator<BR>-&gt; Bidirectional
Traversal Iterator and Writable Iterator </TD></TR>
<TR>
<TD>next_permutation</TD>
<TD rowSpan=2>Bidirectional Iterator<BR>-&gt; 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>-&gt; 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>-&gt; Bidirectional Traversal Iterator and
Readable Iterator </TD></TR>
<TR>
<TD>random_shuffle</TD>
<TD rowSpan=9>Random Access Iterator<BR>-&gt; 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&lt;X&gt;::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&lt;X&gt;::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&lt;X&gt;::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&lt;X&gt;::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>&nbsp;</TD>
<TD><TT>std::iterator_traits&lt;X&gt;::reference</TT></TD></TR>
<TR>
<TD>Member access</TD>
<TD><TT>x-&gt;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&lt;X&gt;::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&lt;X&gt;::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&amp;</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&lt;X&gt;::reference</TT></TD>
<TD>The return type of dereferencing the iterator, which must be <TT>const
T&amp;</TT>. </TD></TR><!-- I don't think this is needed
<tr>
<td>Pointer type</td>
<td><tt>std::iterator_traits&lt;X&gt;::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&lt;X&gt;::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>&nbsp;</td>
<td><tt>std::iterator_traits&lt;X&gt;::reference</tt></td>
</tr>
<tr>
<td>Member access</td>
<td><tt>x-&gt;m</tt></td>
<td><tt>T</tt> is a type with a member named <tt>m</tt>.</td>
<td>
&nbsp;
</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&amp;</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&lt;X&gt;::reference</TT></TD>
<TD>The return type of dereferencing the iterator, which must be
<TT>T&amp;</TT>.</TD></TR><!-- I don't think this is necessary
<tr>
<td>Pointer type</td>
<td><tt>std::iterator_traits&lt;X&gt;::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&lt;X&gt;::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>&nbsp;</td>
<td><tt>std::iterator_traits&lt;X&gt;::reference</tt></td>
</tr>
<tr>
<td>Member access</td>
<td><tt>x-&gt;m</tt></td>
<td><tt>T</tt> is a type with a member named <tt>m</tt>.</td>
<td>
&nbsp;
</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&lt;X&gt;::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&lt;X&gt;::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>&nbsp;</TD>
<TD><TT>X&amp;</TT></TD></TR>
<TR>
<TD>Postincrement</TD>
<TD><TT>i++</TT></TD>
<TD>&nbsp;</TD>
<TD>convertible to <TT>const X&amp;</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&lt;X&gt;::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>&nbsp;</TD>
<TD><TT>X&amp;</TT></TD></TR>
<TR>
<TD>Postdecrement</TD>
<TD><TT>i--</TT></TD>
<TD>&nbsp;</TD>
<TD>convertible to <TT>const X&amp;</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>&lt;</TT> is a total ordering
<H3>Associated types</H3>
<TABLE border=1>
<TBODY>
<TR>
<TD>Traversal Category</TD>
<TD><TT>std::traversal_category&lt;X&gt;::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>&nbsp;</TD>
<TD><TT>X&amp;</TT></TD></TR>
<TR>
<TD>Iterator addition</TD>
<TD><TT>i + n</TT> or <TT>n + i</TT></TD>
<TD>&nbsp;</TD>
<TD><TT>X</TT></TD></TR>
<TR>
<TD>Iterator subtraction</TD>
<TD><TT>i -= n</TT></TD>
<TD>&nbsp;</TD>
<TD><TT>X&amp;</TT></TD></TR>
<TR>
<TD>Iterator subtraction</TD>
<TD><TT>i - n</TT></TD>
<TD>&nbsp;</TD>
<TD><TT>X</TT></TD></TR>
<TR>
<TD>Difference</TD>
<TD><TT>i - j</TT></TD>
<TD>&nbsp;</TD>
<TD><TT>std::iterator_traits&lt;X&gt;::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&lt;X&gt;::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
View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

BIN
doc/traversal.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

1
example/Jamfile Normal file
View File

@ -0,0 +1 @@
unit-test ia1 : reverse_iterator.cpp : <sysinclude>../../.. <sysinclude>$(BOOST) ;

View 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;
}

View 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

View 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

View 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

View 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