mirror of
https://github.com/boostorg/iterator.git
synced 2026-08-27 07:37:40 +02:00
Compare commits
240
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6ca935d9fe | ||
|
|
dea89aa823 | ||
|
|
ce5d2ec4b4 | ||
|
|
640379ac34 | ||
|
|
7cbe926f29 | ||
|
|
5113e4fbec | ||
|
|
66183e43f5 | ||
|
|
4247559960 | ||
|
|
c7c6448bd5 | ||
|
|
218778bb94 | ||
|
|
4b4de44736 | ||
|
|
8deb1c20fb | ||
|
|
20e6d71755 | ||
|
|
52f72c2115 | ||
|
|
6b2da49430 | ||
|
|
f46f7f8091 | ||
|
|
22670777b8 | ||
|
|
6270de1db0 | ||
|
|
6e06e4f89e | ||
|
|
eb73b8e0e2 | ||
|
|
7ffe2601a9 | ||
|
|
62b70f57a9 | ||
|
|
cd37eb3bfb | ||
|
|
bda5890235 | ||
|
|
d51c5ebf07 | ||
|
|
6f90b8b161 | ||
|
|
6ec791e3b9 | ||
|
|
20f188d971 | ||
|
|
7273be17c0 | ||
|
|
77a89a0b89 | ||
|
|
4968b50fc2 | ||
|
|
cbeb7f0632 | ||
|
|
abf8390020 | ||
|
|
2c89e2b15a | ||
|
|
3f49409843 | ||
|
|
abafc5d1be | ||
|
|
2b7ed5f7a8 | ||
|
|
f801c39a59 | ||
|
|
bb7ac6bd84 | ||
|
|
f325582c40 | ||
|
|
36feca8a52 | ||
|
|
a5179f6dfc | ||
|
|
f98f3497b8 | ||
|
|
76af84c0e7 | ||
|
|
0f42b93c3b | ||
|
|
19977c757f | ||
|
|
508696a169 | ||
|
|
3ab9da6a99 | ||
|
|
bd3312cdf2 | ||
|
|
87f93ec521 | ||
|
|
afa92675a2 | ||
|
|
ed8c60c20b | ||
|
|
3fe0d4b532 | ||
|
|
8a51271e3b | ||
|
|
52c0d22cff | ||
|
|
e4447b8e83 | ||
|
|
42e873e10c | ||
|
|
57a40c8cd2 | ||
|
|
a982c42303 | ||
|
|
9db269bb5b | ||
|
|
e5eaaf6a55 | ||
|
|
2225787093 | ||
|
|
f19c1c4059 | ||
|
|
b0aef5a66d | ||
|
|
dfc43d81cf | ||
|
|
eda969d7b5 | ||
|
|
4c8415a99f | ||
|
|
1d6f36e35d | ||
|
|
04301ac6e9 | ||
|
|
a1ec9da737 | ||
|
|
e2a47bdbe5 | ||
|
|
2b1fc22b61 | ||
|
|
273ec4b975 | ||
|
|
4716891117 | ||
|
|
80d9e8e4c1 | ||
|
|
53eb5346de | ||
|
|
e28ca345ea | ||
|
|
92d461cda1 | ||
|
|
8dace06f04 | ||
|
|
ef0bff57d3 | ||
|
|
5bacd289b6 | ||
|
|
77c1698c6e | ||
|
|
2c302ee549 | ||
|
|
a586f20d19 | ||
|
|
34c159dd8d | ||
|
|
b22a3adc02 | ||
|
|
4a24e0f401 | ||
|
|
3844edc4bf | ||
|
|
fdd1601ba4 | ||
|
|
e9b33b336c | ||
|
|
2574365b5c | ||
|
|
12b9366f33 | ||
|
|
4772bb099e | ||
|
|
2be5179020 | ||
|
|
8cb49713b4 | ||
|
|
bd666dc0e9 | ||
|
|
57251d58cc | ||
|
|
ebcb4d861a | ||
|
|
15a7a839f9 | ||
|
|
76a307d31e | ||
|
|
37aee7c13b | ||
|
|
50a502bb81 | ||
|
|
8a4839354e | ||
|
|
4da7371246 | ||
|
|
e162a75e53 | ||
|
|
e60df6ad92 | ||
|
|
4c2b3a9d2c | ||
|
|
75023a1dd3 | ||
|
|
79370a6dfb | ||
|
|
4566798afc | ||
|
|
3fd1c4bc5d | ||
|
|
2d6f48d5ab | ||
|
|
d1c7594344 | ||
|
|
ac327f51e9 | ||
|
|
4e18b11263 | ||
|
|
81e3df2b36 | ||
|
|
ac05307515 | ||
|
|
552a1e6785 | ||
|
|
134b8b51aa | ||
|
|
efecfd17b9 | ||
|
|
799158841e | ||
|
|
582ebfd054 | ||
|
|
42e4db1539 | ||
|
|
d7023154a3 | ||
|
|
9582b2223c | ||
|
|
d7908fb81f | ||
|
|
e48cdcb94f | ||
|
|
0846ad5fd0 | ||
|
|
84663ff2e2 | ||
|
|
6de1934420 | ||
|
|
a110b9fd27 | ||
|
|
eb06c122d1 | ||
|
|
cbbe851adb | ||
|
|
f6cc2e520f | ||
|
|
4e29b5aa29 | ||
|
|
d924f56ad8 | ||
|
|
f27fd095f7 | ||
|
|
d22edf735a | ||
|
|
af8dd117d5 | ||
|
|
149d07cda0 | ||
|
|
e9d9bdbb10 | ||
|
|
8d8f828da5 | ||
|
|
fc15f5f710 | ||
|
|
ef66d28b19 | ||
|
|
0c8d74863f | ||
|
|
1c73f1f2ae | ||
|
|
ee20a630dd | ||
|
|
c2472221ef | ||
|
|
bf45977491 | ||
|
|
1988994bd3 | ||
|
|
5482763a93 | ||
|
|
2c2a3eab21 | ||
|
|
dca20fae75 | ||
|
|
e3aaf2cc91 | ||
|
|
ea4c7c7dd9 | ||
|
|
fd6ba58d5e | ||
|
|
268e70faa1 | ||
|
|
170b44763d | ||
|
|
b2701f9f78 | ||
|
|
ad4c5ab089 | ||
|
|
c585adde71 | ||
|
|
c5f24d0d72 | ||
|
|
dbb99b1cf3 | ||
|
|
be44a4714b | ||
|
|
e9f24023d4 | ||
|
|
51616fa845 | ||
|
|
d7884b5613 | ||
|
|
15b5b66776 | ||
|
|
6f90982a45 | ||
|
|
bfda34e9e0 | ||
|
|
5bfc03ed4a | ||
|
|
490bee3a06 | ||
|
|
8174963a45 | ||
|
|
86e183c75e | ||
|
|
a94c9d0db2 | ||
|
|
8a73dcd052 | ||
|
|
8496571204 | ||
|
|
bafe0703a6 | ||
|
|
b05b38810c | ||
|
|
edf17ba001 | ||
|
|
ee9f140fae | ||
|
|
762e603013 | ||
|
|
6eeeb23332 | ||
|
|
07482538ed | ||
|
|
d17e8dae9b | ||
|
|
5e1bc30db9 | ||
|
|
e8389d5f49 | ||
|
|
332f18cf9f | ||
|
|
7aea7b7881 | ||
|
|
3e6796ab91 | ||
|
|
893b5c0e25 | ||
|
|
41c334d718 | ||
|
|
05336f45c4 | ||
|
|
90299982a6 | ||
|
|
93b54c15c8 | ||
|
|
25f9acabac | ||
|
|
bb2ffadade | ||
|
|
b6aa32721f | ||
|
|
8f41e88f85 | ||
|
|
58b56fbabb | ||
|
|
9a4b0b576d | ||
|
|
c948483ec1 | ||
|
|
a31a89ae7d | ||
|
|
b8ccd48fa3 | ||
|
|
cf1d6a30af | ||
|
|
7fa5da6778 | ||
|
|
34a9d4e702 | ||
|
|
42710d0967 | ||
|
|
487acf8c1c | ||
|
|
d6ec67f6ed | ||
|
|
e1b64d45e2 | ||
|
|
4314dd18ae | ||
|
|
b634113daf | ||
|
|
0c68369f23 | ||
|
|
42ddb0d47b | ||
|
|
e6191bc913 | ||
|
|
8cf1b8acb2 | ||
|
|
3852c810f3 | ||
|
|
04c0c043e0 | ||
|
|
ffec5207fa | ||
|
|
31fef5252a | ||
|
|
80bcc4e643 | ||
|
|
87a3007c92 | ||
|
|
ea1513596d | ||
|
|
9d659841a0 | ||
|
|
efcbd24229 | ||
|
|
3692175786 | ||
|
|
d3b8f893bc | ||
|
|
cebe553621 | ||
|
|
b54236986d | ||
|
|
24c3beb791 | ||
|
|
50c9214b82 | ||
|
|
c583cf8730 | ||
|
|
61d2d43ea5 | ||
|
|
76efd2456c | ||
|
|
40b7a3e8aa | ||
|
|
59a54ab5bd | ||
|
|
7b17be08a2 | ||
|
|
bbeeb17041 | ||
|
|
a8d93ccb41 |
Binary file not shown.
|
Before Width: | Height: | Size: 11 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 41 KiB |
-188
@@ -1,188 +0,0 @@
|
||||
/*
|
||||
: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 }
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,822 +0,0 @@
|
||||
<!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>
|
||||
@@ -1,731 +0,0 @@
|
||||
++++++++++++++++++++++
|
||||
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
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 33 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 8.9 KiB |
@@ -1 +0,0 @@
|
||||
unit-test ia1 : reverse_iterator.cpp : <sysinclude>../../.. <sysinclude>$(BOOST) ;
|
||||
@@ -1,16 +0,0 @@
|
||||
#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;
|
||||
}
|
||||
Executable → Regular
+36
-19
@@ -15,7 +15,12 @@
|
||||
|
||||
namespace boost {
|
||||
|
||||
template <class Incrementable, class Category, class Difference> class counting_iterator;
|
||||
template <
|
||||
class Incrementable
|
||||
, class CategoryOrTraversal
|
||||
, class Difference
|
||||
>
|
||||
class counting_iterator;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
@@ -67,35 +72,38 @@ namespace detail
|
||||
};
|
||||
|
||||
BOOST_STATIC_ASSERT(is_numeric<int>::value);
|
||||
template <class Incrementable, class Category, class Difference>
|
||||
|
||||
template <class Incrementable, class CategoryOrTraversal, class Difference>
|
||||
struct counting_iterator_base
|
||||
{
|
||||
typedef typename mpl::apply_if<
|
||||
is_same<Category, use_default>
|
||||
typedef typename detail::ia_dflt_help<
|
||||
CategoryOrTraversal
|
||||
, mpl::apply_if<
|
||||
is_numeric<Incrementable>
|
||||
, mpl::identity<std::random_access_iterator_tag>
|
||||
, BOOST_ITERATOR_CATEGORY<Incrementable>
|
||||
, mpl::identity<random_access_traversal_tag>
|
||||
, iterator_traversal<Incrementable>
|
||||
>
|
||||
, mpl::identity<Category>
|
||||
>::type category;
|
||||
>::type traversal;
|
||||
|
||||
typedef typename mpl::apply_if<
|
||||
is_same<Difference, use_default>
|
||||
typedef typename detail::ia_dflt_help<
|
||||
Difference
|
||||
, mpl::apply_if<
|
||||
is_numeric<Incrementable>
|
||||
, numeric_difference<Incrementable>
|
||||
, iterator_difference<Incrementable>
|
||||
>
|
||||
, mpl::identity<Difference>
|
||||
>::type difference;
|
||||
|
||||
typedef iterator_adaptor<
|
||||
counting_iterator<Incrementable, Category, Difference> // self
|
||||
, Incrementable // Base
|
||||
, Incrementable // value_type
|
||||
, category
|
||||
, Incrementable const& // reference
|
||||
counting_iterator<Incrementable, CategoryOrTraversal, Difference> // self
|
||||
, Incrementable // Base
|
||||
, Incrementable // Value
|
||||
# ifndef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY
|
||||
const // MSVC won't strip this. Instead we enable Thomas'
|
||||
// criterion (see boost/iterator/detail/facade_iterator_category.hpp)
|
||||
# endif
|
||||
, traversal
|
||||
, Incrementable const& // reference
|
||||
, difference
|
||||
> type;
|
||||
};
|
||||
@@ -128,11 +136,20 @@ namespace detail
|
||||
};
|
||||
}
|
||||
|
||||
template <class Incrementable, class Category = use_default, class Difference = use_default>
|
||||
template <
|
||||
class Incrementable
|
||||
, class CategoryOrTraversal = use_default
|
||||
, class Difference = use_default
|
||||
>
|
||||
class counting_iterator
|
||||
: public detail::counting_iterator_base<Incrementable, Category, Difference>::type
|
||||
: public detail::counting_iterator_base<
|
||||
Incrementable, CategoryOrTraversal, Difference
|
||||
>::type
|
||||
{
|
||||
typedef typename detail::counting_iterator_base<Incrementable, Category, Difference>::type super_t;
|
||||
typedef typename detail::counting_iterator_base<
|
||||
Incrementable, CategoryOrTraversal, Difference
|
||||
>::type super_t;
|
||||
|
||||
friend class iterator_core_access;
|
||||
|
||||
public:
|
||||
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
// Copyright David Abrahams 2003. Use, modification and distribution is
|
||||
// subject to the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef ANY_CONVERSION_EATER_DWA20031117_HPP
|
||||
# define ANY_CONVERSION_EATER_DWA20031117_HPP
|
||||
|
||||
namespace boost { namespace detail {
|
||||
|
||||
// This type can be used in traits to "eat" up the one user-defined
|
||||
// implicit conversion allowed.
|
||||
struct any_conversion_eater
|
||||
{
|
||||
template <class T>
|
||||
any_conversion_eater(T const&);
|
||||
};
|
||||
|
||||
}} // namespace boost::detail
|
||||
|
||||
#endif // ANY_CONVERSION_EATER_DWA20031117_HPP
|
||||
@@ -1,338 +1 @@
|
||||
// (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
|
||||
#error obsolete
|
||||
|
||||
@@ -18,7 +18,66 @@
|
||||
#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.
|
||||
#ifdef BOOST_ITERATOR_CONFIG_DEF
|
||||
# error you have nested config_def #inclusion.
|
||||
#else
|
||||
# define BOOST_ITERATOR_CONFIG_DEF
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \
|
||||
|| BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x531))
|
||||
|
||||
// Recall that in general, compilers without partial specialization
|
||||
// can't strip constness. Consider counting_iterator, which normally
|
||||
// passes a const Value to iterator_facade. As a result, any code
|
||||
// which makes a std::vector of the iterator's value_type will fail
|
||||
// when its allocator declares functions overloaded on reference and
|
||||
// const_reference (the same type).
|
||||
//
|
||||
// Furthermore, Borland 5.5.1 drops constness in enough ways that we
|
||||
// end up using a proxy for operator[] when we otherwise shouldn't.
|
||||
// Using reference constness gives it an extra hint that it can
|
||||
// return the value_type from operator[] directly, but is not
|
||||
// strictly neccessary. Not sure how best to resolve this one.
|
||||
|
||||
# define BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY 1
|
||||
|
||||
#endif
|
||||
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) \
|
||||
|| BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x531)) \
|
||||
|| (BOOST_WORKAROUND(BOOST_INTEL_CXX_VERSION, <= 700) && defined(_MSC_VER))
|
||||
# define BOOST_NO_LVALUE_RETURN_DETECTION
|
||||
|
||||
# if 0 // test code
|
||||
struct v {};
|
||||
|
||||
typedef char (&no)[3];
|
||||
|
||||
template <class T>
|
||||
no foo(T const&, ...);
|
||||
|
||||
template <class T>
|
||||
char foo(T&, int);
|
||||
|
||||
|
||||
struct value_iterator
|
||||
{
|
||||
v operator*() const;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct lvalue_deref_helper
|
||||
{
|
||||
static T& x;
|
||||
enum { value = (sizeof(foo(*x,0)) == 1) };
|
||||
};
|
||||
|
||||
int z2[(lvalue_deref_helper<v*>::value == 1) ? 1 : -1];
|
||||
int z[(lvalue_deref_helper<value_iterator>::value) == 1 ? -1 : 1 ];
|
||||
# endif
|
||||
|
||||
#endif
|
||||
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) \
|
||||
|| BOOST_WORKAROUND(__GNUC__, <= 2 && __GNUC_MINOR__ <= 95) \
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#undef BOOST_NO_IS_CONVERTIBLE_TEMPLATE
|
||||
#undef BOOST_NO_STRICT_ITERATOR_INTEROPERABILITY
|
||||
#undef BOOST_ARG_DEPENDENT_TYPENAME
|
||||
#undef BOOST_NO_LVALUE_RETURN_DETECTION
|
||||
|
||||
#ifdef BOOST_ITERATOR_CONFIG_DEF
|
||||
# undef BOOST_ITERATOR_CONFIG_DEF
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
namespace iterators
|
||||
{
|
||||
//
|
||||
// Base machinery for all kinds of enable if
|
||||
@@ -79,7 +79,7 @@ namespace boost
|
||||
# endif
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace iterators
|
||||
|
||||
} // namespace boost
|
||||
|
||||
|
||||
+214
@@ -0,0 +1,214 @@
|
||||
// Copyright David Abrahams 2003. Use, modification and distribution is
|
||||
// subject to the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef FACADE_ITERATOR_CATEGORY_DWA20031118_HPP
|
||||
# define FACADE_ITERATOR_CATEGORY_DWA20031118_HPP
|
||||
|
||||
# include <boost/iterator/iterator_categories.hpp>
|
||||
|
||||
# include <boost/static_assert.hpp>
|
||||
|
||||
# include <boost/mpl/or.hpp> // used in iterator_tag inheritance logic
|
||||
# include <boost/mpl/and.hpp>
|
||||
# include <boost/mpl/if.hpp>
|
||||
# include <boost/mpl/apply_if.hpp>
|
||||
# include <boost/mpl/identity.hpp>
|
||||
|
||||
# include <boost/type_traits/is_same.hpp>
|
||||
# include <boost/type_traits/is_const.hpp>
|
||||
# include <boost/type_traits/is_reference.hpp>
|
||||
# include <boost/type_traits/is_convertible.hpp>
|
||||
|
||||
# include <boost/type_traits/is_same.hpp>
|
||||
|
||||
# include <boost/iterator/detail/config_def.hpp> // try to keep this last
|
||||
|
||||
# ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY
|
||||
# include <boost/python/detail/indirect_traits.hpp>
|
||||
# endif
|
||||
|
||||
//
|
||||
// iterator_category deduction for iterator_facade
|
||||
//
|
||||
|
||||
// forward declaration
|
||||
namespace boost { struct use_default; }
|
||||
|
||||
namespace boost { namespace detail {
|
||||
|
||||
struct input_output_iterator_tag
|
||||
: std::input_iterator_tag
|
||||
{
|
||||
// Using inheritance for only input_iterator_tag helps to avoid
|
||||
// ambiguities when a stdlib implementation dispatches on a
|
||||
// function which is overloaded on both input_iterator_tag and
|
||||
// output_iterator_tag, as STLPort does, in its __valid_range
|
||||
// function. I claim it's better to avoid the ambiguity in these
|
||||
// cases.
|
||||
operator std::output_iterator_tag() const
|
||||
{
|
||||
return std::output_iterator_tag();
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// True iff the user has explicitly disabled writability of this
|
||||
// iterator. Pass the iterator_facade's Value parameter and its
|
||||
// nested ::reference type.
|
||||
//
|
||||
template <class ValueParam, class Reference>
|
||||
struct iterator_writability_disabled
|
||||
# ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY // Adding Thomas' logic?
|
||||
: mpl::or_<
|
||||
is_const<Reference>
|
||||
, python::detail::is_reference_to_const<Reference>
|
||||
, is_const<ValueParam>
|
||||
>
|
||||
# else
|
||||
: is_const<ValueParam>
|
||||
# endif
|
||||
{};
|
||||
|
||||
|
||||
//
|
||||
// Convert an iterator_facade's traversal category, Value parameter,
|
||||
// and ::reference type to an appropriate old-style category.
|
||||
//
|
||||
// If writability has been disabled per the above metafunction, the
|
||||
// result will not be convertible to output_iterator_tag.
|
||||
//
|
||||
// Otherwise, if Traversal == single_pass_traversal_tag, the following
|
||||
// conditions will result in a tag that is convertible both to
|
||||
// input_iterator_tag and output_iterator_tag:
|
||||
//
|
||||
// 1. Reference is a reference to non-const
|
||||
// 2. Reference is not a reference and is convertible to Value
|
||||
//
|
||||
template <class Traversal, class ValueParam, class Reference>
|
||||
struct iterator_facade_default_category
|
||||
: mpl::apply_if<
|
||||
mpl::and_<
|
||||
is_reference<Reference>
|
||||
, is_convertible<Traversal,forward_traversal_tag>
|
||||
>
|
||||
, mpl::apply_if<
|
||||
is_convertible<Traversal,random_access_traversal_tag>
|
||||
, mpl::identity<std::random_access_iterator_tag>
|
||||
, mpl::if_<
|
||||
is_convertible<Traversal,bidirectional_traversal_tag>
|
||||
, std::bidirectional_iterator_tag
|
||||
, std::forward_iterator_tag
|
||||
>
|
||||
>
|
||||
, typename mpl::apply_if<
|
||||
mpl::and_<
|
||||
is_convertible<Traversal, single_pass_traversal_tag>
|
||||
|
||||
, mpl::or_< // check for readability
|
||||
is_same<ValueParam,use_default>
|
||||
, is_convertible<Reference, ValueParam>
|
||||
>
|
||||
>
|
||||
, mpl::if_<
|
||||
iterator_writability_disabled<ValueParam,Reference>
|
||||
, std::input_iterator_tag
|
||||
, input_output_iterator_tag
|
||||
>
|
||||
|
||||
, mpl::identity<std::output_iterator_tag>
|
||||
>
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
// True iff T is convertible to an old-style iterator category.
|
||||
template <class T>
|
||||
struct is_iterator_category
|
||||
: mpl::or_<
|
||||
is_convertible<T,std::input_iterator_tag>
|
||||
, is_convertible<T,std::output_iterator_tag>
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct is_iterator_traversal
|
||||
: is_convertible<T,incrementable_traversal_tag>
|
||||
{};
|
||||
|
||||
//
|
||||
// A composite iterator_category tag convertible to Category (a pure
|
||||
// old-style category) and Traversal (a pure traversal tag).
|
||||
// Traversal must be a strict increase of the traversal power given by
|
||||
// Category.
|
||||
//
|
||||
template <class Category, class Traversal>
|
||||
struct iterator_category_with_traversal
|
||||
: Category, Traversal
|
||||
{
|
||||
# if 0
|
||||
// Because of limitations on multiple user-defined conversions,
|
||||
// this should be a good test of whether convertibility is enough
|
||||
// in the spec, or whether we need to specify inheritance.
|
||||
operator Category() const { return Category(); }
|
||||
operator Traversal() const { return Traversal(); }
|
||||
# endif
|
||||
|
||||
# if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
|
||||
// Make sure this isn't used to build any categories where
|
||||
// convertibility to Traversal is redundant. Should just use the
|
||||
// Category element in that case.
|
||||
BOOST_STATIC_ASSERT(
|
||||
!(is_convertible<
|
||||
typename iterator_category_to_traversal<Category>::type
|
||||
, Traversal
|
||||
>::value));
|
||||
|
||||
BOOST_STATIC_ASSERT(is_iterator_category<Category>::value);
|
||||
BOOST_STATIC_ASSERT(!is_iterator_category<Traversal>::value);
|
||||
BOOST_STATIC_ASSERT(!is_iterator_traversal<Category>::value);
|
||||
BOOST_STATIC_ASSERT(is_iterator_traversal<Traversal>::value);
|
||||
# endif
|
||||
};
|
||||
|
||||
// Computes an iterator_category tag whose traversal is Traversal and
|
||||
// which is appropriate for an iterator
|
||||
template <class Traversal, class ValueParam, class Reference>
|
||||
struct facade_iterator_category_impl
|
||||
{
|
||||
# if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
|
||||
BOOST_STATIC_ASSERT(!is_iterator_category<Traversal>::value);
|
||||
# endif
|
||||
|
||||
typedef typename iterator_facade_default_category<
|
||||
Traversal,ValueParam,Reference
|
||||
>::type category;
|
||||
|
||||
typedef typename mpl::if_<
|
||||
is_same<
|
||||
Traversal
|
||||
, typename iterator_category_to_traversal<category>::type
|
||||
>
|
||||
, category
|
||||
, iterator_category_with_traversal<category,Traversal>
|
||||
>::type type;
|
||||
};
|
||||
|
||||
//
|
||||
// Compute an iterator_category for iterator_facade
|
||||
//
|
||||
template <class CategoryOrTraversal, class ValueParam, class Reference>
|
||||
struct facade_iterator_category
|
||||
: mpl::apply_if<
|
||||
is_iterator_category<CategoryOrTraversal>
|
||||
, mpl::identity<CategoryOrTraversal> // old-style categories are fine as-is
|
||||
, facade_iterator_category_impl<CategoryOrTraversal,ValueParam,Reference>
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
}} // namespace boost::detail
|
||||
|
||||
# include <boost/iterator/detail/config_undef.hpp>
|
||||
|
||||
#endif // FACADE_ITERATOR_CATEGORY_DWA20031118_HPP
|
||||
+98
@@ -0,0 +1,98 @@
|
||||
// Copyright David Abrahams 2003. Use, modification and distribution is
|
||||
// subject to the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef MINIMUM_CATEGORY_DWA20031119_HPP
|
||||
# define MINIMUM_CATEGORY_DWA20031119_HPP
|
||||
|
||||
# include <boost/type_traits/is_convertible.hpp>
|
||||
# include <boost/type_traits/is_same.hpp>
|
||||
|
||||
# include <boost/mpl/aux_/lambda_support.hpp>
|
||||
|
||||
namespace boost { namespace detail {
|
||||
//
|
||||
// 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 <bool GreaterEqual, bool LessEqual>
|
||||
struct minimum_category_impl;
|
||||
|
||||
template <class T1, class T2>
|
||||
struct error_not_related_by_convertibility;
|
||||
|
||||
template <>
|
||||
struct minimum_category_impl<true,false>
|
||||
{
|
||||
template <class T1, class T2> struct apply
|
||||
{
|
||||
typedef T2 type;
|
||||
};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct minimum_category_impl<false,true>
|
||||
{
|
||||
template <class T1, class T2> struct apply
|
||||
{
|
||||
typedef T1 type;
|
||||
};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct minimum_category_impl<true,true>
|
||||
{
|
||||
template <class T1, class T2> struct apply
|
||||
{
|
||||
BOOST_STATIC_ASSERT((is_same<T1,T2>::value));
|
||||
typedef T1 type;
|
||||
};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct minimum_category_impl<false,false>
|
||||
{
|
||||
template <class T1, class T2> struct apply
|
||||
: error_not_related_by_convertibility<T1,T2>
|
||||
{
|
||||
};
|
||||
};
|
||||
|
||||
template <class T1 = mpl::_1, class T2 = mpl::_2>
|
||||
struct minimum_category
|
||||
{
|
||||
typedef minimum_category_impl<
|
||||
::boost::is_convertible<T1,T2>::value
|
||||
, ::boost::is_convertible<T2,T1>::value
|
||||
> outer;
|
||||
|
||||
typedef typename outer::template apply<T1,T2> inner;
|
||||
typedef typename inner::type type;
|
||||
|
||||
BOOST_MPL_AUX_LAMBDA_SUPPORT(2,minimum_category,(T1,T2))
|
||||
};
|
||||
|
||||
template <>
|
||||
struct minimum_category<mpl::_1,mpl::_2>
|
||||
{
|
||||
template <class T1, class T2>
|
||||
struct apply : minimum_category<T1,T2>
|
||||
{};
|
||||
};
|
||||
|
||||
# if BOOST_WORKAROUND(BOOST_MSVC, == 1200)
|
||||
template <>
|
||||
struct minimum_category<int,int>
|
||||
{
|
||||
typedef int type;
|
||||
};
|
||||
# endif
|
||||
|
||||
}} // namespace boost::detail
|
||||
|
||||
#endif // MINIMUM_CATEGORY_DWA20031119_HPP
|
||||
@@ -13,37 +13,42 @@
|
||||
#include <boost/iterator/iterator_adaptor.hpp>
|
||||
#include <boost/iterator/iterator_categories.hpp>
|
||||
|
||||
#include <boost/type_traits/is_class.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
template <class Predicate, class Iterator>
|
||||
class filter_iterator;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class Iterator>
|
||||
struct filter_iterator_category
|
||||
template <class Predicate, class Iterator>
|
||||
struct filter_iterator_base
|
||||
{
|
||||
typedef iterator_tag<
|
||||
typename access_category<Iterator>::type
|
||||
, typename minimum_category<
|
||||
bidirectional_traversal_tag
|
||||
, typename traversal_category<Iterator>::type
|
||||
>::type
|
||||
> type;
|
||||
typedef iterator_adaptor<
|
||||
filter_iterator<Predicate, Iterator>
|
||||
, Iterator
|
||||
, use_default
|
||||
, typename mpl::if_<
|
||||
is_convertible<
|
||||
typename iterator_traversal<Iterator>::type
|
||||
, bidirectional_traversal_tag
|
||||
>
|
||||
, forward_traversal_tag
|
||||
, use_default
|
||||
>::type
|
||||
> type;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
}
|
||||
|
||||
template <class Predicate, class Iterator>
|
||||
class filter_iterator
|
||||
: public iterator_adaptor<
|
||||
filter_iterator<Predicate, Iterator>, Iterator
|
||||
, use_default
|
||||
, typename detail::filter_iterator_category<Iterator>::type
|
||||
>
|
||||
: public detail::filter_iterator_base<Predicate, Iterator>::type
|
||||
{
|
||||
typedef iterator_adaptor<
|
||||
filter_iterator<Predicate, Iterator>, Iterator
|
||||
, use_default
|
||||
, typename detail::filter_iterator_category<Iterator>::type
|
||||
> super_t;
|
||||
typedef typename detail::filter_iterator_base<
|
||||
Predicate, Iterator
|
||||
>::type super_t;
|
||||
|
||||
friend class iterator_core_access;
|
||||
|
||||
@@ -57,8 +62,15 @@ namespace boost
|
||||
}
|
||||
|
||||
filter_iterator(Iterator x, Iterator end = Iterator())
|
||||
: super_t(x), m_predicate(), m_end(end)
|
||||
: super_t(x), m_predicate(), m_end(end)
|
||||
{
|
||||
// Pro8 is a little too aggressive about instantiating the
|
||||
// body of this function.
|
||||
#if !BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003))
|
||||
// Don't allow use of this constructor if Predicate is a
|
||||
// function pointer type, since it will be 0.
|
||||
BOOST_STATIC_ASSERT(is_class<Predicate>::value);
|
||||
#endif
|
||||
satisfy_predicate();
|
||||
}
|
||||
|
||||
@@ -104,6 +116,22 @@ namespace boost
|
||||
return filter_iterator<Predicate,Iterator>(f,x,end);
|
||||
}
|
||||
|
||||
template <class Predicate, class Iterator>
|
||||
filter_iterator<Predicate,Iterator>
|
||||
make_filter_iterator(
|
||||
typename iterators::enable_if<
|
||||
is_class<Predicate>
|
||||
, Iterator
|
||||
>::type x
|
||||
, Iterator end = Iterator()
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, == 1200)
|
||||
, Predicate* = 0
|
||||
#endif
|
||||
)
|
||||
{
|
||||
return filter_iterator<Predicate,Iterator>(x,end);
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_FILTER_ITERATOR_23022003THW_HPP
|
||||
|
||||
@@ -14,11 +14,16 @@
|
||||
|
||||
#include <boost/iterator/iterator_traits.hpp>
|
||||
|
||||
#include <boost/type_traits/remove_cv.hpp>
|
||||
|
||||
#include <boost/python/detail/indirect_traits.hpp>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <boost/mpl/identity.hpp>
|
||||
#include <boost/mpl/apply_if.hpp>
|
||||
#include <boost/mpl/not.hpp>
|
||||
#include <boost/mpl/aux_/has_xxx.hpp>
|
||||
|
||||
#ifdef BOOST_NO_MPL_AUX_HAS_XXX
|
||||
#ifdef BOOST_MPL_NO_AUX_HAS_XXX
|
||||
# include <boost/shared_ptr.hpp>
|
||||
# include <boost/scoped_ptr.hpp>
|
||||
# include <boost/mpl/bool.hpp>
|
||||
@@ -30,8 +35,11 @@
|
||||
namespace boost
|
||||
{
|
||||
template <class Iter, class Value, class Category, class Reference, class Difference>
|
||||
struct indirect_iterator;
|
||||
class indirect_iterator;
|
||||
|
||||
template <class T>
|
||||
struct referent;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
struct unspecified {};
|
||||
@@ -44,7 +52,7 @@ namespace boost
|
||||
// can be used instead with something like
|
||||
// boost/python/pointee.hpp to find the value_type.
|
||||
//
|
||||
# ifndef BOOST_NO_MPL_AUX_HAS_XXX
|
||||
# ifndef BOOST_MPL_NO_AUX_HAS_XXX
|
||||
namespace aux
|
||||
{
|
||||
BOOST_MPL_HAS_XXX_TRAIT_DEF(element_type)
|
||||
@@ -79,9 +87,10 @@ namespace boost
|
||||
: mpl::true_ {};
|
||||
# endif
|
||||
|
||||
// Metafunction returning the nested element_type typedef
|
||||
// Metafunction accessing the nested ::element_type
|
||||
template <class T>
|
||||
struct smart_pointer_value : remove_const<typename T::element_type>
|
||||
struct element_type
|
||||
: mpl::identity<typename T::element_type>
|
||||
{};
|
||||
|
||||
template <class T>
|
||||
@@ -110,37 +119,45 @@ namespace boost
|
||||
struct not_int
|
||||
: not_int_impl<T>::template apply<U> {};
|
||||
|
||||
|
||||
template <class Dereferenceable>
|
||||
struct class_has_element_type
|
||||
: mpl::and_<
|
||||
is_class<Dereferenceable>
|
||||
, has_element_type<Dereferenceable>
|
||||
>
|
||||
{};
|
||||
|
||||
// If the Value parameter is unspecified, we use this metafunction
|
||||
// to deduce the default types
|
||||
template <class Iter, class Value, class Category, class Reference, class Difference>
|
||||
struct indirect_base
|
||||
template <class Dereferenceable>
|
||||
struct default_indirect_value
|
||||
{
|
||||
typedef typename iterator_value<Iter>::type dereferenceable;
|
||||
|
||||
typedef mpl::and_<
|
||||
is_class<dereferenceable>
|
||||
, has_element_type<dereferenceable>
|
||||
> is_smart_ptr;
|
||||
|
||||
typedef typename mpl::apply_if<
|
||||
is_smart_ptr
|
||||
, smart_pointer_value<dereferenceable>
|
||||
, iterator_value<dereferenceable>
|
||||
>::type value_type;
|
||||
typedef typename remove_cv<
|
||||
typename referent<Dereferenceable>::type
|
||||
>::type referent_t;
|
||||
|
||||
typedef typename mpl::if_<
|
||||
mpl::or_<
|
||||
is_smart_ptr
|
||||
, iterator_is_mutable<dereferenceable>
|
||||
class_has_element_type<Dereferenceable>
|
||||
, iterator_is_mutable<Dereferenceable>
|
||||
>
|
||||
, value_type
|
||||
, value_type const
|
||||
>::type cv_value_type;
|
||||
|
||||
, referent_t
|
||||
, referent_t const
|
||||
>::type type;
|
||||
};
|
||||
|
||||
template <class Iter, class Value, class Category, class Reference, class Difference>
|
||||
struct indirect_base
|
||||
{
|
||||
typedef typename iterator_traits<Iter>::value_type dereferenceable;
|
||||
|
||||
typedef iterator_adaptor<
|
||||
indirect_iterator<Iter, Value, Category, Reference, Difference>
|
||||
, Iter
|
||||
, cv_value_type
|
||||
, typename ia_dflt_help<
|
||||
Value, default_indirect_value<dereferenceable>
|
||||
>::type
|
||||
, Category
|
||||
, Reference
|
||||
, Difference
|
||||
@@ -151,6 +168,20 @@ namespace boost
|
||||
struct indirect_base<int, int, int, int, int> {};
|
||||
} // namespace detail
|
||||
|
||||
// User-specializable metafunction which returns the referent of a
|
||||
// dereferenceable type. The default implementation returns
|
||||
// Dereferenceable::element_type if such a member exists (thus
|
||||
// handling the boost smart pointers and auto_ptr), and
|
||||
// iterator_traits<Dereferenceable>::value_type otherwise.
|
||||
template <class Dereferenceable>
|
||||
struct referent
|
||||
: mpl::apply_if<
|
||||
detail::class_has_element_type<Dereferenceable>
|
||||
, detail::element_type<Dereferenceable>
|
||||
, iterator_value<Dereferenceable>
|
||||
>
|
||||
{};
|
||||
|
||||
template <
|
||||
class Iterator
|
||||
, class Value = use_default
|
||||
|
||||
+150
@@ -0,0 +1,150 @@
|
||||
// Copyright David Abrahams 2003. Use, modification and distribution is
|
||||
// subject to the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef IS_LVALUE_ITERATOR_DWA2003112_HPP
|
||||
# define IS_LVALUE_ITERATOR_DWA2003112_HPP
|
||||
|
||||
#include <boost/iterator.hpp>
|
||||
|
||||
#include <boost/detail/workaround.hpp>
|
||||
#include <boost/detail/iterator.hpp>
|
||||
|
||||
#include <boost/iterator/detail/any_conversion_eater.hpp>
|
||||
|
||||
// should be the last #includes
|
||||
#include <boost/type_traits/detail/bool_trait_def.hpp>
|
||||
#include <boost/iterator/detail/config_def.hpp>
|
||||
|
||||
#ifndef BOOST_NO_IS_CONVERTIBLE
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace detail
|
||||
{
|
||||
#ifndef BOOST_NO_LVALUE_RETURN_DETECTION
|
||||
// Calling lvalue_preserver( <expression>, 0 ) returns a reference
|
||||
// to the expression's result if <expression> is an lvalue, or
|
||||
// not_an_lvalue() otherwise.
|
||||
struct not_an_lvalue {};
|
||||
|
||||
template <class T>
|
||||
T& lvalue_preserver(T&, int);
|
||||
|
||||
template <class U>
|
||||
not_an_lvalue lvalue_preserver(U const&, ...);
|
||||
|
||||
# define BOOST_LVALUE_PRESERVER(expr) lvalue_preserver(expr,0)
|
||||
|
||||
#else
|
||||
|
||||
# define BOOST_LVALUE_PRESERVER(expr) expr
|
||||
|
||||
#endif
|
||||
|
||||
// Guts of is_lvalue_iterator. Value is the iterator's value_type
|
||||
// and the result is computed in the nested rebind template.
|
||||
template <class Value>
|
||||
struct is_lvalue_iterator_impl
|
||||
{
|
||||
// Eat implicit conversions so we don't report true for things
|
||||
// convertible to Value const&
|
||||
struct conversion_eater
|
||||
{
|
||||
conversion_eater(Value&);
|
||||
};
|
||||
|
||||
static char tester(conversion_eater, int);
|
||||
static char (& tester(any_conversion_eater, ...) )[2];
|
||||
|
||||
template <class It>
|
||||
struct rebind
|
||||
{
|
||||
static It& x;
|
||||
|
||||
BOOST_STATIC_CONSTANT(
|
||||
bool
|
||||
, value = (
|
||||
sizeof(
|
||||
is_lvalue_iterator_impl<Value>::tester(
|
||||
BOOST_LVALUE_PRESERVER(*x), 0
|
||||
)
|
||||
) == 1
|
||||
)
|
||||
);
|
||||
};
|
||||
};
|
||||
|
||||
#undef BOOST_LVALUE_PRESERVER
|
||||
|
||||
//
|
||||
// void specializations to handle std input and output iterators
|
||||
//
|
||||
template <>
|
||||
struct is_lvalue_iterator_impl<void>
|
||||
{
|
||||
template <class It>
|
||||
struct rebind : boost::mpl::false_
|
||||
{};
|
||||
};
|
||||
|
||||
#ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS
|
||||
template <>
|
||||
struct is_lvalue_iterator_impl<const void>
|
||||
{
|
||||
template <class It>
|
||||
struct rebind : boost::mpl::false_
|
||||
{};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct is_lvalue_iterator_impl<volatile void>
|
||||
{
|
||||
template <class It>
|
||||
struct rebind : boost::mpl::false_
|
||||
{};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct is_lvalue_iterator_impl<const volatile void>
|
||||
{
|
||||
template <class It>
|
||||
struct rebind : boost::mpl::false_
|
||||
{};
|
||||
};
|
||||
#endif
|
||||
|
||||
//
|
||||
// This level of dispatching is required for Borland. We might save
|
||||
// an instantiation by removing it for others.
|
||||
//
|
||||
template <class It>
|
||||
struct is_readable_lvalue_iterator_impl
|
||||
: is_lvalue_iterator_impl<
|
||||
BOOST_DEDUCED_TYPENAME boost::detail::iterator_traits<It>::value_type const
|
||||
>::template rebind<It>
|
||||
{};
|
||||
|
||||
template <class It>
|
||||
struct is_non_const_lvalue_iterator_impl
|
||||
: is_lvalue_iterator_impl<
|
||||
BOOST_DEDUCED_TYPENAME boost::detail::iterator_traits<It>::value_type
|
||||
>::template rebind<It>
|
||||
{};
|
||||
} // namespace detail
|
||||
|
||||
// Define the trait with full mpl lambda capability and various broken
|
||||
// compiler workarounds
|
||||
BOOST_TT_AUX_BOOL_TRAIT_DEF1(
|
||||
is_lvalue_iterator,T,::boost::detail::is_readable_lvalue_iterator_impl<T>::value)
|
||||
|
||||
BOOST_TT_AUX_BOOL_TRAIT_DEF1(
|
||||
is_non_const_lvalue_iterator,T,::boost::detail::is_non_const_lvalue_iterator_impl<T>::value)
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
|
||||
#include <boost/iterator/detail/config_undef.hpp>
|
||||
#include <boost/type_traits/detail/bool_trait_undef.hpp>
|
||||
|
||||
#endif // IS_LVALUE_ITERATOR_DWA2003112_HPP
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
// Copyright David Abrahams 2003. Use, modification and distribution is
|
||||
// subject to the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef IS_READABLE_ITERATOR_DWA2003112_HPP
|
||||
# define IS_READABLE_ITERATOR_DWA2003112_HPP
|
||||
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <boost/detail/iterator.hpp>
|
||||
|
||||
#include <boost/type_traits/detail/bool_trait_def.hpp>
|
||||
#include <boost/iterator/detail/any_conversion_eater.hpp>
|
||||
|
||||
// should be the last #include
|
||||
#include <boost/iterator/detail/config_def.hpp>
|
||||
|
||||
#ifndef BOOST_NO_IS_CONVERTIBLE
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace detail
|
||||
{
|
||||
// Guts of is_readable_iterator. Value is the iterator's value_type
|
||||
// and the result is computed in the nested rebind template.
|
||||
template <class Value>
|
||||
struct is_readable_iterator_impl
|
||||
{
|
||||
static char tester(Value&, int);
|
||||
static char (& tester(any_conversion_eater, ...) )[2];
|
||||
|
||||
template <class It>
|
||||
struct rebind
|
||||
{
|
||||
static It& x;
|
||||
|
||||
BOOST_STATIC_CONSTANT(
|
||||
bool
|
||||
, value = (
|
||||
sizeof(
|
||||
is_readable_iterator_impl<Value>::tester(*x, 1)
|
||||
) == 1
|
||||
)
|
||||
);
|
||||
};
|
||||
};
|
||||
|
||||
#undef BOOST_READABLE_PRESERVER
|
||||
|
||||
//
|
||||
// void specializations to handle std input and output iterators
|
||||
//
|
||||
template <>
|
||||
struct is_readable_iterator_impl<void>
|
||||
{
|
||||
template <class It>
|
||||
struct rebind : boost::mpl::false_
|
||||
{};
|
||||
};
|
||||
|
||||
#ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS
|
||||
template <>
|
||||
struct is_readable_iterator_impl<const void>
|
||||
{
|
||||
template <class It>
|
||||
struct rebind : boost::mpl::false_
|
||||
{};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct is_readable_iterator_impl<volatile void>
|
||||
{
|
||||
template <class It>
|
||||
struct rebind : boost::mpl::false_
|
||||
{};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct is_readable_iterator_impl<const volatile void>
|
||||
{
|
||||
template <class It>
|
||||
struct rebind : boost::mpl::false_
|
||||
{};
|
||||
};
|
||||
#endif
|
||||
|
||||
//
|
||||
// This level of dispatching is required for Borland. We might save
|
||||
// an instantiation by removing it for others.
|
||||
//
|
||||
template <class It>
|
||||
struct is_readable_iterator_impl2
|
||||
: is_readable_iterator_impl<
|
||||
BOOST_DEDUCED_TYPENAME boost::detail::iterator_traits<It>::value_type const
|
||||
>::template rebind<It>
|
||||
{};
|
||||
} // namespace detail
|
||||
|
||||
// Define the trait with full mpl lambda capability and various broken
|
||||
// compiler workarounds
|
||||
BOOST_TT_AUX_BOOL_TRAIT_DEF1(
|
||||
is_readable_iterator,T,::boost::detail::is_readable_iterator_impl2<T>::value)
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
|
||||
#include <boost/iterator/detail/config_undef.hpp>
|
||||
|
||||
#endif // IS_READABLE_ITERATOR_DWA2003112_HPP
|
||||
@@ -26,12 +26,32 @@
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/type_traits/is_convertible.hpp>
|
||||
|
||||
#ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY
|
||||
# include <boost/type_traits/remove_reference.hpp>
|
||||
#else
|
||||
# include <boost/type_traits/add_reference.hpp>
|
||||
#endif
|
||||
|
||||
#include <boost/iterator/detail/config_def.hpp>
|
||||
|
||||
#include <boost/iterator/iterator_traits.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
// Used as a default template argument internally, merely to
|
||||
// indicate "use the default", this can also be passed by users
|
||||
// explicitly in order to specify that the default should be used.
|
||||
struct use_default;
|
||||
|
||||
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
// the incompleteness of use_default causes massive problems for
|
||||
// is_convertible (naturally). This workaround is fortunately not
|
||||
// needed for vc6/vc7.
|
||||
template<class To>
|
||||
struct is_convertible<use_default,To>
|
||||
: mpl::false_ {};
|
||||
# endif
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
@@ -98,7 +118,7 @@ namespace boost
|
||||
// of is_convertible in a few cases.
|
||||
template<typename From, typename To>
|
||||
struct enable_if_convertible
|
||||
: detail::enable_if<
|
||||
: iterators::enable_if<
|
||||
mpl::or_<
|
||||
is_same<From,To>
|
||||
, is_convertible<From, To>
|
||||
@@ -111,7 +131,7 @@ namespace boost
|
||||
|
||||
template<typename From, typename To>
|
||||
struct enable_if_convertible
|
||||
: detail::enable_if<
|
||||
: iterators::enable_if<
|
||||
is_convertible<From, To>
|
||||
, detail::enable_type
|
||||
>
|
||||
@@ -142,46 +162,51 @@ namespace boost
|
||||
class Derived
|
||||
, class Base
|
||||
, class Value
|
||||
, class Category
|
||||
, class Traversal
|
||||
, class Reference
|
||||
, class Difference
|
||||
>
|
||||
struct iterator_adaptor_base
|
||||
{
|
||||
private: // intermediate results
|
||||
typedef typename detail::ia_dflt_help<
|
||||
Category, BOOST_ITERATOR_CATEGORY<Base>
|
||||
>::type category;
|
||||
|
||||
typedef typename detail::ia_dflt_help<
|
||||
Reference
|
||||
, mpl::apply_if<
|
||||
is_same<Value, use_default>
|
||||
, iterator_reference<Base>
|
||||
, mpl::identity<Value&>
|
||||
>
|
||||
>::type reference;
|
||||
|
||||
public: // return type
|
||||
typedef iterator_facade<
|
||||
Derived
|
||||
|
||||
|
||||
# ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY
|
||||
, typename detail::ia_dflt_help<
|
||||
Value
|
||||
, mpl::apply_if<
|
||||
is_same<Reference,use_default>
|
||||
, iterator_value<Base>
|
||||
, remove_reference<Reference>
|
||||
>
|
||||
>::type
|
||||
# else
|
||||
, typename detail::ia_dflt_help<
|
||||
Value, iterator_value<Base>
|
||||
>::type
|
||||
|
||||
, typename access_category_tag<category, reference>::type
|
||||
|
||||
, typename traversal_category_tag<category>::type
|
||||
|
||||
, reference
|
||||
|
||||
# endif
|
||||
|
||||
, typename detail::ia_dflt_help<
|
||||
Traversal
|
||||
, iterator_traversal<Base>
|
||||
>::type
|
||||
|
||||
, typename detail::ia_dflt_help<
|
||||
Reference
|
||||
, mpl::apply_if<
|
||||
is_same<Value,use_default>
|
||||
, iterator_reference<Base>
|
||||
, add_reference<Value>
|
||||
>
|
||||
>::type
|
||||
|
||||
, typename detail::ia_dflt_help<
|
||||
Difference, iterator_difference<Base>
|
||||
>::type
|
||||
>
|
||||
type;
|
||||
};
|
||||
template <class T> int static_assert_convertible_to(T);
|
||||
}
|
||||
|
||||
//
|
||||
@@ -198,8 +223,8 @@ namespace boost
|
||||
// const. If const, a conforming compiler strips constness for the
|
||||
// value_type. If not supplied, iterator_traits<Base>::value_type is used
|
||||
//
|
||||
// Category - the iterator_category of the resulting iterator. If not
|
||||
// supplied, iterator_traits<Base>::iterator_category is used.
|
||||
// Category - the traversal category of the resulting iterator. If not
|
||||
// supplied, iterator_traversal<Base>::type is used.
|
||||
//
|
||||
// Reference - the reference type of the resulting iterator, and in
|
||||
// particular, the result type of operator*(). If not supplied but
|
||||
@@ -213,19 +238,19 @@ namespace boost
|
||||
class Derived
|
||||
, class Base
|
||||
, class Value = use_default
|
||||
, class Category = use_default
|
||||
, class Traversal = use_default
|
||||
, class Reference = use_default
|
||||
, class Difference = use_default
|
||||
>
|
||||
class iterator_adaptor
|
||||
: public detail::iterator_adaptor_base<
|
||||
Derived, Base, Value, Category, Reference, Difference
|
||||
Derived, Base, Value, Traversal, Reference, Difference
|
||||
>::type
|
||||
{
|
||||
friend class iterator_core_access;
|
||||
|
||||
typedef typename detail::iterator_adaptor_base<
|
||||
Derived, Base, Value, Category, Reference, Difference
|
||||
Derived, Base, Value, Traversal, Reference, Difference
|
||||
>::type super_t;
|
||||
|
||||
public:
|
||||
@@ -270,28 +295,26 @@ namespace boost
|
||||
// );
|
||||
return m_iterator == x.base();
|
||||
}
|
||||
|
||||
|
||||
typedef typename iterator_category_to_traversal<
|
||||
typename super_t::iterator_category
|
||||
>::type my_traversal;
|
||||
|
||||
# define BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL(cat) \
|
||||
typedef int assertion[sizeof(detail::static_assert_convertible_to<cat>(my_traversal()))];
|
||||
// BOOST_STATIC_ASSERT((is_convertible<my_traversal,cat>::value));
|
||||
|
||||
void advance(typename super_t::difference_type n)
|
||||
{
|
||||
BOOST_STATIC_ASSERT(
|
||||
(detail::is_tag<
|
||||
random_access_traversal_tag
|
||||
, BOOST_ARG_DEPENDENT_TYPENAME super_t::iterator_category::traversal
|
||||
>::value)
|
||||
);
|
||||
BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL(random_access_traversal_tag)
|
||||
m_iterator += n;
|
||||
}
|
||||
|
||||
void increment() { ++m_iterator; }
|
||||
|
||||
void decrement()
|
||||
{
|
||||
BOOST_STATIC_ASSERT(
|
||||
(detail::is_tag<
|
||||
bidirectional_traversal_tag
|
||||
, BOOST_ARG_DEPENDENT_TYPENAME super_t::iterator_category::traversal
|
||||
>::value)
|
||||
);
|
||||
{
|
||||
BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL(bidirectional_traversal_tag)
|
||||
--m_iterator;
|
||||
}
|
||||
|
||||
@@ -301,12 +324,7 @@ namespace boost
|
||||
typename super_t::difference_type distance_to(
|
||||
iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D> const& y) const
|
||||
{
|
||||
BOOST_STATIC_ASSERT(
|
||||
(detail::is_tag<
|
||||
random_access_traversal_tag
|
||||
, BOOST_ARG_DEPENDENT_TYPENAME super_t::iterator_category::traversal
|
||||
>::value)
|
||||
);
|
||||
BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL(random_access_traversal_tag)
|
||||
// Maybe readd with same_distance
|
||||
// BOOST_STATIC_ASSERT(
|
||||
// (detail::same_category_and_difference<Derived,OtherDerived>::value)
|
||||
@@ -314,6 +332,8 @@ namespace boost
|
||||
return y.base() - m_iterator;
|
||||
}
|
||||
|
||||
# undef BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL
|
||||
|
||||
private: // data members
|
||||
Base m_iterator;
|
||||
};
|
||||
|
||||
@@ -8,341 +8,449 @@
|
||||
#define BOOST_ITERATOR_ARCHETYPES_HPP
|
||||
|
||||
#include <boost/iterator/iterator_categories.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/mpl/and.hpp>
|
||||
#include <boost/operators.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/iterator.hpp>
|
||||
|
||||
#include <boost/iterator/detail/facade_iterator_category.hpp>
|
||||
|
||||
#include <boost/type_traits/is_const.hpp>
|
||||
#include <boost/type_traits/add_const.hpp>
|
||||
#include <boost/type_traits/remove_const.hpp>
|
||||
#include <boost/type_traits/remove_cv.hpp>
|
||||
|
||||
#include <boost/mpl/aux_/msvc_eti_base.hpp>
|
||||
#include <boost/mpl/bitand.hpp>
|
||||
#include <boost/mpl/int.hpp>
|
||||
#include <boost/mpl/equal_to.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/mpl/apply_if.hpp>
|
||||
#include <boost/mpl/and.hpp>
|
||||
#include <boost/mpl/identity.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace boost
|
||||
namespace boost {
|
||||
|
||||
template <class Value, class AccessCategory>
|
||||
struct access_archetype;
|
||||
|
||||
template <class Derived, class Value, class AccessCategory, class TraversalCategory>
|
||||
struct traversal_archetype;
|
||||
|
||||
namespace iterator_archetypes
|
||||
{
|
||||
enum {
|
||||
readable_iterator_bit = 1
|
||||
, writable_iterator_bit = 2
|
||||
, swappable_iterator_bit = 4
|
||||
, lvalue_iterator_bit = 8
|
||||
};
|
||||
|
||||
template <class Value, class AccessCategory>
|
||||
struct access_archetype;
|
||||
// Not quite tags, since dispatching wouldn't work.
|
||||
typedef mpl::int_<readable_iterator_bit>::type readable_iterator_t;
|
||||
typedef mpl::int_<writable_iterator_bit>::type writable_iterator_t;
|
||||
|
||||
typedef mpl::int_<
|
||||
(readable_iterator_bit|writable_iterator_bit)
|
||||
>::type readable_writable_iterator_t;
|
||||
|
||||
typedef mpl::int_<
|
||||
(readable_iterator_bit|lvalue_iterator_bit)
|
||||
>::type readable_lvalue_iterator_t;
|
||||
|
||||
typedef mpl::int_<
|
||||
(lvalue_iterator_bit|writable_iterator_bit)
|
||||
>::type writable_lvalue_iterator_t;
|
||||
|
||||
typedef mpl::int_<swappable_iterator_bit>::type swappable_iterator_t;
|
||||
typedef mpl::int_<lvalue_iterator_bit>::type lvalue_iterator_t;
|
||||
|
||||
template <class Derived, class Value, class AccessCategory, class TraversalCategory>
|
||||
struct traversal_archetype;
|
||||
template <class Derived, class Base>
|
||||
struct has_access
|
||||
: mpl::equal_to<
|
||||
mpl::bitand_<Derived,Base>
|
||||
, Base
|
||||
>
|
||||
{};
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <class T>
|
||||
struct assign_proxy
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template <class T>
|
||||
struct assign_proxy
|
||||
{
|
||||
assign_proxy& operator=(T);
|
||||
};
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct read_write_proxy :
|
||||
assign_proxy<T>
|
||||
{
|
||||
template <class T>
|
||||
struct read_proxy
|
||||
{
|
||||
operator T();
|
||||
};
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct arrow_proxy
|
||||
{
|
||||
template <class T>
|
||||
struct read_write_proxy
|
||||
: assign_proxy<T>
|
||||
, read_proxy<T>
|
||||
{
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct arrow_proxy
|
||||
{
|
||||
T const* operator->() const;
|
||||
};
|
||||
};
|
||||
|
||||
struct no_operator_brackets {};
|
||||
struct no_operator_brackets {};
|
||||
|
||||
template <class ValueType>
|
||||
struct readable_operator_brackets
|
||||
{
|
||||
ValueType operator[](std::ptrdiff_t n) const;
|
||||
};
|
||||
template <class ValueType>
|
||||
struct readable_operator_brackets
|
||||
{
|
||||
read_proxy<ValueType> operator[](std::ptrdiff_t n) const;
|
||||
};
|
||||
|
||||
template <class ValueType>
|
||||
struct writable_operator_brackets
|
||||
{
|
||||
template <class ValueType>
|
||||
struct writable_operator_brackets
|
||||
{
|
||||
read_write_proxy<ValueType> operator[](std::ptrdiff_t n) const;
|
||||
};
|
||||
};
|
||||
|
||||
template <class Value, class AccessCategory, class TraversalCategory>
|
||||
struct operator_brackets :
|
||||
mpl::if_< is_tag<random_access_traversal_tag, TraversalCategory>,
|
||||
mpl::if_< is_tag<writable_iterator_tag, AccessCategory>,
|
||||
writable_operator_brackets< Value >,
|
||||
mpl::if_< is_tag<readable_iterator_tag, AccessCategory>,
|
||||
readable_operator_brackets<Value>,
|
||||
no_operator_brackets > >,
|
||||
no_operator_brackets >::type
|
||||
{
|
||||
};
|
||||
template <class Value, class AccessCategory, class TraversalCategory>
|
||||
struct operator_brackets
|
||||
: mpl::aux::msvc_eti_base<
|
||||
typename mpl::apply_if<
|
||||
is_convertible<TraversalCategory, random_access_traversal_tag>
|
||||
, mpl::apply_if<
|
||||
iterator_archetypes::has_access<
|
||||
AccessCategory
|
||||
, iterator_archetypes::writable_iterator_t
|
||||
>
|
||||
, mpl::identity<writable_operator_brackets<Value> >
|
||||
, mpl::if_<
|
||||
iterator_archetypes::has_access<
|
||||
AccessCategory
|
||||
, iterator_archetypes::readable_iterator_t
|
||||
>
|
||||
, readable_operator_brackets<Value>
|
||||
, no_operator_brackets
|
||||
>
|
||||
>
|
||||
, mpl::identity<no_operator_brackets>
|
||||
>::type
|
||||
>::type
|
||||
{};
|
||||
|
||||
template <class TraversalCategory>
|
||||
struct traversal_archetype_impl
|
||||
{
|
||||
template <class Derived,class Value> struct archetype;
|
||||
};
|
||||
|
||||
template <class TraversalCategory>
|
||||
struct traversal_archetype_impl
|
||||
{
|
||||
template <class Derived,class Value> struct archetype;
|
||||
};
|
||||
template <class Derived, class Value, class TraversalCategory>
|
||||
struct traversal_archetype_
|
||||
: mpl::aux::msvc_eti_base<
|
||||
typename traversal_archetype_impl<TraversalCategory>::template archetype<Derived,Value>
|
||||
>::type
|
||||
{};
|
||||
|
||||
template <class Derived, class Value, class TraversalCategory>
|
||||
struct traversal_archetype_
|
||||
: mpl::aux::msvc_eti_base<
|
||||
typename traversal_archetype_impl<TraversalCategory>::template archetype<Derived,Value>
|
||||
>::type
|
||||
{};
|
||||
template <>
|
||||
struct traversal_archetype_impl<incrementable_traversal_tag>
|
||||
{
|
||||
template<class Derived, class Value>
|
||||
struct archetype
|
||||
{
|
||||
typedef void difference_type;
|
||||
|
||||
template <>
|
||||
struct traversal_archetype_impl<incrementable_traversal_tag>
|
||||
{
|
||||
template<class Derived, class Value>
|
||||
struct archetype
|
||||
{
|
||||
typedef void difference_type;
|
||||
Derived& operator++();
|
||||
Derived operator++(int) const;
|
||||
};
|
||||
};
|
||||
|
||||
Derived& operator++();
|
||||
Derived operator++(int) const;
|
||||
};
|
||||
};
|
||||
template <>
|
||||
struct traversal_archetype_impl<single_pass_traversal_tag>
|
||||
{
|
||||
template<class Derived, class Value>
|
||||
struct archetype
|
||||
: public equality_comparable< traversal_archetype_<Derived, Value, single_pass_traversal_tag> >,
|
||||
public traversal_archetype_<Derived, Value, incrementable_traversal_tag>
|
||||
{
|
||||
};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct traversal_archetype_impl<single_pass_traversal_tag>
|
||||
{
|
||||
template<class Derived, class Value>
|
||||
struct archetype
|
||||
: public equality_comparable< traversal_archetype_<Derived, Value, single_pass_traversal_tag> >,
|
||||
public traversal_archetype_<Derived, Value, incrementable_traversal_tag>
|
||||
{
|
||||
};
|
||||
};
|
||||
|
||||
template <class Derived, class Value>
|
||||
bool operator==(traversal_archetype_<Derived, Value, single_pass_traversal_tag> const&,
|
||||
traversal_archetype_<Derived, Value, single_pass_traversal_tag> const&);
|
||||
template <class Derived, class Value>
|
||||
bool operator==(traversal_archetype_<Derived, Value, single_pass_traversal_tag> const&,
|
||||
traversal_archetype_<Derived, Value, single_pass_traversal_tag> const&);
|
||||
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
|
||||
// doesn't seem to pick up != from equality_comparable
|
||||
template <class Derived, class Value>
|
||||
bool operator!=(traversal_archetype_<Derived, Value, single_pass_traversal_tag> const&,
|
||||
traversal_archetype_<Derived, Value, single_pass_traversal_tag> const&);
|
||||
template <class Derived, class Value>
|
||||
bool operator!=(traversal_archetype_<Derived, Value, single_pass_traversal_tag> const&,
|
||||
traversal_archetype_<Derived, Value, single_pass_traversal_tag> const&);
|
||||
#endif
|
||||
template <>
|
||||
struct traversal_archetype_impl<forward_traversal_tag>
|
||||
{
|
||||
template<class Derived, class Value>
|
||||
struct archetype
|
||||
: public traversal_archetype_<Derived, Value, single_pass_traversal_tag>
|
||||
{
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
};
|
||||
};
|
||||
template <>
|
||||
struct traversal_archetype_impl<forward_traversal_tag>
|
||||
{
|
||||
template<class Derived, class Value>
|
||||
struct archetype
|
||||
: public traversal_archetype_<Derived, Value, single_pass_traversal_tag>
|
||||
{
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct traversal_archetype_impl<bidirectional_traversal_tag>
|
||||
{
|
||||
template<class Derived, class Value>
|
||||
struct archetype
|
||||
: public traversal_archetype_<Derived, Value, forward_traversal_tag>
|
||||
{
|
||||
Derived& operator--();
|
||||
Derived operator--(int) const;
|
||||
};
|
||||
};
|
||||
template <>
|
||||
struct traversal_archetype_impl<bidirectional_traversal_tag>
|
||||
{
|
||||
template<class Derived, class Value>
|
||||
struct archetype
|
||||
: public traversal_archetype_<Derived, Value, forward_traversal_tag>
|
||||
{
|
||||
Derived& operator--();
|
||||
Derived operator--(int) const;
|
||||
};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct traversal_archetype_impl<random_access_traversal_tag>
|
||||
{
|
||||
template<class Derived, class Value>
|
||||
struct archetype
|
||||
: public partially_ordered<traversal_archetype_<Derived, Value, random_access_traversal_tag> >,
|
||||
public traversal_archetype_<Derived, Value, bidirectional_traversal_tag>
|
||||
{
|
||||
Derived& operator+=(std::ptrdiff_t);
|
||||
Derived& operator-=(std::ptrdiff_t);
|
||||
};
|
||||
};
|
||||
template <>
|
||||
struct traversal_archetype_impl<random_access_traversal_tag>
|
||||
{
|
||||
template<class Derived, class Value>
|
||||
struct archetype
|
||||
: public partially_ordered<traversal_archetype_<Derived, Value, random_access_traversal_tag> >,
|
||||
public traversal_archetype_<Derived, Value, bidirectional_traversal_tag>
|
||||
{
|
||||
Derived& operator+=(std::ptrdiff_t);
|
||||
Derived& operator-=(std::ptrdiff_t);
|
||||
};
|
||||
};
|
||||
|
||||
template <class Derived, class Value>
|
||||
Derived& operator+(traversal_archetype_<Derived, Value, random_access_traversal_tag> const&,
|
||||
std::ptrdiff_t);
|
||||
template <class Derived, class Value>
|
||||
Derived& operator+(traversal_archetype_<Derived, Value, random_access_traversal_tag> const&,
|
||||
std::ptrdiff_t);
|
||||
|
||||
template <class Derived, class Value>
|
||||
Derived& operator+(std::ptrdiff_t,
|
||||
traversal_archetype_<Derived, Value, random_access_traversal_tag> const&);
|
||||
template <class Derived, class Value>
|
||||
Derived& operator+(std::ptrdiff_t,
|
||||
traversal_archetype_<Derived, Value, random_access_traversal_tag> const&);
|
||||
|
||||
template <class Derived, class Value>
|
||||
Derived& operator-(traversal_archetype_<Derived, Value, random_access_traversal_tag> const&,
|
||||
std::ptrdiff_t);
|
||||
template <class Derived, class Value>
|
||||
Derived& operator-(traversal_archetype_<Derived, Value, random_access_traversal_tag> const&,
|
||||
std::ptrdiff_t);
|
||||
|
||||
template <class Derived, class Value>
|
||||
std::ptrdiff_t operator-(traversal_archetype_<Derived, Value, random_access_traversal_tag> const&,
|
||||
traversal_archetype_<Derived, Value, random_access_traversal_tag> const&);
|
||||
template <class Derived, class Value>
|
||||
std::ptrdiff_t operator-(traversal_archetype_<Derived, Value, random_access_traversal_tag> const&,
|
||||
traversal_archetype_<Derived, Value, random_access_traversal_tag> const&);
|
||||
|
||||
template <class Derived, class Value>
|
||||
bool operator<(traversal_archetype_<Derived, Value, random_access_traversal_tag> const&,
|
||||
traversal_archetype_<Derived, Value, random_access_traversal_tag> const&);
|
||||
template <class Derived, class Value>
|
||||
bool operator<(traversal_archetype_<Derived, Value, random_access_traversal_tag> const&,
|
||||
traversal_archetype_<Derived, Value, random_access_traversal_tag> const&);
|
||||
|
||||
struct bogus_type;
|
||||
struct bogus_type;
|
||||
|
||||
template <class Value>
|
||||
struct convertible_type
|
||||
: mpl::if_< is_const<Value>,
|
||||
typename remove_const<Value>::type,
|
||||
bogus_type >
|
||||
{};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
|
||||
template <class> struct undefined;
|
||||
|
||||
template <class AccessCategory>
|
||||
struct iterator_access_archetype_impl
|
||||
{
|
||||
template <class Value> struct archetype;
|
||||
};
|
||||
|
||||
template <class Value, class AccessCategory>
|
||||
struct iterator_access_archetype
|
||||
: mpl::aux::msvc_eti_base<
|
||||
typename iterator_access_archetype_impl<
|
||||
AccessCategory
|
||||
>::template archetype<Value>
|
||||
>::type
|
||||
{
|
||||
};
|
||||
|
||||
template <>
|
||||
struct iterator_access_archetype_impl<
|
||||
iterator_archetypes::readable_iterator_t
|
||||
>
|
||||
{
|
||||
template <class Value>
|
||||
struct convertible_type
|
||||
: mpl::if_< is_const<Value>,
|
||||
typename remove_const<Value>::type,
|
||||
bogus_type >
|
||||
{};
|
||||
struct archetype
|
||||
{
|
||||
typedef typename remove_cv<Value>::type value_type;
|
||||
typedef Value reference;
|
||||
typedef Value* pointer;
|
||||
|
||||
} // namespace detail
|
||||
value_type operator*() const;
|
||||
|
||||
detail::arrow_proxy<Value> operator->() const;
|
||||
};
|
||||
};
|
||||
|
||||
template <class> struct undefined;
|
||||
|
||||
template <class AccessCategory>
|
||||
struct access_archetype_impl
|
||||
{
|
||||
template <class Value> struct archetype;
|
||||
};
|
||||
|
||||
template <class Value, class AccessCategory>
|
||||
struct access_archetype
|
||||
: mpl::aux::msvc_eti_base<
|
||||
typename access_archetype_impl<AccessCategory>::template archetype<Value>
|
||||
>::type
|
||||
{
|
||||
};
|
||||
|
||||
template <>
|
||||
struct access_archetype_impl<readable_iterator_tag>
|
||||
{
|
||||
template <class Value>
|
||||
struct archetype
|
||||
{
|
||||
typedef typename remove_cv<Value>::type value_type;
|
||||
typedef Value reference;
|
||||
typedef Value* pointer;
|
||||
|
||||
value_type operator*() const;
|
||||
|
||||
detail::arrow_proxy<Value> operator->() const;
|
||||
};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct access_archetype_impl<writable_iterator_tag>
|
||||
{
|
||||
template <class Value>
|
||||
struct archetype
|
||||
{
|
||||
template <>
|
||||
struct iterator_access_archetype_impl<
|
||||
iterator_archetypes::writable_iterator_t
|
||||
>
|
||||
{
|
||||
template <class Value>
|
||||
struct archetype
|
||||
{
|
||||
# if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
|
||||
BOOST_STATIC_ASSERT(!is_const<Value>::value);
|
||||
BOOST_STATIC_ASSERT(!is_const<Value>::value);
|
||||
# endif
|
||||
typedef void value_type;
|
||||
typedef void reference;
|
||||
typedef void pointer;
|
||||
typedef void value_type;
|
||||
typedef void reference;
|
||||
typedef void pointer;
|
||||
|
||||
detail::assign_proxy<Value> operator*() const;
|
||||
};
|
||||
};
|
||||
detail::assign_proxy<Value> operator*() const;
|
||||
};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct access_archetype_impl<readable_writable_iterator_tag>
|
||||
{
|
||||
template <class Value>
|
||||
struct archetype
|
||||
: public virtual access_archetype<Value, readable_iterator_tag>
|
||||
{
|
||||
typedef detail::read_write_proxy<Value> reference;
|
||||
|
||||
detail::read_write_proxy<Value> operator*() const;
|
||||
};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct access_archetype_impl<readable_lvalue_iterator_tag>
|
||||
{
|
||||
template <class Value>
|
||||
struct archetype
|
||||
: public virtual access_archetype<Value, readable_iterator_tag>
|
||||
{
|
||||
typedef Value& reference;
|
||||
|
||||
Value& operator*() const;
|
||||
Value* operator->() const;
|
||||
};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct access_archetype_impl<writable_lvalue_iterator_tag>
|
||||
{
|
||||
template <class Value>
|
||||
struct archetype
|
||||
: public virtual access_archetype<Value, readable_lvalue_iterator_tag>
|
||||
{
|
||||
# if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
|
||||
BOOST_STATIC_ASSERT((!is_const<Value>::value));
|
||||
# endif
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
template <class Value, class AccessCategory, class TraversalCategory>
|
||||
struct iterator_archetype;
|
||||
|
||||
template <class Value, class AccessCategory, class TraversalCategory>
|
||||
struct traversal_archetype_base
|
||||
: detail::operator_brackets<
|
||||
typename remove_cv<Value>::type
|
||||
, AccessCategory
|
||||
, TraversalCategory
|
||||
>
|
||||
, detail::traversal_archetype_<
|
||||
iterator_archetype<Value, AccessCategory, TraversalCategory>
|
||||
, Value
|
||||
, TraversalCategory
|
||||
template <>
|
||||
struct iterator_access_archetype_impl<
|
||||
iterator_archetypes::readable_writable_iterator_t
|
||||
>
|
||||
{
|
||||
template <class Value>
|
||||
struct archetype
|
||||
: public virtual iterator_access_archetype<
|
||||
Value, iterator_archetypes::readable_iterator_t
|
||||
>
|
||||
{
|
||||
};
|
||||
{
|
||||
typedef detail::read_write_proxy<Value> reference;
|
||||
|
||||
template <class Value, class AccessCategory, class TraversalCategory>
|
||||
struct iterator_archetype
|
||||
: public traversal_archetype_base<Value, AccessCategory, TraversalCategory>
|
||||
, public access_archetype<Value, AccessCategory>
|
||||
detail::read_write_proxy<Value> operator*() const;
|
||||
};
|
||||
};
|
||||
|
||||
// These broken libraries require derivation from std::iterator
|
||||
// (or related magic) in order to handle iter_swap and other
|
||||
// iterator operations
|
||||
# if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, < 310) \
|
||||
|| BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(0x20101))
|
||||
, public std::iterator<
|
||||
iterator_tag<AccessCategory,TraversalCategory>
|
||||
, typename access_archetype<Value, AccessCategory>::value_type
|
||||
, typename traversal_archetype_base<
|
||||
Value, AccessCategory, TraversalCategory
|
||||
>::difference_type
|
||||
>
|
||||
template <>
|
||||
struct iterator_access_archetype_impl<iterator_archetypes::readable_lvalue_iterator_t>
|
||||
{
|
||||
template <class Value>
|
||||
struct archetype
|
||||
: public virtual iterator_access_archetype<
|
||||
Value, iterator_archetypes::readable_iterator_t
|
||||
>
|
||||
{
|
||||
typedef Value& reference;
|
||||
|
||||
Value& operator*() const;
|
||||
Value* operator->() const;
|
||||
};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct iterator_access_archetype_impl<iterator_archetypes::writable_lvalue_iterator_t>
|
||||
{
|
||||
template <class Value>
|
||||
struct archetype
|
||||
: public virtual iterator_access_archetype<
|
||||
Value, iterator_archetypes::readable_lvalue_iterator_t
|
||||
>
|
||||
{
|
||||
# if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
|
||||
BOOST_STATIC_ASSERT((!is_const<Value>::value));
|
||||
# endif
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
template <class Value, class AccessCategory, class TraversalCategory>
|
||||
struct iterator_archetype;
|
||||
|
||||
template <class Value, class AccessCategory, class TraversalCategory>
|
||||
struct traversal_archetype_base
|
||||
: detail::operator_brackets<
|
||||
typename remove_cv<Value>::type
|
||||
, AccessCategory
|
||||
, TraversalCategory
|
||||
>
|
||||
, detail::traversal_archetype_<
|
||||
iterator_archetype<Value, AccessCategory, TraversalCategory>
|
||||
, Value
|
||||
, TraversalCategory
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class Value, class AccessCategory, class TraversalCategory>
|
||||
struct iterator_archetype_base
|
||||
: iterator_access_archetype<Value, AccessCategory>
|
||||
, traversal_archetype_base<Value, AccessCategory, TraversalCategory>
|
||||
{
|
||||
// Derivation from std::iterator above caused ambiguity, so now
|
||||
// we have to declare all the types here.
|
||||
typedef iterator_access_archetype<Value, AccessCategory> access;
|
||||
|
||||
typedef typename detail::facade_iterator_category<
|
||||
TraversalCategory
|
||||
, typename mpl::apply_if<
|
||||
iterator_archetypes::has_access<
|
||||
AccessCategory, iterator_archetypes::writable_iterator_t
|
||||
>
|
||||
, remove_const<Value>
|
||||
, add_const<Value>
|
||||
>::type
|
||||
, typename access::reference
|
||||
>::type iterator_category;
|
||||
|
||||
// Needed for some broken libraries (see below)
|
||||
typedef boost::iterator<
|
||||
iterator_category
|
||||
, Value
|
||||
, typename traversal_archetype_base<
|
||||
Value, AccessCategory, TraversalCategory
|
||||
>::difference_type
|
||||
, typename access::pointer
|
||||
, typename access::reference
|
||||
> workaround_iterator_base;
|
||||
};
|
||||
}
|
||||
|
||||
template <class Value, class AccessCategory, class TraversalCategory>
|
||||
struct iterator_archetype
|
||||
: public detail::iterator_archetype_base<Value, AccessCategory, TraversalCategory>
|
||||
|
||||
// These broken libraries require derivation from std::iterator
|
||||
// (or related magic) in order to handle iter_swap and other
|
||||
// iterator operations
|
||||
# if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, < 310) \
|
||||
|| BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(0x20101))
|
||||
typedef typename access_archetype<Value, AccessCategory>::value_type value_type;
|
||||
|
||||
typedef typename access_archetype<Value, AccessCategory>::pointer pointer;
|
||||
|
||||
typedef typename access_archetype<Value, AccessCategory>::reference reference;
|
||||
|
||||
typedef typename traversal_archetype_base<
|
||||
Value, AccessCategory, TraversalCategory
|
||||
>::difference_type difference_type;
|
||||
, public detail::iterator_archetype_base<
|
||||
Value, AccessCategory, TraversalCategory
|
||||
>::workaround_iterator_base
|
||||
# endif
|
||||
{
|
||||
// Derivation from std::iterator above caused references to nested
|
||||
// types to be ambiguous, so now we have to redeclare them all
|
||||
// here.
|
||||
# if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, < 310) \
|
||||
|| BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(0x20101))
|
||||
|
||||
typedef detail::iterator_archetype_base<
|
||||
Value,AccessCategory,TraversalCategory
|
||||
> base;
|
||||
|
||||
typedef typename base::value_type value_type;
|
||||
typedef typename base::reference reference;
|
||||
typedef typename base::pointer pointer;
|
||||
typedef typename base::difference_type difference_type;
|
||||
typedef typename base::iterator_category iterator_category;
|
||||
# endif
|
||||
|
||||
typedef iterator_tag<AccessCategory, TraversalCategory> iterator_category;
|
||||
|
||||
iterator_archetype();
|
||||
iterator_archetype(iterator_archetype const&);
|
||||
iterator_archetype();
|
||||
iterator_archetype(iterator_archetype const&);
|
||||
|
||||
iterator_archetype& operator=(iterator_archetype const&);
|
||||
iterator_archetype& operator=(iterator_archetype const&);
|
||||
|
||||
// Optional conversion from mutable
|
||||
// iterator_archetype(iterator_archetype<typename detail::convertible_type<Value>::type, AccessCategory, TraversalCategory> const&);
|
||||
};
|
||||
// Optional conversion from mutable
|
||||
// iterator_archetype(iterator_archetype<typename detail::convertible_type<Value>::type, AccessCategory, TraversalCategory> const&);
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
|
||||
|
||||
@@ -4,399 +4,159 @@
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
|
||||
// TODO:
|
||||
// Add separate category tag for operator[].
|
||||
|
||||
#ifndef BOOST_ITERATOR_CATEGORIES_HPP
|
||||
#define BOOST_ITERATOR_CATEGORIES_HPP
|
||||
# define BOOST_ITERATOR_CATEGORIES_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/iterator/detail/categories.hpp>
|
||||
# include <boost/config.hpp>
|
||||
# include <boost/detail/iterator.hpp>
|
||||
# include <boost/iterator/detail/config_def.hpp>
|
||||
|
||||
#include <boost/type_traits/conversion_traits.hpp>
|
||||
#include <boost/type_traits/cv_traits.hpp>
|
||||
# include <boost/detail/workaround.hpp>
|
||||
|
||||
#include <boost/python/detail/indirect_traits.hpp>
|
||||
# include <boost/mpl/apply_if.hpp>
|
||||
# include <boost/mpl/identity.hpp>
|
||||
# include <boost/mpl/placeholders.hpp>
|
||||
# include <boost/mpl/aux_/lambda_support.hpp>
|
||||
|
||||
#include <boost/detail/iterator.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
# include <boost/type_traits/is_convertible.hpp>
|
||||
|
||||
#include <boost/mpl/apply_if.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <boost/mpl/aux_/has_xxx.hpp>
|
||||
#include <boost/mpl/not.hpp>
|
||||
#include <boost/mpl/or.hpp>
|
||||
#include <boost/mpl/apply.hpp>
|
||||
#include <boost/mpl/aux_/msvc_eti_base.hpp>
|
||||
|
||||
#include <iterator>
|
||||
|
||||
#include <boost/iterator/detail/config_def.hpp> // must be last #include
|
||||
|
||||
#if BOOST_WORKAROUND(__MWERKS__, <=0x2407)
|
||||
# define BOOST_NO_IS_CONVERTIBLE // "Convertible does not provide enough/is not working"
|
||||
#endif
|
||||
# include <boost/static_assert.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace detail
|
||||
{
|
||||
// Helper metafunction for std_category below
|
||||
template <class Cat, class Tag, class Next>
|
||||
struct match_tag
|
||||
: mpl::apply_if<is_tag<Tag, Cat>, mpl::identity<Tag>, Next>
|
||||
{
|
||||
};
|
||||
|
||||
// Converts a possibly user-defined category tag to the
|
||||
// most-derived standard tag which is a base of that tag.
|
||||
template <class Category>
|
||||
struct std_category
|
||||
: match_tag<
|
||||
Category, std::random_access_iterator_tag
|
||||
, match_tag<Category, std::bidirectional_iterator_tag
|
||||
, match_tag<Category, std::forward_iterator_tag
|
||||
, match_tag<Category, std::input_iterator_tag
|
||||
, match_tag<Category, std::output_iterator_tag
|
||||
# if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
|
||||
, mpl::identity<void>
|
||||
# else
|
||||
, void
|
||||
# endif
|
||||
>
|
||||
>
|
||||
>
|
||||
>
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
// std_to_new_tags --
|
||||
//
|
||||
// A metafunction which converts any standard tag into its
|
||||
// corresponding new-style traversal tag.
|
||||
//
|
||||
// Also, instantiations are metafunction classes which convert a
|
||||
// reference type into a corresponding new-style access tag.
|
||||
template <class Category> struct std_to_new_tags
|
||||
# if BOOST_WORKAROUND(BOOST_MSVC, == 1300) // handle ETI
|
||||
{
|
||||
typedef void type;
|
||||
template <class T> struct apply { typedef void type; };
|
||||
}
|
||||
# endif
|
||||
;
|
||||
|
||||
# if BOOST_WORKAROUND(BOOST_MSVC, <= 1200) // handle ETI
|
||||
template <> struct std_to_new_tags<int> {};
|
||||
# endif
|
||||
|
||||
//
|
||||
// Specializations for specific standard tags
|
||||
//
|
||||
template <>
|
||||
struct std_to_new_tags<std::input_iterator_tag>
|
||||
{
|
||||
typedef single_pass_traversal_tag type;
|
||||
|
||||
template <class Reference>
|
||||
struct apply
|
||||
: mpl::identity<readable_iterator_tag> {};
|
||||
|
||||
};
|
||||
|
||||
template <>
|
||||
struct std_to_new_tags<std::output_iterator_tag>
|
||||
{
|
||||
typedef incrementable_traversal_tag type;
|
||||
|
||||
template <class Reference>
|
||||
struct apply
|
||||
: mpl::identity<writable_iterator_tag> {};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct std_to_new_tags<std::forward_iterator_tag>
|
||||
{
|
||||
typedef forward_traversal_tag type;
|
||||
|
||||
template <class Reference>
|
||||
struct apply
|
||||
: mpl::if_<
|
||||
python::detail::is_reference_to_const<Reference>
|
||||
, boost::readable_lvalue_iterator_tag
|
||||
, boost::writable_lvalue_iterator_tag
|
||||
>
|
||||
{};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct std_to_new_tags<std::bidirectional_iterator_tag>
|
||||
: std_to_new_tags<std::forward_iterator_tag>
|
||||
{
|
||||
typedef bidirectional_traversal_tag type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct std_to_new_tags<std::random_access_iterator_tag>
|
||||
: std_to_new_tags<std::bidirectional_iterator_tag>
|
||||
{
|
||||
typedef random_access_traversal_tag type;
|
||||
};
|
||||
|
||||
template <class Category>
|
||||
struct old_tag_converter
|
||||
: std_to_new_tags<
|
||||
typename std_category<Category>::type
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
template <typename Category>
|
||||
struct iter_category_to_traversal
|
||||
: std_to_new_tags<
|
||||
typename std_category<Category>::type
|
||||
>
|
||||
{};
|
||||
|
||||
template <typename Category, typename Reference>
|
||||
struct iter_category_to_access
|
||||
: mpl::apply1<
|
||||
iter_category_to_traversal<Category>
|
||||
, Reference
|
||||
>
|
||||
{};
|
||||
|
||||
# if BOOST_WORKAROUND(BOOST_MSVC, <= 1200)
|
||||
// Deal with ETI
|
||||
template <> struct iter_category_to_access<int, int> {};
|
||||
template <> struct iter_category_to_traversal<int> {};
|
||||
# endif
|
||||
|
||||
// A metafunction returning true iff T is boost::iterator_tag<R,U>
|
||||
template <class T>
|
||||
struct is_boost_iterator_tag;
|
||||
|
||||
#if BOOST_WORKAROUND(__MWERKS__, <= 0x2407)
|
||||
//
|
||||
// has_xxx fails, so we have to use
|
||||
// something less sophisticated.
|
||||
//
|
||||
// The solution depends on the fact that only
|
||||
// std iterator categories work with is_xxx_iterator
|
||||
// meta functions, as BOOST_NO_IS_CONVERTIBLE is
|
||||
// defined for cwpro7.
|
||||
//
|
||||
template <class Tag>
|
||||
struct is_new_iterator_tag
|
||||
: mpl::not_<
|
||||
mpl::or_<
|
||||
is_tag<std::input_iterator_tag, Tag>
|
||||
, is_tag<std::output_iterator_tag, Tag>
|
||||
>
|
||||
>
|
||||
{};
|
||||
|
||||
#elif BOOST_WORKAROUND(__GNUC__, == 2 && __GNUC_MINOR__ == 95) \
|
||||
|| BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
|
||||
|
||||
template <class Tag>
|
||||
struct is_new_iterator_tag
|
||||
: is_boost_iterator_tag<Tag>
|
||||
{
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
BOOST_MPL_HAS_XXX_TRAIT_DEF(traversal)
|
||||
|
||||
template <class Tag>
|
||||
struct is_new_iterator_tag
|
||||
: mpl::if_<
|
||||
is_class<Tag>
|
||||
, has_traversal<Tag>
|
||||
, mpl::false_
|
||||
>::type
|
||||
{
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace detail
|
||||
//
|
||||
// Traversal Categories
|
||||
//
|
||||
struct incrementable_traversal_tag {};
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <class NewCategoryTag>
|
||||
struct get_traversal_category {
|
||||
typedef typename NewCategoryTag::traversal type;
|
||||
};
|
||||
|
||||
// Remove all writability from the given access tag. This
|
||||
// functionality is part of new_category_to_access in order to
|
||||
// support deduction of the proper default access category for
|
||||
// iterator_adaptor; when the reference type is a reference to
|
||||
// constant we must strip writability.
|
||||
template <class AccessTag>
|
||||
struct remove_access_writability
|
||||
: mpl::apply_if<
|
||||
is_tag<writable_lvalue_iterator_tag, AccessTag>
|
||||
, mpl::identity<readable_lvalue_iterator_tag>
|
||||
|
||||
, mpl::apply_if<
|
||||
is_tag<readable_writable_iterator_tag, AccessTag>
|
||||
, mpl::identity<readable_iterator_tag>
|
||||
|
||||
, mpl::if_<
|
||||
is_tag<writable_iterator_tag, AccessTag>
|
||||
// Is this OK? I think it may correct be for all
|
||||
// legitimate cases, because at this point the
|
||||
// iterator is not readable, so it could not have
|
||||
// been any more than writable + swappable.
|
||||
, swappable_iterator_tag
|
||||
, AccessTag
|
||||
>
|
||||
>
|
||||
>
|
||||
{};
|
||||
struct single_pass_traversal_tag
|
||||
: incrementable_traversal_tag {};
|
||||
|
||||
template <class NewCategoryTag, class Reference>
|
||||
struct new_category_to_access
|
||||
: mpl::apply_if<
|
||||
python::detail::is_reference_to_const<Reference>
|
||||
, remove_access_writability<typename NewCategoryTag::access>
|
||||
, mpl::identity<typename NewCategoryTag::access>
|
||||
>
|
||||
{};
|
||||
struct forward_traversal_tag
|
||||
: single_pass_traversal_tag {};
|
||||
|
||||
struct bidirectional_traversal_tag
|
||||
: forward_traversal_tag {};
|
||||
|
||||
struct random_access_traversal_tag
|
||||
: bidirectional_traversal_tag {};
|
||||
|
||||
template <class CategoryTag, class Reference>
|
||||
struct access_category_tag
|
||||
: mpl::apply_if<
|
||||
is_new_iterator_tag<CategoryTag>
|
||||
, new_category_to_access<CategoryTag, Reference>
|
||||
, iter_category_to_access<CategoryTag, Reference>
|
||||
namespace detail
|
||||
{
|
||||
//
|
||||
// Convert a "strictly old-style" iterator category to a traversal
|
||||
// tag. This is broken out into a separate metafunction to reduce
|
||||
// the cost of instantiating iterator_category_to_traversal, below,
|
||||
// for new-style types.
|
||||
//
|
||||
template <class Cat>
|
||||
struct old_category_to_traversal
|
||||
: mpl::apply_if<
|
||||
is_convertible<Cat,std::random_access_iterator_tag>
|
||||
, mpl::identity<random_access_traversal_tag>
|
||||
, mpl::apply_if<
|
||||
is_convertible<Cat,std::bidirectional_iterator_tag>
|
||||
, mpl::identity<bidirectional_traversal_tag>
|
||||
, mpl::apply_if<
|
||||
is_convertible<Cat,std::forward_iterator_tag>
|
||||
, mpl::identity<forward_traversal_tag>
|
||||
, mpl::apply_if<
|
||||
is_convertible<Cat,std::input_iterator_tag>
|
||||
, mpl::identity<single_pass_traversal_tag>
|
||||
, mpl::apply_if<
|
||||
is_convertible<Cat,std::output_iterator_tag>
|
||||
, mpl::identity<incrementable_traversal_tag>
|
||||
, void
|
||||
>
|
||||
>
|
||||
>
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
template <class CategoryTag>
|
||||
struct traversal_category_tag
|
||||
: mpl::apply_if<
|
||||
is_new_iterator_tag<CategoryTag>
|
||||
, get_traversal_category<CategoryTag>
|
||||
, iter_category_to_traversal<CategoryTag>
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
# if BOOST_WORKAROUND(BOOST_MSVC, <= 1200)
|
||||
// Deal with ETI
|
||||
template <> struct access_category_tag<int, int> { typedef void type; };
|
||||
template <> struct traversal_category_tag<int> { typedef void type; };
|
||||
# endif
|
||||
|
||||
// iterator_tag_base - a metafunction to compute the appropriate
|
||||
// old-style tag (if any) to use as a base for a new-style tag.
|
||||
template <class KnownAccessTag, class KnownTraversalTag>
|
||||
struct iterator_tag_base
|
||||
: minimum_category<
|
||||
typename KnownAccessTag::max_category
|
||||
, typename KnownTraversalTag::max_category
|
||||
>
|
||||
{};
|
||||
|
||||
# if BOOST_WORKAROUND(BOOST_MSVC,<=1200)
|
||||
template <>
|
||||
struct iterator_tag_base<int,int>
|
||||
: mpl::false_ {}; // just using false_ so that the result will be
|
||||
// a legal base class
|
||||
# endif
|
||||
|
||||
// specialization for this special case. Otherwise we get
|
||||
// input_output_iterator_tag, because the standard hierarchy has a
|
||||
// sudden anomalous distinction between readability and
|
||||
// writability at the level of input iterator/output iterator.
|
||||
template <>
|
||||
struct iterator_tag_base<
|
||||
readable_lvalue_iterator_tag,single_pass_traversal_tag>
|
||||
{
|
||||
typedef std::input_iterator_tag type;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class Iterator>
|
||||
struct access_category
|
||||
: detail::access_category_tag<
|
||||
typename detail::iterator_traits<Iterator>::iterator_category
|
||||
, typename detail::iterator_traits<Iterator>::reference>
|
||||
>
|
||||
{};
|
||||
|
||||
template <class Iterator>
|
||||
struct traversal_category
|
||||
: detail::traversal_category_tag<
|
||||
typename detail::iterator_traits<Iterator>::iterator_category
|
||||
# if BOOST_WORKAROUND(BOOST_MSVC, == 1200)
|
||||
template <>
|
||||
struct old_category_to_traversal<int>
|
||||
{
|
||||
typedef int type;
|
||||
};
|
||||
# endif
|
||||
|
||||
template <class Traversal>
|
||||
struct pure_traversal_tag
|
||||
: mpl::apply_if<
|
||||
is_convertible<Traversal,random_access_traversal_tag>
|
||||
, mpl::identity<random_access_traversal_tag>
|
||||
, mpl::apply_if<
|
||||
is_convertible<Traversal,bidirectional_traversal_tag>
|
||||
, mpl::identity<bidirectional_traversal_tag>
|
||||
, mpl::apply_if<
|
||||
is_convertible<Traversal,forward_traversal_tag>
|
||||
, mpl::identity<forward_traversal_tag>
|
||||
, mpl::apply_if<
|
||||
is_convertible<Traversal,single_pass_traversal_tag>
|
||||
, mpl::identity<single_pass_traversal_tag>
|
||||
, mpl::apply_if<
|
||||
is_convertible<Traversal,incrementable_traversal_tag>
|
||||
, mpl::identity<incrementable_traversal_tag>
|
||||
, void
|
||||
>
|
||||
>
|
||||
>
|
||||
>
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
# if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
|
||||
|
||||
template <typename T>
|
||||
struct access_category<T*>
|
||||
: mpl::if_<
|
||||
is_const<T>
|
||||
, readable_lvalue_iterator_tag
|
||||
, writable_lvalue_iterator_tag>
|
||||
|
||||
# if BOOST_WORKAROUND(BOOST_MSVC, == 1200)
|
||||
template <>
|
||||
struct pure_traversal_tag<int>
|
||||
{
|
||||
typedef int type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct traversal_category<T*>
|
||||
{
|
||||
typedef random_access_traversal_tag type;
|
||||
};
|
||||
|
||||
# endif
|
||||
|
||||
template <class AccessTag, class TraversalTag>
|
||||
struct iterator_tag
|
||||
: detail::iterator_tag_base<
|
||||
typename detail::max_known_access_tag<AccessTag>::type
|
||||
, typename detail::max_known_traversal_tag<TraversalTag>::type
|
||||
>::type
|
||||
{
|
||||
typedef AccessTag access;
|
||||
typedef TraversalTag traversal;
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
namespace detail
|
||||
{
|
||||
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
template <class T>
|
||||
struct is_boost_iterator_tag
|
||||
: mpl::false_ {};
|
||||
|
||||
template <class R, class T>
|
||||
struct is_boost_iterator_tag<iterator_tag<R,T> >
|
||||
: mpl::true_ {};
|
||||
# else
|
||||
//
|
||||
// Convert an iterator category into a traversal tag
|
||||
//
|
||||
template <class Cat>
|
||||
struct iterator_category_to_traversal
|
||||
: mpl::apply_if< // if already convertible to a traversal tag, we're done.
|
||||
is_convertible<Cat,incrementable_traversal_tag>
|
||||
, mpl::identity<Cat>
|
||||
, detail::old_category_to_traversal<Cat>
|
||||
>
|
||||
{};
|
||||
|
||||
// Trait to get an iterator's traversal category
|
||||
template <class Iterator = mpl::_1>
|
||||
struct iterator_traversal
|
||||
: iterator_category_to_traversal<
|
||||
typename boost::detail::iterator_traits<Iterator>::iterator_category
|
||||
>
|
||||
{};
|
||||
|
||||
# ifdef BOOST_MPL_NO_FULL_LAMBDA_SUPPORT
|
||||
// Hack because BOOST_MPL_AUX_LAMBDA_SUPPORT doesn't seem to work
|
||||
// out well. Instantiating the nested apply template also
|
||||
// requires instantiating iterator_traits on the
|
||||
// placeholder. Instead we just specialize it as a metafunction
|
||||
// class.
|
||||
template <>
|
||||
struct iterator_traversal<mpl::_1>
|
||||
{
|
||||
template <class T>
|
||||
struct is_boost_iterator_tag
|
||||
{
|
||||
typedef char (&yes)[1];
|
||||
typedef char (&no)[2];
|
||||
|
||||
template <class R, class U>
|
||||
static yes test(mpl::identity<iterator_tag<R,U> >*);
|
||||
static no test(...);
|
||||
|
||||
static mpl::identity<T>* inst;
|
||||
BOOST_STATIC_CONSTANT(bool, value = sizeof(test(inst)) == sizeof(yes));
|
||||
typedef mpl::bool_<value> type;
|
||||
};
|
||||
struct apply : iterator_traversal<T>
|
||||
{};
|
||||
};
|
||||
template <>
|
||||
struct iterator_traversal<mpl::_>
|
||||
: iterator_traversal<mpl::_1>
|
||||
{};
|
||||
# endif
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
|
||||
@@ -15,16 +15,20 @@
|
||||
|
||||
#include <boost/concept_check.hpp>
|
||||
#include <boost/iterator/iterator_categories.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/type_traits/is_integral.hpp>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/mpl/and.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
|
||||
// Use boost::detail::iterator_traits to work around some MSVC/Dinkumware problems.
|
||||
#include <boost/detail/iterator.hpp>
|
||||
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/type_traits/is_integral.hpp>
|
||||
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/mpl/and.hpp>
|
||||
#include <boost/mpl/or.hpp>
|
||||
|
||||
#include <boost/static_assert.hpp>
|
||||
|
||||
// Use boost/limits to work around missing limits headers on some compilers
|
||||
#include <boost/limits.hpp>
|
||||
|
||||
@@ -56,7 +60,6 @@ namespace boost_concepts {
|
||||
public:
|
||||
typedef BOOST_DEDUCED_TYPENAME ::boost::detail::iterator_traits<Iterator>::value_type value_type;
|
||||
typedef BOOST_DEDUCED_TYPENAME ::boost::detail::iterator_traits<Iterator>::reference reference;
|
||||
typedef BOOST_DEDUCED_TYPENAME ::boost::access_category<Iterator>::type access_category;
|
||||
|
||||
void constraints() {
|
||||
boost::function_requires< boost::SGIAssignableConcept<Iterator> >();
|
||||
@@ -64,8 +67,6 @@ namespace boost_concepts {
|
||||
boost::function_requires<
|
||||
boost::DefaultConstructibleConcept<Iterator> >();
|
||||
|
||||
BOOST_STATIC_ASSERT((boost::detail::is_tag<boost::readable_iterator_tag, access_category>::value));
|
||||
|
||||
reference r = *i; // or perhaps read(x)
|
||||
value_type v(r);
|
||||
boost::ignore_unused_variable_warning(v);
|
||||
@@ -73,19 +74,19 @@ namespace boost_concepts {
|
||||
Iterator i;
|
||||
};
|
||||
|
||||
template <typename Iterator, typename ValueType>
|
||||
template <
|
||||
typename Iterator
|
||||
, typename ValueType = typename boost::detail::iterator_traits<Iterator>::value_type
|
||||
>
|
||||
class WritableIteratorConcept {
|
||||
public:
|
||||
typedef typename boost::access_category<Iterator>::type access_category;
|
||||
|
||||
|
||||
void constraints() {
|
||||
boost::function_requires< boost::SGIAssignableConcept<Iterator> >();
|
||||
boost::function_requires< boost::EqualityComparableConcept<Iterator> >();
|
||||
boost::function_requires<
|
||||
boost::DefaultConstructibleConcept<Iterator> >();
|
||||
|
||||
BOOST_STATIC_ASSERT((boost::detail::is_tag<boost::writable_iterator_tag, access_category>::value));
|
||||
|
||||
*i = v; // a good alternative could be something like write(x, v)
|
||||
}
|
||||
ValueType v;
|
||||
@@ -95,11 +96,8 @@ namespace boost_concepts {
|
||||
template <typename Iterator>
|
||||
class SwappableIteratorConcept {
|
||||
public:
|
||||
typedef typename boost::access_category<Iterator>::type access_category;
|
||||
|
||||
void constraints() {
|
||||
BOOST_STATIC_ASSERT((boost::detail::is_tag<boost::swappable_iterator_tag, access_category>::value));
|
||||
|
||||
std::iter_swap(i1, i2);
|
||||
}
|
||||
Iterator i1;
|
||||
@@ -107,25 +105,25 @@ namespace boost_concepts {
|
||||
};
|
||||
|
||||
template <typename Iterator>
|
||||
class ReadableLvalueIteratorConcept {
|
||||
public:
|
||||
typedef typename boost::detail::iterator_traits<Iterator>::value_type value_type;
|
||||
typedef typename boost::detail::iterator_traits<Iterator>::reference reference;
|
||||
typedef typename boost::access_category<Iterator>::type access_category;
|
||||
class ReadableLvalueIteratorConcept
|
||||
{
|
||||
public:
|
||||
typedef typename boost::detail::iterator_traits<Iterator>::value_type value_type;
|
||||
typedef typename boost::detail::iterator_traits<Iterator>::reference reference;
|
||||
|
||||
void constraints() {
|
||||
boost::function_requires< ReadableIteratorConcept<Iterator> >();
|
||||
void constraints()
|
||||
{
|
||||
boost::function_requires< ReadableIteratorConcept<Iterator> >();
|
||||
|
||||
BOOST_STATIC_ASSERT((boost::detail::is_tag<boost::readable_lvalue_iterator_tag, access_category>::value));
|
||||
|
||||
typedef boost::mpl::or_<
|
||||
boost::is_same<reference, value_type&>,
|
||||
boost::is_same<reference, value_type const&> > correct_reference;
|
||||
typedef boost::mpl::or_<
|
||||
boost::is_same<reference, value_type&>
|
||||
, boost::is_same<reference, value_type const&>
|
||||
> correct_reference;
|
||||
|
||||
BOOST_STATIC_ASSERT(correct_reference::value);
|
||||
BOOST_STATIC_ASSERT(correct_reference::value);
|
||||
|
||||
reference v = *i;
|
||||
boost::ignore_unused_variable_warning(v);
|
||||
reference v = *i;
|
||||
boost::ignore_unused_variable_warning(v);
|
||||
}
|
||||
Iterator i;
|
||||
};
|
||||
@@ -135,7 +133,6 @@ namespace boost_concepts {
|
||||
public:
|
||||
typedef typename boost::detail::iterator_traits<Iterator>::value_type value_type;
|
||||
typedef typename boost::detail::iterator_traits<Iterator>::reference reference;
|
||||
typedef typename boost::access_category<Iterator>::type access_category;
|
||||
|
||||
void constraints() {
|
||||
boost::function_requires<
|
||||
@@ -145,7 +142,6 @@ namespace boost_concepts {
|
||||
boost::function_requires<
|
||||
SwappableIteratorConcept<Iterator> >();
|
||||
|
||||
BOOST_STATIC_ASSERT((boost::detail::is_tag<boost::writable_lvalue_iterator_tag, access_category>::value));
|
||||
|
||||
BOOST_STATIC_ASSERT((boost::is_same<reference, value_type&>::value));
|
||||
}
|
||||
@@ -157,14 +153,19 @@ namespace boost_concepts {
|
||||
template <typename Iterator>
|
||||
class IncrementableIteratorConcept {
|
||||
public:
|
||||
typedef typename boost::traversal_category<Iterator>::type traversal_category;
|
||||
typedef typename boost::iterator_traversal<Iterator>::type traversal_category;
|
||||
|
||||
void constraints() {
|
||||
boost::function_requires< boost::SGIAssignableConcept<Iterator> >();
|
||||
boost::function_requires<
|
||||
boost::DefaultConstructibleConcept<Iterator> >();
|
||||
|
||||
BOOST_STATIC_ASSERT((boost::detail::is_tag<boost::incrementable_traversal_tag, traversal_category>::value));
|
||||
BOOST_STATIC_ASSERT(
|
||||
(boost::is_convertible<
|
||||
traversal_category
|
||||
, boost::incrementable_traversal_tag
|
||||
>::value
|
||||
));
|
||||
|
||||
++i;
|
||||
(void)i++;
|
||||
@@ -175,21 +176,26 @@ namespace boost_concepts {
|
||||
template <typename Iterator>
|
||||
class SinglePassIteratorConcept {
|
||||
public:
|
||||
typedef typename boost::traversal_category<Iterator>::type traversal_category;
|
||||
typedef typename boost::iterator_traversal<Iterator>::type traversal_category;
|
||||
typedef typename boost::detail::iterator_traits<Iterator>::difference_type difference_type;
|
||||
|
||||
void constraints() {
|
||||
boost::function_requires< IncrementableIteratorConcept<Iterator> >();
|
||||
boost::function_requires< boost::EqualityComparableConcept<Iterator> >();
|
||||
|
||||
BOOST_STATIC_ASSERT((boost::detail::is_tag<boost::single_pass_traversal_tag, traversal_category>::value));
|
||||
BOOST_STATIC_ASSERT(
|
||||
(boost::is_convertible<
|
||||
traversal_category
|
||||
, boost::single_pass_traversal_tag
|
||||
>::value
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Iterator>
|
||||
class ForwardTraversalConcept {
|
||||
public:
|
||||
typedef typename boost::traversal_category<Iterator>::type traversal_category;
|
||||
typedef typename boost::iterator_traversal<Iterator>::type traversal_category;
|
||||
typedef typename boost::detail::iterator_traits<Iterator>::difference_type difference_type;
|
||||
|
||||
void constraints() {
|
||||
@@ -201,19 +207,29 @@ namespace boost_concepts {
|
||||
> difference_type_is_signed_integral;
|
||||
|
||||
BOOST_STATIC_ASSERT(difference_type_is_signed_integral::value);
|
||||
BOOST_STATIC_ASSERT((boost::detail::is_tag<boost::forward_traversal_tag, traversal_category>::value));
|
||||
BOOST_STATIC_ASSERT(
|
||||
(boost::is_convertible<
|
||||
traversal_category
|
||||
, boost::forward_traversal_tag
|
||||
>::value
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Iterator>
|
||||
class BidirectionalTraversalConcept {
|
||||
public:
|
||||
typedef typename boost::traversal_category<Iterator>::type traversal_category;
|
||||
typedef typename boost::iterator_traversal<Iterator>::type traversal_category;
|
||||
|
||||
void constraints() {
|
||||
boost::function_requires< ForwardTraversalConcept<Iterator> >();
|
||||
|
||||
BOOST_STATIC_ASSERT((boost::detail::is_tag<boost::bidirectional_traversal_tag, traversal_category>::value));
|
||||
BOOST_STATIC_ASSERT(
|
||||
(boost::is_convertible<
|
||||
traversal_category
|
||||
, boost::bidirectional_traversal_tag
|
||||
>::value
|
||||
));
|
||||
|
||||
--i;
|
||||
(void)i--;
|
||||
@@ -224,14 +240,19 @@ namespace boost_concepts {
|
||||
template <typename Iterator>
|
||||
class RandomAccessTraversalConcept {
|
||||
public:
|
||||
typedef typename boost::traversal_category<Iterator>::type traversal_category;
|
||||
typedef typename boost::iterator_traversal<Iterator>::type traversal_category;
|
||||
typedef typename boost::detail::iterator_traits<Iterator>::difference_type
|
||||
difference_type;
|
||||
|
||||
void constraints() {
|
||||
boost::function_requires< BidirectionalTraversalConcept<Iterator> >();
|
||||
|
||||
BOOST_STATIC_ASSERT((boost::detail::is_tag<boost::random_access_traversal_tag, traversal_category>::value));
|
||||
BOOST_STATIC_ASSERT(
|
||||
(boost::is_convertible<
|
||||
traversal_category
|
||||
, boost::random_access_traversal_tag
|
||||
>::value
|
||||
));
|
||||
|
||||
i += n;
|
||||
i = i + n;
|
||||
@@ -269,7 +290,7 @@ namespace detail
|
||||
template <typename Iterator1, typename Iterator2>
|
||||
static void constraints(Iterator1 const& i1, Iterator2 const& i2)
|
||||
{
|
||||
Operations<boost::incrementable_traversal_tag>(i1, i2);
|
||||
Operations<boost::incrementable_traversal_tag>::constraints(i1, i2);
|
||||
i1 == i2;
|
||||
i1 != i2;
|
||||
|
||||
@@ -326,11 +347,11 @@ namespace detail
|
||||
class InteroperableConcept
|
||||
{
|
||||
public:
|
||||
typedef typename boost::traversal_category<Iterator>::type traversal_category;
|
||||
typedef typename boost::iterator_traversal<Iterator>::type traversal_category;
|
||||
typedef typename boost::detail::iterator_traits<Iterator>::difference_type
|
||||
difference_type;
|
||||
|
||||
typedef typename boost::traversal_category<ConstIterator>::type
|
||||
typedef typename boost::iterator_traversal<ConstIterator>::type
|
||||
const_traversal_category;
|
||||
typedef typename boost::detail::iterator_traits<ConstIterator>::difference_type
|
||||
const_difference_type;
|
||||
|
||||
@@ -12,15 +12,17 @@
|
||||
#include <boost/static_assert.hpp>
|
||||
|
||||
#include <boost/iterator.hpp>
|
||||
#include <boost/iterator/iterator_categories.hpp>
|
||||
#include <boost/iterator/interoperable.hpp>
|
||||
|
||||
#include <boost/iterator/detail/facade_iterator_category.hpp>
|
||||
#include <boost/iterator/detail/enable_if.hpp>
|
||||
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/type_traits/add_const.hpp>
|
||||
#include <boost/type_traits/add_pointer.hpp>
|
||||
#include <boost/type_traits/remove_const.hpp>
|
||||
#include <boost/type_traits/is_convertible.hpp>
|
||||
|
||||
#include <boost/iterator/iterator_traits.hpp>
|
||||
|
||||
#include <boost/mpl/apply_if.hpp>
|
||||
#include <boost/mpl/or.hpp>
|
||||
|
||||
@@ -28,12 +30,12 @@
|
||||
|
||||
namespace boost
|
||||
{
|
||||
// This forward declaration is required for the friend declaration
|
||||
// in iterator_core_access
|
||||
template <class I, class V, class TC, class R, class D> class iterator_facade;
|
||||
|
||||
struct use_default;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
//
|
||||
// enable if for use in operator implementation.
|
||||
//
|
||||
@@ -47,7 +49,7 @@ namespace boost
|
||||
>
|
||||
struct enable_if_interoperable
|
||||
#ifndef BOOST_NO_STRICT_ITERATOR_INTEROPERABILITY
|
||||
: ::boost::detail::enable_if<
|
||||
: ::boost::iterators::enable_if<
|
||||
mpl::or_<
|
||||
is_convertible<Facade1, Facade2>
|
||||
, is_convertible<Facade2, Facade1>
|
||||
@@ -61,59 +63,30 @@ namespace boost
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// Add const qualification for iterators which are not writable
|
||||
//
|
||||
template<class Value, class AccessCategory>
|
||||
struct const_qualified_ref :
|
||||
mpl::if_< is_tag< writable_iterator_tag, AccessCategory >,
|
||||
Value&,
|
||||
Value const& >
|
||||
{};
|
||||
|
||||
// The apparent duplication here works around a Borland problem
|
||||
template<class Value, class AccessCategory>
|
||||
struct const_qualified_ptr :
|
||||
mpl::if_< is_tag< writable_iterator_tag, AccessCategory >,
|
||||
Value*,
|
||||
Value const* >
|
||||
{};
|
||||
|
||||
//
|
||||
// Generates the associated types for an iterator_facade with the
|
||||
// given parameters. Additionally generates a 'base' type for
|
||||
// compiler/library combinations which require user-defined
|
||||
// iterators to inherit from std::iterator.
|
||||
// Generates associated types for an iterator_facade with the
|
||||
// given parameters.
|
||||
//
|
||||
template <
|
||||
class Value
|
||||
, class AccessCategory
|
||||
, class TraversalCategory
|
||||
, class Reference
|
||||
class ValueParam
|
||||
, class CategoryOrTraversal
|
||||
, class Reference
|
||||
, class Difference
|
||||
>
|
||||
struct iterator_facade_types
|
||||
{
|
||||
typedef iterator_tag<AccessCategory, TraversalCategory> iterator_category;
|
||||
typedef typename facade_iterator_category<
|
||||
CategoryOrTraversal, ValueParam, Reference
|
||||
>::type iterator_category;
|
||||
|
||||
typedef typename remove_cv<Value>::type value_type;
|
||||
typedef typename remove_const<ValueParam>::type value_type;
|
||||
|
||||
typedef Difference difference_type;
|
||||
|
||||
typedef typename const_qualified_ptr<Value, AccessCategory>::type pointer;
|
||||
|
||||
// The use_default support is needed for iterator_adaptor.
|
||||
// For practical reasons iterator_adaptor needs to specify
|
||||
// a fixed number of template arguments of iterator_facade.
|
||||
// So use_default is its way to say: "What I really mean
|
||||
// is your default parameter".
|
||||
typedef typename mpl::if_<
|
||||
is_same<Reference, use_default>
|
||||
, typename const_qualified_ref<Value, AccessCategory>::type
|
||||
, Reference
|
||||
>::type reference;
|
||||
|
||||
typedef typename mpl::apply_if<
|
||||
detail::iterator_writability_disabled<ValueParam,Reference>
|
||||
, add_pointer<typename add_const<value_type>::type>
|
||||
, add_pointer<value_type>
|
||||
>::type pointer;
|
||||
|
||||
# if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \
|
||||
&& (BOOST_WORKAROUND(_STLPORT_VERSION, BOOST_TESTED_AT(0x452)) \
|
||||
|| BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, BOOST_TESTED_AT(310))) \
|
||||
@@ -127,7 +100,7 @@ namespace boost
|
||||
# define BOOST_ITERATOR_FACADE_NEEDS_ITERATOR_BASE 1
|
||||
|
||||
typedef
|
||||
iterator<iterator_category, value_type, difference_type, pointer, reference>
|
||||
iterator<iterator_category, value_type, Difference, pointer, Reference>
|
||||
base;
|
||||
# endif
|
||||
};
|
||||
@@ -152,17 +125,14 @@ namespace boost
|
||||
// A metafunction that gets the result type for operator->. Also
|
||||
// has a static function make() which builds the result from a
|
||||
// Reference
|
||||
template <class Value, class Category, class Reference, class Pointer>
|
||||
template <class Value, class Reference, class Pointer>
|
||||
struct operator_arrow_result
|
||||
{
|
||||
// CWPro8.3 won't accept "operator_arrow_result::type", and we
|
||||
// need that type below, so metafunction forwarding would be a
|
||||
// losing proposition here.
|
||||
typedef typename mpl::if_<
|
||||
is_tag<
|
||||
readable_lvalue_iterator_tag
|
||||
, typename access_category_tag<Category,Reference>::type
|
||||
>
|
||||
is_reference<Reference>
|
||||
, Pointer
|
||||
, operator_arrow_proxy<Value>
|
||||
>::type type;
|
||||
@@ -176,16 +146,15 @@ namespace boost
|
||||
# if BOOST_WORKAROUND(BOOST_MSVC, <= 1200)
|
||||
// Deal with ETI
|
||||
template<>
|
||||
struct operator_arrow_result<int, int, int, int>
|
||||
struct operator_arrow_result<int, int, int>
|
||||
{
|
||||
typedef int type;
|
||||
};
|
||||
# endif
|
||||
|
||||
//
|
||||
// Facade is actually an iterator. We require Facade here
|
||||
// so that we do not have to go through iterator_traits
|
||||
// to access the traits
|
||||
// Iterator is actually an iterator_facade, so we do not have to
|
||||
// go through iterator_traits to access the traits.
|
||||
//
|
||||
template <class Iterator>
|
||||
class operator_brackets_proxy
|
||||
@@ -195,10 +164,10 @@ namespace boost
|
||||
|
||||
public:
|
||||
operator_brackets_proxy(Iterator const& iter)
|
||||
: m_iter(iter)
|
||||
: m_iter(iter)
|
||||
{}
|
||||
|
||||
operator reference()
|
||||
operator reference() const
|
||||
{
|
||||
return *m_iter;
|
||||
}
|
||||
@@ -213,28 +182,24 @@ namespace boost
|
||||
Iterator m_iter;
|
||||
};
|
||||
|
||||
template <class Iterator, class ValueType, class Category, class Reference>
|
||||
template <class Iterator, class Value, class Reference>
|
||||
struct operator_brackets_result
|
||||
{
|
||||
typedef typename access_category_tag<Category,Reference>::type access_category;
|
||||
|
||||
typedef is_tag<writable_iterator_tag, access_category> use_proxy;
|
||||
|
||||
typedef typename mpl::if_<
|
||||
use_proxy
|
||||
typedef typename mpl::if_<
|
||||
iterator_writability_disabled<Value,Reference>
|
||||
, Value
|
||||
, operator_brackets_proxy<Iterator>
|
||||
, ValueType
|
||||
>::type type;
|
||||
};
|
||||
|
||||
template <class Iterator>
|
||||
operator_brackets_proxy<Iterator> make_operator_brackets_result(Iterator const& iter, mpl::true_)
|
||||
operator_brackets_proxy<Iterator> make_operator_brackets_result(Iterator const& iter, mpl::false_)
|
||||
{
|
||||
return operator_brackets_proxy<Iterator>(iter);
|
||||
}
|
||||
|
||||
template <class Iterator>
|
||||
typename Iterator::value_type make_operator_brackets_result(Iterator const& iter, mpl::false_)
|
||||
typename Iterator::value_type make_operator_brackets_result(Iterator const& iter, mpl::true_)
|
||||
{
|
||||
return *iter;
|
||||
}
|
||||
@@ -243,20 +208,20 @@ namespace boost
|
||||
|
||||
|
||||
// Macros which describe the declarations of binary operators
|
||||
# define BOOST_ITERATOR_FACADE_INTEROP_HEAD(prefix, op, result_type) \
|
||||
template < \
|
||||
class Derived1, class V1, class AC1, class TC1, class R1, class D1 \
|
||||
, class Derived2, class V2, class AC2, class TC2, class R2, class D2 \
|
||||
> \
|
||||
prefix typename detail::enable_if_interoperable< \
|
||||
Derived1, Derived2, result_type \
|
||||
>::type \
|
||||
operator op( \
|
||||
iterator_facade<Derived1, V1, AC1, TC1, R1, D1> const& lhs \
|
||||
, iterator_facade<Derived2, V2, AC2, TC2, R2, D2> const& rhs)
|
||||
# define BOOST_ITERATOR_FACADE_INTEROP_HEAD(prefix, op, result_type) \
|
||||
template < \
|
||||
class Derived1, class V1, class TC1, class R1, class D1 \
|
||||
, class Derived2, class V2, class TC2, class R2, class D2 \
|
||||
> \
|
||||
prefix typename detail::enable_if_interoperable< \
|
||||
Derived1, Derived2, result_type \
|
||||
>::type \
|
||||
operator op( \
|
||||
iterator_facade<Derived1, V1, TC1, R1, D1> const& lhs \
|
||||
, iterator_facade<Derived2, V2, TC2, R2, D2> const& rhs)
|
||||
|
||||
# define BOOST_ITERATOR_FACADE_PLUS_HEAD(prefix,args) \
|
||||
template <class Derived, class V, class AC, class TC, class R, class D> \
|
||||
# define BOOST_ITERATOR_FACADE_PLUS_HEAD(prefix,args) \
|
||||
template <class Derived, class V, class TC, class R, class D> \
|
||||
prefix Derived operator+ args
|
||||
|
||||
//
|
||||
@@ -277,7 +242,7 @@ namespace boost
|
||||
public:
|
||||
# else
|
||||
|
||||
template <class I, class V, class AC, class TC, class R, class D> friend class iterator_facade;
|
||||
template <class I, class V, class TC, class R, class D> friend class iterator_facade;
|
||||
|
||||
# define BOOST_ITERATOR_FACADE_RELATION(op) \
|
||||
BOOST_ITERATOR_FACADE_INTEROP_HEAD(friend,op, bool);
|
||||
@@ -297,7 +262,7 @@ namespace boost
|
||||
|
||||
BOOST_ITERATOR_FACADE_PLUS_HEAD(
|
||||
friend
|
||||
, (iterator_facade<Derived, V, AC, TC, R, D> const&
|
||||
, (iterator_facade<Derived, V, TC, R, D> const&
|
||||
, typename Derived::difference_type)
|
||||
)
|
||||
;
|
||||
@@ -305,7 +270,7 @@ namespace boost
|
||||
BOOST_ITERATOR_FACADE_PLUS_HEAD(
|
||||
friend
|
||||
, (typename Derived::difference_type
|
||||
, iterator_facade<Derived, V, AC, TC, R, D> const&)
|
||||
, iterator_facade<Derived, V, TC, R, D> const&)
|
||||
)
|
||||
;
|
||||
|
||||
@@ -360,26 +325,21 @@ namespace boost
|
||||
template <
|
||||
class Derived // The derived iterator type being constructed
|
||||
, class Value
|
||||
, class AccessCategory
|
||||
, class TraversalCategory
|
||||
, class Reference = typename detail::const_qualified_ref<Value, AccessCategory>::type
|
||||
, class CategoryOrTraversal
|
||||
, class Reference = Value&
|
||||
, class Difference = std::ptrdiff_t
|
||||
>
|
||||
class iterator_facade
|
||||
# ifdef BOOST_ITERATOR_FACADE_NEEDS_ITERATOR_BASE
|
||||
: public detail::iterator_facade_types<
|
||||
Value, AccessCategory, TraversalCategory, Reference, Difference
|
||||
Value, CategoryOrTraversal, Reference, Difference
|
||||
>::base
|
||||
# undef BOOST_ITERATOR_FACADE_NEEDS_ITERATOR_BASE
|
||||
# endif
|
||||
{
|
||||
private:
|
||||
typedef typename
|
||||
detail::iterator_facade_types<Value, AccessCategory, TraversalCategory, Reference, Difference>
|
||||
types;
|
||||
|
||||
//
|
||||
// Curiously Recursive Template interface.
|
||||
// Curiously Recurring Template interface.
|
||||
//
|
||||
typedef Derived derived_t;
|
||||
|
||||
@@ -393,13 +353,17 @@ namespace boost
|
||||
return static_cast<Derived const&>(*this);
|
||||
}
|
||||
|
||||
typedef detail::iterator_facade_types<
|
||||
Value, CategoryOrTraversal, Reference, Difference
|
||||
> associated_types;
|
||||
|
||||
public:
|
||||
|
||||
typedef typename types::value_type value_type;
|
||||
typedef typename types::reference reference;
|
||||
typedef typename types::difference_type difference_type;
|
||||
typedef typename types::pointer pointer;
|
||||
typedef typename types::iterator_category iterator_category;
|
||||
typedef typename associated_types::value_type value_type;
|
||||
typedef Reference reference;
|
||||
typedef Difference difference_type;
|
||||
typedef typename associated_types::pointer pointer;
|
||||
typedef typename associated_types::iterator_category iterator_category;
|
||||
|
||||
reference operator*() const
|
||||
{
|
||||
@@ -408,7 +372,6 @@ namespace boost
|
||||
|
||||
typename detail::operator_arrow_result<
|
||||
value_type
|
||||
, iterator_category
|
||||
, reference
|
||||
, pointer
|
||||
>::type
|
||||
@@ -416,20 +379,21 @@ namespace boost
|
||||
{
|
||||
return detail::operator_arrow_result<
|
||||
value_type
|
||||
, iterator_category
|
||||
, reference
|
||||
, pointer
|
||||
>::make(*this->derived());
|
||||
}
|
||||
|
||||
typename detail::operator_brackets_result<Derived,value_type,iterator_category,reference>::type
|
||||
typename detail::operator_brackets_result<Derived,Value,Reference>::type
|
||||
operator[](difference_type n) const
|
||||
{
|
||||
typedef typename
|
||||
detail::operator_brackets_result<Derived,value_type,iterator_category,reference>::use_proxy
|
||||
use_proxy;
|
||||
typedef detail::iterator_writability_disabled<Value,Reference>
|
||||
not_writable;
|
||||
|
||||
return detail::make_operator_brackets_result<Derived>(this->derived() + n, use_proxy());
|
||||
return detail::make_operator_brackets_result<Derived>(
|
||||
this->derived() + n
|
||||
, not_writable()
|
||||
);
|
||||
}
|
||||
|
||||
Derived& operator++()
|
||||
@@ -607,13 +571,13 @@ namespace boost
|
||||
}
|
||||
|
||||
BOOST_ITERATOR_FACADE_PLUS((
|
||||
iterator_facade<Derived, V, AC, TC, R, D> const& i
|
||||
iterator_facade<Derived, V, TC, R, D> const& i
|
||||
, typename Derived::difference_type n
|
||||
))
|
||||
|
||||
BOOST_ITERATOR_FACADE_PLUS((
|
||||
typename Derived::difference_type n
|
||||
, iterator_facade<Derived, V, AC, TC, R, D> const& i
|
||||
, iterator_facade<Derived, V, TC, R, D> const& i
|
||||
))
|
||||
# undef BOOST_ITERATOR_FACADE_PLUS
|
||||
# undef BOOST_ITERATOR_FACADE_PLUS_HEAD
|
||||
|
||||
Executable → Regular
@@ -24,15 +24,13 @@
|
||||
# include <boost/concept_archetype.hpp> // for detail::dummy_constructor
|
||||
# include <boost/detail/iterator.hpp>
|
||||
# include <boost/pending/iterator_tests.hpp>
|
||||
# include <boost/iterator/is_readable_iterator.hpp>
|
||||
# include <boost/iterator/is_lvalue_iterator.hpp>
|
||||
|
||||
# include <boost/iterator/detail/config_def.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
void is_readable(readable_iterator_tag) { }
|
||||
void is_writable(writable_iterator_tag) { }
|
||||
void is_swappable(swappable_iterator_tag) { }
|
||||
void is_constant_lvalue(readable_lvalue_iterator_tag) { }
|
||||
void is_mutable_lvalue(writable_lvalue_iterator_tag) { }
|
||||
|
||||
// Preconditions: *i == v
|
||||
template <class Iterator, class T>
|
||||
void readable_iterator_test(const Iterator i1, T v)
|
||||
@@ -45,8 +43,12 @@ void readable_iterator_test(const Iterator i1, T v)
|
||||
T v2 = r2;
|
||||
assert(v1 == v);
|
||||
assert(v2 == v);
|
||||
typedef typename access_category<Iterator>::type result_category;
|
||||
is_readable(result_category());
|
||||
|
||||
# if !BOOST_WORKAROUND(__MWERKS__, <= 0x2407)
|
||||
// I think we don't really need this as it checks the same things as
|
||||
// the above code.
|
||||
BOOST_STATIC_ASSERT(is_readable_iterator<Iterator>::value);
|
||||
# endif
|
||||
}
|
||||
|
||||
template <class Iterator, class T>
|
||||
@@ -54,7 +56,6 @@ void writable_iterator_test(Iterator i, T v)
|
||||
{
|
||||
Iterator i2(i); // Copy Constructible
|
||||
*i2 = v;
|
||||
is_writable(typename access_category<Iterator>::type());
|
||||
}
|
||||
|
||||
template <class Iterator>
|
||||
@@ -65,8 +66,6 @@ void swappable_iterator_test(Iterator i, Iterator j)
|
||||
iter_swap(i2, j2);
|
||||
typename detail::iterator_traits<Iterator>::value_type ai = *i, aj = *j;
|
||||
assert(bi == aj && bj == ai);
|
||||
typedef typename access_category<Iterator>::type result_category;
|
||||
is_swappable(result_category());
|
||||
}
|
||||
|
||||
template <class Iterator, class T>
|
||||
@@ -78,12 +77,14 @@ void constant_lvalue_iterator_test(Iterator i, T v1)
|
||||
BOOST_STATIC_ASSERT((is_same<const value_type&, reference>::value));
|
||||
const T& v2 = *i2;
|
||||
assert(v1 == v2);
|
||||
typedef typename access_category<Iterator>::type result_category;
|
||||
is_constant_lvalue(result_category());
|
||||
# ifndef BOOST_NO_LVALUE_RETURN_DETECTION
|
||||
BOOST_STATIC_ASSERT(is_lvalue_iterator<Iterator>::value);
|
||||
BOOST_STATIC_ASSERT(!is_non_const_lvalue_iterator<Iterator>::value);
|
||||
# endif
|
||||
}
|
||||
|
||||
template <class Iterator, class T>
|
||||
void mutable_lvalue_iterator_test(Iterator i, T v1, T v2)
|
||||
void non_const_lvalue_iterator_test(Iterator i, T v1, T v2)
|
||||
{
|
||||
Iterator i2(i);
|
||||
typedef typename detail::iterator_traits<Iterator>::value_type value_type;
|
||||
@@ -91,11 +92,17 @@ void mutable_lvalue_iterator_test(Iterator i, T v1, T v2)
|
||||
BOOST_STATIC_ASSERT((is_same<value_type&, reference>::value));
|
||||
T& v3 = *i2;
|
||||
assert(v1 == v3);
|
||||
|
||||
// A non-const lvalue iterator is not neccessarily writable, but we
|
||||
// are assuming the value_type is assignable here
|
||||
*i = v2;
|
||||
|
||||
T& v4 = *i2;
|
||||
assert(v2 == v4);
|
||||
typedef typename access_category<Iterator>::type result_category;
|
||||
is_mutable_lvalue(result_category());
|
||||
# ifndef BOOST_NO_LVALUE_RETURN_DETECTION
|
||||
BOOST_STATIC_ASSERT(is_lvalue_iterator<Iterator>::value);
|
||||
BOOST_STATIC_ASSERT(is_non_const_lvalue_iterator<Iterator>::value);
|
||||
# endif
|
||||
}
|
||||
|
||||
template <class Iterator, class T>
|
||||
@@ -159,7 +166,6 @@ void bidirectional_readable_iterator_test(Iterator i, T v1, T v2)
|
||||
readable_iterator_test(i2, v2);
|
||||
}
|
||||
|
||||
|
||||
// random access
|
||||
// Preconditions: [i,i+N) is a valid range
|
||||
template <class Iterator, class TrueVals>
|
||||
@@ -169,10 +175,12 @@ void random_access_readable_iterator_test(Iterator i, int N, TrueVals vals)
|
||||
const Iterator j = i;
|
||||
int c;
|
||||
|
||||
for (c = 0; c < N-1; ++c) {
|
||||
for (c = 0; c < N-1; ++c)
|
||||
{
|
||||
assert(i == j + c);
|
||||
assert(*i == vals[c]);
|
||||
assert(*i == j[c]);
|
||||
typename detail::iterator_traits<Iterator>::value_type x = j[c];
|
||||
assert(*i == x);
|
||||
assert(*i == *(j + c));
|
||||
assert(*i == *(c + j));
|
||||
++i;
|
||||
@@ -183,10 +191,12 @@ void random_access_readable_iterator_test(Iterator i, int N, TrueVals vals)
|
||||
}
|
||||
|
||||
Iterator k = j + N - 1;
|
||||
for (c = 0; c < N-1; ++c) {
|
||||
for (c = 0; c < N-1; ++c)
|
||||
{
|
||||
assert(i == k - c);
|
||||
assert(*i == vals[N - 1 - c]);
|
||||
assert(*i == j[N - 1 - c]);
|
||||
typename detail::iterator_traits<Iterator>::value_type x = j[N - 1 - c];
|
||||
assert(*i == x);
|
||||
Iterator q = k - c;
|
||||
assert(*i == *q);
|
||||
assert(i > j);
|
||||
@@ -197,8 +207,8 @@ void random_access_readable_iterator_test(Iterator i, int N, TrueVals vals)
|
||||
}
|
||||
}
|
||||
|
||||
// #if 0'd code snipped; see CVS v 1.4 if you need it back
|
||||
|
||||
} // namespace boost
|
||||
|
||||
# include <boost/iterator/detail/config_undef.hpp>
|
||||
|
||||
#endif // BOOST_NEW_ITERATOR_TESTS_HPP
|
||||
|
||||
@@ -14,15 +14,18 @@
|
||||
#include <boost/iterator/detail/enable_if.hpp>
|
||||
#include <boost/iterator/iterator_adaptor.hpp>
|
||||
#include <boost/iterator/iterator_categories.hpp>
|
||||
#include <boost/mpl/and.hpp>
|
||||
#include <boost/mpl/not.hpp>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <boost/type_traits/function_traits.hpp>
|
||||
#include <boost/type_traits/is_const.hpp>
|
||||
#include <boost/type_traits/is_class.hpp>
|
||||
#include <boost/type_traits/is_function.hpp>
|
||||
#include <boost/type_traits/is_reference.hpp>
|
||||
#include <boost/type_traits/remove_const.hpp>
|
||||
#include <boost/type_traits/remove_reference.hpp>
|
||||
|
||||
#include <boost/iterator/detail/config_def.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
template <class UnaryFunction, class Iterator, class Reference = use_default, class Value = use_default>
|
||||
@@ -45,58 +48,39 @@ namespace boost
|
||||
};
|
||||
#endif
|
||||
|
||||
// Given the transform iterator's transformation and iterator, this
|
||||
// is the type used as its traits.
|
||||
// Compute the iterator_adaptor instantiation to be used for transform_iterator
|
||||
template <class UnaryFunction, class Iterator, class Reference, class Value>
|
||||
struct transform_iterator_base
|
||||
{
|
||||
private:
|
||||
private:
|
||||
// By default, dereferencing the iterator yields the same as
|
||||
// the function. Do we need to adjust the way
|
||||
// function_object_result is computed for the standard
|
||||
// proposal (e.g. using Doug's result_of)?
|
||||
typedef typename ia_dflt_help<
|
||||
Reference
|
||||
, function_object_result<UnaryFunction>
|
||||
>::type reference;
|
||||
|
||||
// transform_iterator does not support writable/swappable iterators
|
||||
#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
|
||||
BOOST_STATIC_ASSERT((is_tag< readable_iterator_tag, typename access_category<Iterator>::type >::value));
|
||||
#endif
|
||||
|
||||
typedef typename mpl::apply_if<
|
||||
is_same< Reference, use_default >
|
||||
, function_object_result<UnaryFunction>
|
||||
, mpl::identity<Reference>
|
||||
>::type result_type;
|
||||
// To get the default for Value: remove any reference on the
|
||||
// result type, but retain any constness to signal
|
||||
// non-writability. Note that if we adopt Thomas' suggestion
|
||||
// to key non-writability *only* on the Reference argument,
|
||||
// we'd need to strip constness here as well.
|
||||
typedef typename ia_dflt_help<
|
||||
Value
|
||||
, remove_reference<reference>
|
||||
>::type cv_value_type;
|
||||
|
||||
typedef typename mpl::if_<
|
||||
is_same< Value, use_default >
|
||||
, typename remove_reference< result_type >::type
|
||||
, Value
|
||||
>::type cv_value_type;
|
||||
|
||||
typedef typename mpl::if_<
|
||||
is_reference< result_type >
|
||||
, typename mpl::if_<
|
||||
is_const< cv_value_type >
|
||||
, readable_lvalue_iterator_tag
|
||||
, writable_lvalue_iterator_tag
|
||||
>::type
|
||||
, readable_iterator_tag
|
||||
>::type maximum_access_tag;
|
||||
|
||||
typedef typename minimum_category<
|
||||
maximum_access_tag
|
||||
, typename access_category<Iterator>::type
|
||||
>::type access_category;
|
||||
|
||||
public:
|
||||
typedef iterator_adaptor<
|
||||
transform_iterator<UnaryFunction, Iterator, Reference, Value>
|
||||
, Iterator
|
||||
, cv_value_type
|
||||
, iterator_tag<
|
||||
access_category
|
||||
, typename traversal_category<Iterator>::type
|
||||
>
|
||||
, result_type
|
||||
> type;
|
||||
public:
|
||||
typedef iterator_adaptor<
|
||||
transform_iterator<UnaryFunction, Iterator, Reference, Value>
|
||||
, Iterator
|
||||
, cv_value_type
|
||||
, use_default // Leave the traversal category alone
|
||||
, reference
|
||||
> type;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template <class UnaryFunction, class Iterator, class Reference, class Value>
|
||||
@@ -115,10 +99,22 @@ namespace boost
|
||||
transform_iterator(Iterator const& x, UnaryFunction f)
|
||||
: super_t(x), m_f(f) { }
|
||||
|
||||
explicit transform_iterator(Iterator const& x)
|
||||
: super_t(x)
|
||||
{
|
||||
// Pro8 is a little too aggressive about instantiating the
|
||||
// body of this function.
|
||||
#if !BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003))
|
||||
// don't provide this constructor if UnaryFunction is a
|
||||
// function pointer type, since it will be 0. Too dangerous.
|
||||
BOOST_STATIC_ASSERT(is_class<UnaryFunction>::value);
|
||||
#endif
|
||||
}
|
||||
|
||||
template<class OtherIterator>
|
||||
transform_iterator(
|
||||
transform_iterator<UnaryFunction, OtherIterator, Reference, Value> const& t
|
||||
, typename enable_if_convertible<OtherIterator, Iterator>::type* = 0
|
||||
transform_iterator<UnaryFunction, OtherIterator, Reference, Value> const& t
|
||||
, typename enable_if_convertible<OtherIterator, Iterator>::type* = 0
|
||||
)
|
||||
: super_t(t.base()), m_f(t.functor()) {}
|
||||
|
||||
@@ -135,9 +131,27 @@ namespace boost
|
||||
};
|
||||
|
||||
template <class UnaryFunction, class Iterator>
|
||||
transform_iterator<UnaryFunction, Iterator> make_transform_iterator(Iterator it, UnaryFunction fun)
|
||||
transform_iterator<UnaryFunction, Iterator>
|
||||
make_transform_iterator(Iterator it, UnaryFunction fun)
|
||||
{
|
||||
return transform_iterator<UnaryFunction, Iterator>(it, fun);
|
||||
return transform_iterator<UnaryFunction, Iterator>(it, fun);
|
||||
}
|
||||
|
||||
// Version which allows explicit specification of the UnaryFunction
|
||||
// type.
|
||||
//
|
||||
// This generator is not provided if UnaryFunction is a function
|
||||
// pointer type, because it's too dangerous: the default-constructed
|
||||
// function pointer in the iterator be 0, leading to a runtime
|
||||
// crash.
|
||||
template <class UnaryFunction, class Iterator>
|
||||
typename iterators::enable_if<
|
||||
is_class<UnaryFunction> // We should probably find a cheaper test than is_class<>
|
||||
, transform_iterator<UnaryFunction, Iterator>
|
||||
>::type
|
||||
make_transform_iterator(Iterator it)
|
||||
{
|
||||
return transform_iterator<UnaryFunction, Iterator>(it, UnaryFunction());
|
||||
}
|
||||
|
||||
#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) && !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
|
||||
@@ -151,4 +165,6 @@ namespace boost
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#include <boost/iterator/detail/config_undef.hpp>
|
||||
|
||||
#endif // BOOST_TRANSFORM_ITERATOR_23022003THW_HPP
|
||||
|
||||
Executable
+611
@@ -0,0 +1,611 @@
|
||||
// (C) Copyright David Abrahams and Thomas Becker 2000. 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.
|
||||
//
|
||||
// Compilers Tested:
|
||||
// =================
|
||||
// Metrowerks Codewarrior Pro 7.2, 8.3
|
||||
// gcc 2.95.3
|
||||
// gcc 3.2
|
||||
// Microsoft VC 6sp5 (test fails due to some compiler bug)
|
||||
// Microsoft VC 7 (works)
|
||||
// Microsoft VC 7.1
|
||||
// Intel 5
|
||||
// Intel 6
|
||||
// Intel 7.1
|
||||
// Intel 8
|
||||
// Borland 5.5.1 (broken due to lack of support from Boost.Tuples)
|
||||
|
||||
#ifndef BOOST_ZIP_ITERATOR_TMB_07_13_2003_HPP_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <boost/iterator.hpp>
|
||||
#include <boost/iterator/iterator_traits.hpp>
|
||||
#include <boost/iterator/iterator_facade.hpp>
|
||||
#include <boost/iterator/iterator_adaptor.hpp> // for enable_if_convertible
|
||||
#include <boost/iterator/iterator_categories.hpp>
|
||||
#include <boost/detail/iterator.hpp>
|
||||
|
||||
#include <boost/iterator/detail/minimum_category.hpp>
|
||||
|
||||
#include <boost/tuple/tuple.hpp>
|
||||
|
||||
#if BOOST_WORKAROUND(__GNUC__, == 2) || BOOST_WORKAROUND(__MWERKS__, <= 0x2407)
|
||||
# include <boost/type_traits/remove_cv.hpp>
|
||||
#endif
|
||||
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/mpl/and.hpp>
|
||||
#include <boost/mpl/apply.hpp>
|
||||
#include <boost/mpl/apply_if.hpp>
|
||||
#include <boost/mpl/lambda.hpp>
|
||||
#include <boost/mpl/placeholders.hpp>
|
||||
#include <boost/mpl/aux_/lambda_support.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
// Zip iterator forward declaration for zip_iterator_base
|
||||
template<typename IteratorTuple>
|
||||
class zip_iterator;
|
||||
|
||||
// One important design goal of the zip_iterator is to isolate all
|
||||
// functionality whose implementation relies on the current tuple
|
||||
// implementation. This goal has been achieved as follows: Inside
|
||||
// the namespace detail there is a namespace tuple_impl_specific.
|
||||
// This namespace encapsulates all functionality that is specific
|
||||
// to the current Boost tuple implementation. More precisely, the
|
||||
// namespace tuple_impl_specific provides the following tuple
|
||||
// algorithms and meta-algorithms for the current Boost tuple
|
||||
// implementation:
|
||||
//
|
||||
// tuple_meta_transform
|
||||
// tuple_meta_accumulate
|
||||
// tuple_transform
|
||||
// tuple_for_each
|
||||
//
|
||||
// If the tuple implementation changes, all that needs to be
|
||||
// replaced is the implementation of these four (meta-)algorithms.
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
// Functors to be used with tuple algorithms
|
||||
//
|
||||
template<typename DiffType>
|
||||
class advance_iterator
|
||||
{
|
||||
public:
|
||||
advance_iterator(DiffType step) : m_step(step) {}
|
||||
|
||||
template<typename Iterator>
|
||||
void operator()(Iterator& it) const
|
||||
{ it += m_step; }
|
||||
|
||||
private:
|
||||
DiffType m_step;
|
||||
};
|
||||
//
|
||||
struct increment_iterator
|
||||
{
|
||||
template<typename Iterator>
|
||||
void operator()(Iterator& it)
|
||||
{ ++it; }
|
||||
};
|
||||
//
|
||||
struct decrement_iterator
|
||||
{
|
||||
template<typename Iterator>
|
||||
void operator()(Iterator& it)
|
||||
{ --it; }
|
||||
};
|
||||
//
|
||||
struct dereference_iterator
|
||||
{
|
||||
template<typename Iterator>
|
||||
struct apply
|
||||
{
|
||||
#if BOOST_WORKAROUND(__GNUC__, == 2) || BOOST_WORKAROUND(__MWERKS__, <= 0x2407)
|
||||
typedef typename
|
||||
iterator_traits<
|
||||
typename boost::remove_cv<Iterator>::type
|
||||
>::reference
|
||||
type;
|
||||
#else
|
||||
typedef typename
|
||||
iterator_traits<Iterator>::reference
|
||||
type;
|
||||
#endif
|
||||
};
|
||||
|
||||
template<typename Iterator>
|
||||
typename apply<Iterator>::type operator()(Iterator& it)
|
||||
{ return *it; }
|
||||
};
|
||||
|
||||
|
||||
// The namespace tuple_impl_specific provides two meta-
|
||||
// algorithms and two algorithms for tuples.
|
||||
//
|
||||
namespace tuple_impl_specific
|
||||
{
|
||||
// Meta-transform algorithm for tuples
|
||||
//
|
||||
template<typename Tuple, class UnaryMetaFun>
|
||||
struct tuple_meta_transform;
|
||||
|
||||
template<typename Tuple, class UnaryMetaFun>
|
||||
struct tuple_meta_transform_impl
|
||||
{
|
||||
typedef tuples::cons<
|
||||
typename mpl::apply1<
|
||||
typename mpl::lambda<UnaryMetaFun>::type
|
||||
, typename Tuple::head_type
|
||||
>::type
|
||||
, typename tuple_meta_transform<
|
||||
typename Tuple::tail_type
|
||||
, UnaryMetaFun
|
||||
>::type
|
||||
> type;
|
||||
};
|
||||
|
||||
template<typename Tuple, class UnaryMetaFun>
|
||||
struct tuple_meta_transform
|
||||
: mpl::apply_if<
|
||||
boost::is_same<Tuple, tuples::null_type>
|
||||
, mpl::identity<tuples::null_type>
|
||||
, tuple_meta_transform_impl<Tuple, UnaryMetaFun>
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
// Meta-accumulate algorithm for tuples. Note: The template
|
||||
// parameter StartType corresponds to the initial value in
|
||||
// ordinary accumulation.
|
||||
//
|
||||
template<class Tuple, class BinaryMetaFun, class StartType>
|
||||
struct tuple_meta_accumulate;
|
||||
|
||||
template<
|
||||
typename Tuple
|
||||
, class BinaryMetaFun
|
||||
, typename StartType
|
||||
>
|
||||
struct tuple_meta_accumulate_impl
|
||||
{
|
||||
typedef typename mpl::apply2<
|
||||
typename mpl::lambda<BinaryMetaFun>::type
|
||||
, typename Tuple::head_type
|
||||
, typename tuple_meta_accumulate<
|
||||
typename Tuple::tail_type
|
||||
, BinaryMetaFun
|
||||
, StartType
|
||||
>::type
|
||||
>::type type;
|
||||
};
|
||||
|
||||
template<
|
||||
typename Tuple
|
||||
, class BinaryMetaFun
|
||||
, typename StartType
|
||||
>
|
||||
struct tuple_meta_accumulate
|
||||
: mpl::apply_if<
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, == 1200)
|
||||
mpl::or_<
|
||||
#endif
|
||||
boost::is_same<Tuple, tuples::null_type>
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, == 1200)
|
||||
, boost::is_same<Tuple,int>
|
||||
>
|
||||
#endif
|
||||
, mpl::identity<StartType>
|
||||
, tuple_meta_accumulate_impl<
|
||||
Tuple
|
||||
, BinaryMetaFun
|
||||
, StartType
|
||||
>
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
#if defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) \
|
||||
|| ( \
|
||||
BOOST_WORKAROUND(BOOST_INTEL_CXX_VERSION, != 0) && defined(_MSC_VER) \
|
||||
)
|
||||
// Not sure why intel's partial ordering fails in this case, but I'm
|
||||
// assuming int's an MSVC bug-compatibility feature.
|
||||
|
||||
# define BOOST_TUPLE_ALGO_DISPATCH
|
||||
# define BOOST_TUPLE_ALGO(algo) algo##_impl
|
||||
# define BOOST_TUPLE_ALGO_TERMINATOR , int
|
||||
# define BOOST_TUPLE_ALGO_RECURSE , ...
|
||||
#else
|
||||
# define BOOST_TUPLE_ALGO(algo) algo
|
||||
# define BOOST_TUPLE_ALGO_TERMINATOR
|
||||
# define BOOST_TUPLE_ALGO_RECURSE
|
||||
#endif
|
||||
|
||||
// transform algorithm for tuples. The template parameter Fun
|
||||
// must be a unary functor which is also a unary metafunction
|
||||
// class that computes its return type based on its argument
|
||||
// type. For example:
|
||||
//
|
||||
// struct to_ptr
|
||||
// {
|
||||
// template <class Arg>
|
||||
// struct apply
|
||||
// {
|
||||
// typedef Arg* type;
|
||||
// }
|
||||
//
|
||||
// template <class Arg>
|
||||
// Arg* operator()(Arg x);
|
||||
// };
|
||||
template<typename Fun>
|
||||
tuples::null_type BOOST_TUPLE_ALGO(tuple_transform)
|
||||
(tuples::null_type const&, Fun BOOST_TUPLE_ALGO_TERMINATOR)
|
||||
{ return tuples::null_type(); }
|
||||
|
||||
template<typename Tuple, typename Fun>
|
||||
typename tuple_meta_transform<
|
||||
Tuple
|
||||
, Fun
|
||||
>::type
|
||||
|
||||
BOOST_TUPLE_ALGO(tuple_transform)(
|
||||
const Tuple& t,
|
||||
Fun f
|
||||
BOOST_TUPLE_ALGO_RECURSE
|
||||
)
|
||||
{
|
||||
typedef typename tuple_meta_transform<
|
||||
BOOST_DEDUCED_TYPENAME Tuple::tail_type
|
||||
, Fun
|
||||
>::type transformed_tail_type;
|
||||
|
||||
return tuples::cons<
|
||||
BOOST_DEDUCED_TYPENAME mpl::apply1<
|
||||
Fun, BOOST_DEDUCED_TYPENAME Tuple::head_type
|
||||
>::type
|
||||
, transformed_tail_type
|
||||
>(
|
||||
f(boost::tuples::get<0>(t)), tuple_transform(t.get_tail(), f)
|
||||
);
|
||||
}
|
||||
|
||||
#ifdef BOOST_TUPLE_ALGO_DISPATCH
|
||||
template<typename Tuple, typename Fun>
|
||||
typename tuple_meta_transform<
|
||||
Tuple
|
||||
, Fun
|
||||
>::type
|
||||
|
||||
tuple_transform(
|
||||
const Tuple& t,
|
||||
Fun f
|
||||
)
|
||||
{
|
||||
return tuple_transform_impl(t, f, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
// for_each algorithm for tuples.
|
||||
//
|
||||
template<typename Fun>
|
||||
Fun BOOST_TUPLE_ALGO(tuple_for_each)(
|
||||
tuples::null_type
|
||||
, Fun f BOOST_TUPLE_ALGO_TERMINATOR
|
||||
)
|
||||
{ return f; }
|
||||
|
||||
|
||||
template<typename Tuple, typename Fun>
|
||||
Fun BOOST_TUPLE_ALGO(tuple_for_each)(
|
||||
Tuple& t
|
||||
, Fun f BOOST_TUPLE_ALGO_RECURSE)
|
||||
{
|
||||
f( t.get_head() );
|
||||
return tuple_for_each(t.get_tail(), f);
|
||||
}
|
||||
|
||||
#ifdef BOOST_TUPLE_ALGO_DISPATCH
|
||||
template<typename Tuple, typename Fun>
|
||||
Fun
|
||||
tuple_for_each(
|
||||
Tuple& t,
|
||||
Fun f
|
||||
)
|
||||
{
|
||||
return tuple_for_each_impl(t, f, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Equality of tuples. NOTE: "==" for tuples currently (7/2003)
|
||||
// has problems under some compilers, so I just do my own.
|
||||
// No point in bringing in a bunch of #ifdefs here. This is
|
||||
// going to go away with the next tuple implementation anyway.
|
||||
//
|
||||
bool tuple_equal(tuples::null_type, tuples::null_type)
|
||||
{ return true; }
|
||||
|
||||
template<typename Tuple1, typename Tuple2>
|
||||
bool tuple_equal(
|
||||
Tuple1 const& t1,
|
||||
Tuple2 const& t2
|
||||
)
|
||||
{
|
||||
return t1.get_head() == t2.get_head() &&
|
||||
tuple_equal(t1.get_tail(), t2.get_tail());
|
||||
}
|
||||
}
|
||||
//
|
||||
// end namespace tuple_impl_specific
|
||||
|
||||
template<typename Iterator>
|
||||
struct iterator_reference
|
||||
{
|
||||
typedef typename iterator_traits<Iterator>::reference type;
|
||||
};
|
||||
|
||||
#ifdef BOOST_MPL_NO_FULL_LAMBDA_SUPPORT
|
||||
// Hack because BOOST_MPL_AUX_LAMBDA_SUPPORT doesn't seem to work
|
||||
// out well. Instantiating the nested apply template also
|
||||
// requires instantiating iterator_traits on the
|
||||
// placeholder. Instead we just specialize it as a metafunction
|
||||
// class.
|
||||
template<>
|
||||
struct iterator_reference<mpl::_1>
|
||||
{
|
||||
template <class T>
|
||||
struct apply : iterator_reference<T> {};
|
||||
};
|
||||
#endif
|
||||
|
||||
// Metafunction to obtain the type of the tuple whose element types
|
||||
// are the reference types of an iterator tuple.
|
||||
//
|
||||
template<typename IteratorTuple>
|
||||
struct tuple_of_references
|
||||
: tuple_impl_specific::tuple_meta_transform<
|
||||
IteratorTuple,
|
||||
iterator_reference<mpl::_1>
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
// Metafunction to obtain the minimal traversal tag in a tuple
|
||||
// of iterators.
|
||||
//
|
||||
template<typename IteratorTuple>
|
||||
struct minimum_traversal_category_in_iterator_tuple
|
||||
{
|
||||
typedef typename tuple_impl_specific::tuple_meta_transform<
|
||||
IteratorTuple
|
||||
, iterator_traversal<>
|
||||
>::type tuple_of_traversal_tags;
|
||||
|
||||
typedef typename tuple_impl_specific::tuple_meta_accumulate<
|
||||
tuple_of_traversal_tags
|
||||
, minimum_category<>
|
||||
, random_access_traversal_tag
|
||||
>::type type;
|
||||
};
|
||||
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, == 1200) // ETI workaround
|
||||
template <>
|
||||
struct minimum_traversal_category_in_iterator_tuple<int>
|
||||
{
|
||||
typedef int type;
|
||||
};
|
||||
#endif
|
||||
|
||||
// We need to call tuple_meta_accumulate with mpl::and_ as the
|
||||
// accumulating functor. To this end, we need to wrap it into
|
||||
// a struct that has exactly two arguments (that is, template
|
||||
// parameters) and not five, like mpl::and_ does.
|
||||
//
|
||||
template<typename Arg1, typename Arg2>
|
||||
struct and_with_two_args
|
||||
: mpl::and_<Arg1, Arg2>
|
||||
{
|
||||
};
|
||||
|
||||
# ifdef BOOST_MPL_NO_FULL_LAMBDA_SUPPORT
|
||||
// Hack because BOOST_MPL_AUX_LAMBDA_SUPPORT doesn't seem to work
|
||||
// out well. In this case I think it's an MPL bug
|
||||
template<>
|
||||
struct and_with_two_args<mpl::_1,mpl::_2>
|
||||
{
|
||||
template <class A1, class A2>
|
||||
struct apply : mpl::and_<A1,A2>
|
||||
{};
|
||||
};
|
||||
# endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Class zip_iterator_base
|
||||
//
|
||||
// Builds and exposes the iterator facade type from which the zip
|
||||
// iterator will be derived.
|
||||
//
|
||||
template<typename IteratorTuple>
|
||||
struct zip_iterator_base
|
||||
{
|
||||
private:
|
||||
// Reference type is the type of the tuple obtained from the
|
||||
// iterators' reference types.
|
||||
typedef typename
|
||||
detail::tuple_of_references<IteratorTuple>::type reference;
|
||||
|
||||
// Value type is the same as reference type.
|
||||
typedef reference value_type;
|
||||
|
||||
// Difference type is the first iterator's difference type
|
||||
typedef typename iterator_traits<
|
||||
typename tuples::element<0, IteratorTuple>::type
|
||||
>::difference_type difference_type;
|
||||
|
||||
// Traversal catetgory is the minimum traversal category in the
|
||||
// iterator tuple.
|
||||
typedef typename
|
||||
detail::minimum_traversal_category_in_iterator_tuple<
|
||||
IteratorTuple
|
||||
>::type traversal_category;
|
||||
public:
|
||||
|
||||
// The iterator facade type from which the zip iterator will
|
||||
// be derived.
|
||||
typedef iterator_facade<
|
||||
zip_iterator<IteratorTuple>,
|
||||
value_type,
|
||||
traversal_category,
|
||||
reference,
|
||||
difference_type
|
||||
> type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct zip_iterator_base<int>
|
||||
{
|
||||
typedef int type;
|
||||
};
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// zip_iterator class definition
|
||||
//
|
||||
template<typename IteratorTuple>
|
||||
class zip_iterator :
|
||||
public detail::zip_iterator_base<IteratorTuple>::type
|
||||
{
|
||||
|
||||
// Typedef super_t as our base class.
|
||||
typedef typename
|
||||
detail::zip_iterator_base<IteratorTuple>::type super_t;
|
||||
|
||||
// iterator_core_access is the iterator's best friend.
|
||||
friend class iterator_core_access;
|
||||
|
||||
public:
|
||||
|
||||
// Construction
|
||||
// ============
|
||||
|
||||
// Default constructor
|
||||
zip_iterator() { }
|
||||
|
||||
// Constructor from iterator tuple
|
||||
zip_iterator(IteratorTuple iterator_tuple)
|
||||
: m_iterator_tuple(iterator_tuple)
|
||||
{ }
|
||||
|
||||
// Copy constructor
|
||||
template<typename OtherIteratorTuple>
|
||||
zip_iterator(
|
||||
const zip_iterator<OtherIteratorTuple>& other,
|
||||
typename enable_if_convertible<
|
||||
OtherIteratorTuple,
|
||||
IteratorTuple
|
||||
>::type* = 0
|
||||
) : m_iterator_tuple(other.get_iterator_tuple())
|
||||
{}
|
||||
|
||||
// Get method for the iterator tuple.
|
||||
const IteratorTuple& get_iterator_tuple() const
|
||||
{ return m_iterator_tuple; }
|
||||
|
||||
private:
|
||||
|
||||
// Implementation of Iterator Operations
|
||||
// =====================================
|
||||
|
||||
// Dereferencing returns a tuple built from the dereferenced
|
||||
// iterators in the iterator tuple.
|
||||
typename super_t::reference dereference() const
|
||||
{
|
||||
return detail::tuple_impl_specific::tuple_transform(
|
||||
get_iterator_tuple(),
|
||||
detail::dereference_iterator()
|
||||
);
|
||||
}
|
||||
|
||||
// Two zip iterators are equal if all iterators in the iterator
|
||||
// tuple are equal. NOTE: It should be possible to implement this
|
||||
// as
|
||||
//
|
||||
// return get_iterator_tuple() == other.get_iterator_tuple();
|
||||
//
|
||||
// but equality of tuples currently (7/2003) does not compile
|
||||
// under several compilers. No point in bringing in a bunch
|
||||
// of #ifdefs here.
|
||||
//
|
||||
template<typename OtherIteratorTuple>
|
||||
bool equal(const zip_iterator<OtherIteratorTuple>& other) const
|
||||
{
|
||||
return detail::tuple_impl_specific::tuple_equal(
|
||||
get_iterator_tuple(),
|
||||
other.get_iterator_tuple()
|
||||
);
|
||||
}
|
||||
|
||||
// Advancing a zip iterator means to advance all iterators in the
|
||||
// iterator tuple.
|
||||
void advance(typename super_t::difference_type n)
|
||||
{
|
||||
detail::tuple_impl_specific::tuple_for_each(
|
||||
m_iterator_tuple,
|
||||
detail::advance_iterator<BOOST_DEDUCED_TYPENAME super_t::difference_type>(n)
|
||||
);
|
||||
}
|
||||
// Incrementing a zip iterator means to increment all iterators in
|
||||
// the iterator tuple.
|
||||
void increment()
|
||||
{
|
||||
detail::tuple_impl_specific::tuple_for_each(
|
||||
m_iterator_tuple,
|
||||
detail::increment_iterator()
|
||||
);
|
||||
}
|
||||
|
||||
// Decrementing a zip iterator means to decrement all iterators in
|
||||
// the iterator tuple.
|
||||
void decrement()
|
||||
{
|
||||
detail::tuple_impl_specific::tuple_for_each(
|
||||
m_iterator_tuple,
|
||||
detail::decrement_iterator()
|
||||
);
|
||||
}
|
||||
|
||||
// Distance is calculated using the first iterator in the tuple.
|
||||
template<typename OtherIteratorTuple>
|
||||
typename super_t::difference_type distance_to(
|
||||
const zip_iterator<OtherIteratorTuple>& other
|
||||
) const
|
||||
{
|
||||
return boost::tuples::get<0>(other.get_iterator_tuple()) -
|
||||
boost::tuples::get<0>(this->get_iterator_tuple());
|
||||
}
|
||||
|
||||
// Data Members
|
||||
// ============
|
||||
|
||||
// The iterator tuple.
|
||||
IteratorTuple m_iterator_tuple;
|
||||
|
||||
};
|
||||
|
||||
// Make function for zip iterator
|
||||
//
|
||||
template<typename IteratorTuple>
|
||||
zip_iterator<IteratorTuple>
|
||||
make_zip_iterator(IteratorTuple t)
|
||||
{ return zip_iterator<IteratorTuple>(t); }
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,13 +0,0 @@
|
||||
// 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_ADAPTOR_13062003HK_HPP
|
||||
#define BOOST_ITERATOR_ADAPTOR_13062003HK_HPP
|
||||
|
||||
#define BOOST_ITERATOR_ADAPTORS_VERSION 0x0200
|
||||
#include <boost/iterator/iterator_adaptor.hpp>
|
||||
|
||||
#endif // BOOST_ITERATOR_ADAPTOR_13062003HK_HPP
|
||||
+50
-14
@@ -1,14 +1,50 @@
|
||||
SEARCH on testing.jam = $(BOOST_BUILD_PATH) ;
|
||||
include testing.jam ;
|
||||
run unit_tests.cpp ;
|
||||
run concept_tests.cpp ;
|
||||
run iterator_adaptor_cc.cpp ;
|
||||
run iterator_adaptor_test.cpp ;
|
||||
compile iterator_archetype_cc.cpp ;
|
||||
run transform_iterator_test.cpp ;
|
||||
run indirect_iterator_test.cpp ;
|
||||
run filter_iterator_test.cpp ;
|
||||
run reverse_iterator_test.cpp ;
|
||||
run counting_iterator_test.cpp ;
|
||||
run is_convertible_fail.cpp ; # test changed to expected success, so that we catch compilation failures.
|
||||
compile-fail interoperable_fail.cpp ;
|
||||
# Copyright David Abrahams 2003. 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.
|
||||
|
||||
subproject libs/iterator/test ;
|
||||
|
||||
import testing ;
|
||||
|
||||
test-suite iterator
|
||||
:
|
||||
# These first two tests will run last, and are expected to fail
|
||||
# for many less-capable compilers.
|
||||
|
||||
[ compile-fail interoperable_fail.cpp ]
|
||||
# test uses expected success, so that we catch unrelated
|
||||
# compilation problems.
|
||||
[ run is_convertible_fail.cpp ]
|
||||
|
||||
[ run zip_iterator_test.cpp ]
|
||||
|
||||
# These tests should work for just about everything.
|
||||
[ compile is_lvalue_iterator.cpp ]
|
||||
[ compile is_readable_iterator.cpp ]
|
||||
|
||||
[ run unit_tests.cpp ]
|
||||
[ run concept_tests.cpp ]
|
||||
[ run iterator_adaptor_cc.cpp ]
|
||||
[ run iterator_adaptor_test.cpp ]
|
||||
[ compile iterator_archetype_cc.cpp ]
|
||||
[ run transform_iterator_test.cpp ]
|
||||
[ run indirect_iterator_test.cpp ]
|
||||
[ run filter_iterator_test.cpp ]
|
||||
[ run reverse_iterator_test.cpp ]
|
||||
[ run counting_iterator_test.cpp ]
|
||||
[ run permutation_iterator_test.cpp : : : # <stlport-iostream>on
|
||||
]
|
||||
|
||||
[ run ../../utility/iterator_adaptor_examples.cpp ]
|
||||
[ run ../../utility/counting_iterator_example.cpp ]
|
||||
[ run ../../utility/filter_iterator_example.cpp ]
|
||||
[ run ../../utility/fun_out_iter_example.cpp ]
|
||||
[ run ../../utility/indirect_iterator_example.cpp ]
|
||||
[ run ../../utility/projection_iterator_example.cpp ]
|
||||
[ run ../../utility/reverse_iterator_example.cpp ]
|
||||
[ run ../../utility/transform_iterator_example.cpp ]
|
||||
[ run ../../utility/iterator_traits_test.cpp ]
|
||||
|
||||
;
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
# Copyright David Abrahams 2003. 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.
|
||||
|
||||
import testing ;
|
||||
|
||||
test-suite iterator
|
||||
:
|
||||
# These first two tests will run last, and are expected to fail
|
||||
# for many less-capable compilers.
|
||||
|
||||
[ compile-fail interoperable_fail.cpp ]
|
||||
# test uses expected success, so that we catch unrelated
|
||||
# compilation problems.
|
||||
[ run is_convertible_fail.cpp ]
|
||||
|
||||
# These tests should work for just about everything.
|
||||
[ run unit_tests.cpp ]
|
||||
[ run concept_tests.cpp ]
|
||||
[ run iterator_adaptor_cc.cpp ]
|
||||
[ run iterator_adaptor_test.cpp ]
|
||||
[ compile iterator_archetype_cc.cpp ]
|
||||
[ run transform_iterator_test.cpp ]
|
||||
[ run indirect_iterator_test.cpp ]
|
||||
[ run filter_iterator_test.cpp ]
|
||||
[ run reverse_iterator_test.cpp ]
|
||||
[ run counting_iterator_test.cpp ]
|
||||
[ run permutation_iterator_test.cpp : : : # <stlport-iostream>on
|
||||
]
|
||||
[ run zip_iterator_test.cpp ]
|
||||
|
||||
[ run ../../utility/iterator_adaptor_examples.cpp ]
|
||||
[ run ../../utility/counting_iterator_example.cpp ]
|
||||
[ run ../../utility/filter_iterator_example.cpp ]
|
||||
[ run ../../utility/fun_out_iter_example.cpp ]
|
||||
[ run ../../utility/indirect_iterator_example.cpp ]
|
||||
[ run ../../utility/projection_iterator_example.cpp ]
|
||||
[ run ../../utility/reverse_iterator_example.cpp ]
|
||||
[ run ../../utility/transform_iterator_example.cpp ]
|
||||
[ run ../../utility/iterator_traits_test.cpp ]
|
||||
|
||||
;
|
||||
+11
-102
@@ -5,15 +5,16 @@
|
||||
// to its suitability for any purpose.
|
||||
|
||||
#include <boost/iterator/iterator_concepts.hpp>
|
||||
#include <boost/iterator/iterator_categories.hpp>
|
||||
#include <boost/operators.hpp>
|
||||
#include <boost/static_assert.hpp> // remove
|
||||
#include <boost/detail/workaround.hpp>
|
||||
#include "static_assert_same.hpp" // remove
|
||||
|
||||
struct new_random_access
|
||||
: std::random_access_iterator_tag
|
||||
, boost::random_access_traversal_tag
|
||||
{};
|
||||
|
||||
struct new_iterator
|
||||
: public boost::iterator< boost::iterator_tag<
|
||||
boost::writable_lvalue_iterator_tag
|
||||
, boost::random_access_traversal_tag>, int>
|
||||
: public boost::iterator< new_random_access, int >
|
||||
{
|
||||
int& operator*() const { return *m_x; }
|
||||
new_iterator& operator++() { return *this; }
|
||||
@@ -52,104 +53,13 @@ struct old_iterator
|
||||
};
|
||||
old_iterator operator+(std::ptrdiff_t, old_iterator x) { return x; }
|
||||
|
||||
struct my_writable_lvalue_iterator_tag
|
||||
{
|
||||
operator boost::writable_lvalue_iterator_tag() const;
|
||||
};
|
||||
|
||||
struct my_single_pass_traversal_tag
|
||||
{
|
||||
operator boost::single_pass_traversal_tag() const;
|
||||
};
|
||||
|
||||
void test_tag_convertibility()
|
||||
{
|
||||
// This set of tests is by no means complete.
|
||||
|
||||
// Test that this is an input/output iterator
|
||||
#if !BOOST_WORKAROUND(__MWERKS__, <= 0x2407)
|
||||
{
|
||||
typedef boost::iterator_tag<
|
||||
boost::writable_lvalue_iterator_tag
|
||||
, boost::single_pass_traversal_tag
|
||||
> tag;
|
||||
|
||||
BOOST_STATIC_ASSERT((
|
||||
boost::is_convertible<tag, std::output_iterator_tag>::value
|
||||
));
|
||||
BOOST_STATIC_ASSERT((
|
||||
boost::is_convertible<tag, std::input_iterator_tag>::value
|
||||
));
|
||||
BOOST_STATIC_ASSERT((
|
||||
!boost::is_convertible<tag, std::forward_iterator_tag>::value
|
||||
));
|
||||
}
|
||||
|
||||
// Test that it's possible to build new sub-tags without
|
||||
// derivation. Convertibility should be enough
|
||||
{
|
||||
typedef boost::iterator_tag<
|
||||
my_writable_lvalue_iterator_tag
|
||||
, my_single_pass_traversal_tag
|
||||
> tag;
|
||||
|
||||
BOOST_STATIC_ASSERT((
|
||||
boost::is_convertible<tag, std::output_iterator_tag>::value
|
||||
));
|
||||
BOOST_STATIC_ASSERT((
|
||||
boost::is_convertible<tag, std::input_iterator_tag>::value
|
||||
));
|
||||
BOOST_STATIC_ASSERT((
|
||||
!boost::is_convertible<tag, std::forward_iterator_tag>::value
|
||||
));
|
||||
}
|
||||
|
||||
// Test that a single-pass readable lvalue iterator is only an
|
||||
// input iterator. Requires special case handling in
|
||||
// categories.hpp
|
||||
{
|
||||
typedef boost::iterator_tag<
|
||||
boost::readable_lvalue_iterator_tag
|
||||
, boost::single_pass_traversal_tag
|
||||
> tag;
|
||||
BOOST_STATIC_ASSERT((
|
||||
boost::is_convertible<tag, std::input_iterator_tag>::value
|
||||
));
|
||||
BOOST_STATIC_ASSERT((
|
||||
!boost::is_convertible<tag, std::output_iterator_tag>::value
|
||||
));
|
||||
BOOST_STATIC_ASSERT((
|
||||
!boost::is_convertible<tag, std::forward_iterator_tag>::value
|
||||
));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
test_tag_convertibility();
|
||||
|
||||
typedef boost::iterator_tag< boost::writable_lvalue_iterator_tag, boost::random_access_traversal_tag > tag;
|
||||
|
||||
// BOOST_STATIC_ASSERT((boost::detail::is_random_access_iterator<tag>::value));
|
||||
int test = static_assert_same<tag::access, boost::writable_lvalue_iterator_tag>::value;
|
||||
test = static_assert_same<tag::traversal, boost::random_access_traversal_tag>::value;
|
||||
|
||||
// BOOST_STATIC_ASSERT((boost::detail::is_random_access_iterator<new_iterator::iterator_category>::value));
|
||||
test = static_assert_same<new_iterator::iterator_category::access, boost::writable_lvalue_iterator_tag>::value;
|
||||
test = static_assert_same<new_iterator::iterator_category::traversal, boost::random_access_traversal_tag>::value;
|
||||
|
||||
typedef boost::traversal_category<new_iterator>::type traversal_category;
|
||||
|
||||
// BOOST_STATIC_ASSERT(boost::detail::has_traversal<new_iterator::iterator_category>::value);
|
||||
BOOST_STATIC_ASSERT(boost::detail::is_new_iterator_tag<new_iterator::iterator_category>::value);
|
||||
|
||||
|
||||
test = static_assert_same<traversal_category, boost::random_access_traversal_tag>::value;
|
||||
(void)test;
|
||||
|
||||
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
|
||||
boost::iterator_traversal<new_iterator>::type tc;
|
||||
boost::random_access_traversal_tag derived = tc;
|
||||
(void)derived;
|
||||
|
||||
boost::function_requires<
|
||||
boost_concepts::WritableLvalueIteratorConcept<int*> >();
|
||||
boost::function_requires<
|
||||
@@ -159,7 +69,6 @@ main()
|
||||
boost_concepts::ReadableLvalueIteratorConcept<const int*> >();
|
||||
boost::function_requires<
|
||||
boost_concepts::RandomAccessTraversalConcept<const int*> >();
|
||||
#endif
|
||||
|
||||
boost::function_requires<
|
||||
boost_concepts::WritableLvalueIteratorConcept<new_iterator> >();
|
||||
|
||||
Executable → Regular
+1
-1
@@ -286,7 +286,7 @@ int main()
|
||||
# ifndef BOOST_NO_SLIST
|
||||
test_container<BOOST_STD_EXTENSION_NAMESPACE::slist<int> >();
|
||||
# endif
|
||||
|
||||
|
||||
// Also prove that we can handle raw pointers.
|
||||
int array[2000];
|
||||
test(boost::make_counting_iterator(array), boost::make_counting_iterator(array+2000-1));
|
||||
|
||||
@@ -7,12 +7,13 @@
|
||||
#include <boost/iterator/filter_iterator.hpp>
|
||||
#include <boost/iterator/reverse_iterator.hpp>
|
||||
#include <boost/iterator/new_iterator_tests.hpp>
|
||||
#include <boost/type_traits/is_convertible.hpp>
|
||||
|
||||
#include <deque>
|
||||
#include <iostream>
|
||||
|
||||
using boost::dummyT;
|
||||
|
||||
|
||||
struct one_or_four
|
||||
{
|
||||
bool operator()(dummyT x) const
|
||||
@@ -21,14 +22,6 @@ struct one_or_four
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
namespace boost { namespace detail
|
||||
{
|
||||
template<> struct iterator_traits<dummyT*>
|
||||
: ptr_iter_traits<dummyT> {};
|
||||
}}
|
||||
#endif
|
||||
|
||||
template <class T> struct undefined;
|
||||
|
||||
// Test filter iterator
|
||||
@@ -44,12 +37,12 @@ int main()
|
||||
filter_iter(one_or_four(), array, array+N)
|
||||
, dummyT(1), dummyT(4));
|
||||
|
||||
BOOST_STATIC_ASSERT((
|
||||
!boost::detail::is_tag<
|
||||
boost::random_access_traversal_tag
|
||||
, boost::traversal_category<filter_iter>::type
|
||||
>::value
|
||||
));
|
||||
BOOST_STATIC_ASSERT(
|
||||
(!boost::is_convertible<
|
||||
boost::iterator_traversal<filter_iter>::type
|
||||
, boost::random_access_traversal_tag
|
||||
>::value
|
||||
));
|
||||
|
||||
//# endif
|
||||
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/utility.hpp>
|
||||
|
||||
#include <boost/type_traits/broken_compiler_spec.hpp>
|
||||
#include <vector>
|
||||
#include <stdlib.h>
|
||||
#include <set>
|
||||
|
||||
@@ -36,35 +38,18 @@
|
||||
|
||||
// std container random-access iterators don't support mutable/const
|
||||
// interoperability (but may support const/mutable interop).
|
||||
# define NO_MUTABLE_CONST_STD_DEQUE_ITERATOR_INTEROPERABILITY
|
||||
# define NO_MUTABLE_CONST_STD_SET_ITERATOR_INTEROPERABILITY
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_MSVC_STD_ITERATOR) \
|
||||
|| defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
|
||||
|
||||
// No working iterator_traits implementation, so we must use deque
|
||||
# define RA_CONTAINER std::deque
|
||||
# include <deque>
|
||||
|
||||
# ifdef NO_MUTABLE_CONST_STD_DEQUE_ITERATOR_INTEROPERABILITY
|
||||
# define NO_MUTABLE_CONST_RA_ITERATOR_INTEROPERABILITY
|
||||
# endif
|
||||
|
||||
#else
|
||||
|
||||
# define RA_CONTAINER std::vector
|
||||
# include <vector>
|
||||
|
||||
#endif
|
||||
|
||||
struct my_iterator_tag : public std::random_access_iterator_tag { };
|
||||
|
||||
using boost::dummyT;
|
||||
|
||||
typedef RA_CONTAINER<int> storage;
|
||||
typedef RA_CONTAINER<int*> pointer_ra_container;
|
||||
BOOST_TT_BROKEN_COMPILER_SPEC(boost::shared_ptr<dummyT>)
|
||||
|
||||
typedef std::vector<int> storage;
|
||||
typedef std::vector<int*> pointer_ra_container;
|
||||
typedef std::set<storage::iterator> iterator_set;
|
||||
|
||||
template <class Container>
|
||||
@@ -78,36 +63,8 @@ struct indirect_iterator_pair_generator
|
||||
> const_iterator;
|
||||
};
|
||||
|
||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
namespace boost { namespace detail
|
||||
{
|
||||
template<> struct iterator_traits<int*>
|
||||
: ptr_iter_traits<int> {};
|
||||
|
||||
template<> struct iterator_traits<dummyT*>
|
||||
: ptr_iter_traits<dummyT> {};
|
||||
|
||||
template<> struct iterator_traits<dummyT*const>
|
||||
: ptr_iter_traits<dummyT> {};
|
||||
|
||||
template<> struct iterator_traits<dummyT const*>
|
||||
: ptr_iter_traits<dummyT, dummyT const> {};
|
||||
|
||||
template<> struct iterator_traits<dummyT**>
|
||||
: ptr_iter_traits<dummyT*> {};
|
||||
|
||||
template<> struct iterator_traits<dummyT*const*>
|
||||
: ptr_iter_traits<dummyT*const> {};
|
||||
|
||||
template<> struct iterator_traits<dummyT const*const*>
|
||||
: ptr_iter_traits<dummyT const*, dummyT const*const> {};
|
||||
}}
|
||||
#endif
|
||||
|
||||
|
||||
void more_indirect_iterator_tests()
|
||||
{
|
||||
# if 0
|
||||
storage store(1000);
|
||||
std::generate(store.begin(), store.end(), rand);
|
||||
|
||||
@@ -177,7 +134,6 @@ void more_indirect_iterator_tests()
|
||||
|
||||
boost::bidirectional_iterator_test(boost::next(sb), store[1], store[2]);
|
||||
assert(std::equal(db, de, store.begin()));
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
@@ -187,7 +143,7 @@ main()
|
||||
dummyT(3), dummyT(4), dummyT(5) };
|
||||
const int N = sizeof(array)/sizeof(dummyT);
|
||||
|
||||
typedef RA_CONTAINER<boost::shared_ptr<dummyT> > shared_t;
|
||||
typedef std::vector<boost::shared_ptr<dummyT> > shared_t;
|
||||
shared_t shared;
|
||||
|
||||
// Concept checks
|
||||
|
||||
Executable
+145
@@ -0,0 +1,145 @@
|
||||
// Copyright David Abrahams 2003. Use, modification and distribution is
|
||||
// subject to the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <deque>
|
||||
#include <iterator>
|
||||
#include <iostream>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <boost/type_traits/broken_compiler_spec.hpp>
|
||||
#include <boost/iterator/is_lvalue_iterator.hpp>
|
||||
#include <boost/iterator.hpp>
|
||||
|
||||
// Last, for BOOST_NO_LVALUE_RETURN_DETECTION
|
||||
#include <boost/iterator/detail/config_def.hpp>
|
||||
|
||||
struct v
|
||||
{
|
||||
v();
|
||||
~v();
|
||||
};
|
||||
|
||||
BOOST_TT_BROKEN_COMPILER_SPEC(v)
|
||||
|
||||
struct value_iterator : boost::iterator<std::input_iterator_tag,v>
|
||||
{
|
||||
v operator*() const;
|
||||
};
|
||||
|
||||
struct noncopyable_iterator : boost::iterator<std::forward_iterator_tag,boost::noncopyable>
|
||||
{
|
||||
boost::noncopyable const& operator*() const;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct proxy_iterator
|
||||
: boost::iterator<std::output_iterator_tag,T>
|
||||
{
|
||||
typedef T value_type;
|
||||
|
||||
#if BOOST_WORKAROUND(__GNUC__, == 2)
|
||||
typedef boost::iterator<std::input_iterator_tag,value_type> base;
|
||||
typedef base::iterator_category iterator_category;
|
||||
typedef base::difference_type difference_type;
|
||||
typedef base::pointer pointer;
|
||||
typedef base::reference reference;
|
||||
#endif
|
||||
|
||||
struct proxy
|
||||
{
|
||||
operator value_type&() const;
|
||||
proxy& operator=(value_type) const;
|
||||
};
|
||||
|
||||
proxy operator*() const;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct lvalue_iterator
|
||||
{
|
||||
typedef T value_type;
|
||||
typedef T& reference;
|
||||
typedef T difference_type;
|
||||
typedef std::input_iterator_tag iterator_category;
|
||||
typedef T* pointer;
|
||||
|
||||
T& operator*() const;
|
||||
lvalue_iterator& operator++();
|
||||
lvalue_iterator operator++(int);
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct constant_lvalue_iterator
|
||||
{
|
||||
typedef T value_type;
|
||||
typedef T const& reference;
|
||||
typedef T difference_type;
|
||||
typedef std::input_iterator_tag iterator_category;
|
||||
typedef T const* pointer;
|
||||
|
||||
T const& operator*() const;
|
||||
constant_lvalue_iterator& operator++();
|
||||
constant_lvalue_iterator operator++(int);
|
||||
};
|
||||
|
||||
BOOST_TT_BROKEN_COMPILER_SPEC(proxy_iterator<v>::proxy)
|
||||
BOOST_TT_BROKEN_COMPILER_SPEC(proxy_iterator<int>::proxy)
|
||||
|
||||
int main()
|
||||
{
|
||||
BOOST_STATIC_ASSERT(boost::is_lvalue_iterator<v*>::value);
|
||||
BOOST_STATIC_ASSERT(boost::is_lvalue_iterator<v const*>::value);
|
||||
BOOST_STATIC_ASSERT(boost::is_lvalue_iterator<std::deque<v>::iterator>::value);
|
||||
BOOST_STATIC_ASSERT(boost::is_lvalue_iterator<std::deque<v>::const_iterator>::value);
|
||||
BOOST_STATIC_ASSERT(!boost::is_lvalue_iterator<std::back_insert_iterator<std::deque<v> > >::value);
|
||||
BOOST_STATIC_ASSERT(!boost::is_lvalue_iterator<std::ostream_iterator<v> >::value);
|
||||
BOOST_STATIC_ASSERT(!boost::is_lvalue_iterator<proxy_iterator<v> >::value);
|
||||
BOOST_STATIC_ASSERT(!boost::is_lvalue_iterator<proxy_iterator<int> >::value);
|
||||
#ifndef BOOST_NO_LVALUE_RETURN_DETECTION
|
||||
BOOST_STATIC_ASSERT(!boost::is_lvalue_iterator<value_iterator>::value);
|
||||
#endif
|
||||
// Make sure inaccessible copy constructor doesn't prevent
|
||||
// reference binding
|
||||
BOOST_STATIC_ASSERT(boost::is_lvalue_iterator<noncopyable_iterator>::value);
|
||||
|
||||
BOOST_STATIC_ASSERT(boost::is_lvalue_iterator<lvalue_iterator<v> >::value);
|
||||
BOOST_STATIC_ASSERT(boost::is_lvalue_iterator<lvalue_iterator<int> >::value);
|
||||
BOOST_STATIC_ASSERT(boost::is_lvalue_iterator<lvalue_iterator<char*> >::value);
|
||||
BOOST_STATIC_ASSERT(boost::is_lvalue_iterator<lvalue_iterator<float> >::value);
|
||||
|
||||
|
||||
BOOST_STATIC_ASSERT(boost::is_lvalue_iterator<constant_lvalue_iterator<v> >::value);
|
||||
BOOST_STATIC_ASSERT(boost::is_lvalue_iterator<constant_lvalue_iterator<int> >::value);
|
||||
BOOST_STATIC_ASSERT(boost::is_lvalue_iterator<constant_lvalue_iterator<char*> >::value);
|
||||
BOOST_STATIC_ASSERT(boost::is_lvalue_iterator<constant_lvalue_iterator<float> >::value);
|
||||
|
||||
|
||||
|
||||
BOOST_STATIC_ASSERT(boost::is_non_const_lvalue_iterator<v*>::value);
|
||||
BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator<v const*>::value);
|
||||
BOOST_STATIC_ASSERT(boost::is_non_const_lvalue_iterator<std::deque<v>::iterator>::value);
|
||||
BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator<std::deque<v>::const_iterator>::value);
|
||||
BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator<std::back_insert_iterator<std::deque<v> > >::value);
|
||||
BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator<std::ostream_iterator<v> >::value);
|
||||
BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator<proxy_iterator<v> >::value);
|
||||
BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator<proxy_iterator<int> >::value);
|
||||
#ifndef BOOST_NO_LVALUE_RETURN_DETECTION
|
||||
BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator<value_iterator>::value);
|
||||
#endif
|
||||
BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator<noncopyable_iterator>::value);
|
||||
|
||||
BOOST_STATIC_ASSERT(boost::is_non_const_lvalue_iterator<lvalue_iterator<v> >::value);
|
||||
#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
|
||||
BOOST_STATIC_ASSERT(boost::is_non_const_lvalue_iterator<lvalue_iterator<int> >::value);
|
||||
#endif
|
||||
BOOST_STATIC_ASSERT(boost::is_non_const_lvalue_iterator<lvalue_iterator<char*> >::value);
|
||||
BOOST_STATIC_ASSERT(boost::is_non_const_lvalue_iterator<lvalue_iterator<float> >::value);
|
||||
|
||||
BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator<constant_lvalue_iterator<v> >::value);
|
||||
BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator<constant_lvalue_iterator<int> >::value);
|
||||
BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator<constant_lvalue_iterator<char*> >::value);
|
||||
BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator<constant_lvalue_iterator<float> >::value);
|
||||
|
||||
return 0;
|
||||
}
|
||||
Executable
+93
@@ -0,0 +1,93 @@
|
||||
// Copyright David Abrahams 2003. Use, modification and distribution is
|
||||
// subject to the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <deque>
|
||||
#include <iterator>
|
||||
#include <iostream>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <boost/type_traits/broken_compiler_spec.hpp>
|
||||
#include <boost/iterator/is_readable_iterator.hpp>
|
||||
#include <boost/iterator.hpp>
|
||||
|
||||
// Last, for BOOST_NO_LVALUE_RETURN_DETECTION
|
||||
#include <boost/iterator/detail/config_def.hpp>
|
||||
|
||||
struct v
|
||||
{
|
||||
v();
|
||||
~v();
|
||||
};
|
||||
|
||||
BOOST_TT_BROKEN_COMPILER_SPEC(v)
|
||||
|
||||
struct value_iterator : boost::iterator<std::input_iterator_tag,v>
|
||||
{
|
||||
v operator*() const;
|
||||
};
|
||||
|
||||
struct noncopyable_iterator : boost::iterator<std::forward_iterator_tag,boost::noncopyable>
|
||||
{
|
||||
boost::noncopyable const& operator*() const;
|
||||
};
|
||||
|
||||
struct proxy_iterator : boost::iterator<std::output_iterator_tag,v>
|
||||
{
|
||||
#if BOOST_WORKAROUND(__GNUC__, == 2)
|
||||
typedef boost::iterator<std::input_iterator_tag,v> base;
|
||||
typedef base::iterator_category iterator_category;
|
||||
typedef base::value_type value_type;
|
||||
typedef base::difference_type difference_type;
|
||||
typedef base::pointer pointer;
|
||||
typedef base::reference reference;
|
||||
#endif
|
||||
|
||||
struct proxy
|
||||
{
|
||||
operator v&();
|
||||
proxy& operator=(v) const;
|
||||
};
|
||||
|
||||
proxy operator*() const;
|
||||
};
|
||||
|
||||
struct proxy_iterator2 : boost::iterator<std::output_iterator_tag,v>
|
||||
{
|
||||
#if BOOST_WORKAROUND(__GNUC__, == 2)
|
||||
typedef boost::iterator<std::input_iterator_tag,v> base;
|
||||
typedef base::iterator_category iterator_category;
|
||||
typedef base::value_type value_type;
|
||||
typedef base::difference_type difference_type;
|
||||
typedef base::pointer pointer;
|
||||
typedef base::reference reference;
|
||||
#endif
|
||||
|
||||
struct proxy
|
||||
{
|
||||
proxy& operator=(v) const;
|
||||
};
|
||||
|
||||
proxy operator*() const;
|
||||
};
|
||||
|
||||
BOOST_TT_BROKEN_COMPILER_SPEC(proxy_iterator::proxy)
|
||||
|
||||
int main()
|
||||
{
|
||||
BOOST_STATIC_ASSERT(boost::is_readable_iterator<v*>::value);
|
||||
BOOST_STATIC_ASSERT(boost::is_readable_iterator<v const*>::value);
|
||||
BOOST_STATIC_ASSERT(boost::is_readable_iterator<std::deque<v>::iterator>::value);
|
||||
BOOST_STATIC_ASSERT(boost::is_readable_iterator<std::deque<v>::const_iterator>::value);
|
||||
BOOST_STATIC_ASSERT(!boost::is_readable_iterator<std::back_insert_iterator<std::deque<v> > >::value);
|
||||
BOOST_STATIC_ASSERT(!boost::is_readable_iterator<std::ostream_iterator<v> >::value);
|
||||
BOOST_STATIC_ASSERT(boost::is_readable_iterator<proxy_iterator>::value);
|
||||
BOOST_STATIC_ASSERT(!boost::is_readable_iterator<proxy_iterator2>::value);
|
||||
BOOST_STATIC_ASSERT(boost::is_readable_iterator<value_iterator>::value);
|
||||
|
||||
// Make sure inaccessible copy constructor doesn't prevent
|
||||
// readability
|
||||
BOOST_STATIC_ASSERT(boost::is_readable_iterator<noncopyable_iterator>::value);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -4,17 +4,6 @@
|
||||
#include <boost/cstdlib.hpp>
|
||||
#include <list>
|
||||
|
||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
namespace boost { namespace detail
|
||||
{
|
||||
template<> struct iterator_traits<int*>
|
||||
: ptr_iter_traits<int> {};
|
||||
|
||||
template<> struct iterator_traits<int const*>
|
||||
: ptr_iter_traits<int, int const> {};
|
||||
}}
|
||||
#endif
|
||||
|
||||
int main()
|
||||
{
|
||||
{
|
||||
|
||||
@@ -14,8 +14,14 @@
|
||||
#include <numeric>
|
||||
|
||||
#include <boost/iterator/iterator_adaptor.hpp>
|
||||
#if !BOOST_WORKAROUND(__MWERKS__, <= 0x2407)
|
||||
# include <boost/iterator/is_readable_iterator.hpp>
|
||||
# include <boost/iterator/is_lvalue_iterator.hpp>
|
||||
#endif
|
||||
#include <boost/pending/iterator_tests.hpp>
|
||||
|
||||
# include <boost/type_traits/broken_compiler_spec.hpp>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
@@ -24,11 +30,10 @@
|
||||
|
||||
#include "static_assert_same.hpp"
|
||||
|
||||
struct my_iterator_tag : public std::random_access_iterator_tag { };
|
||||
#include <boost/iterator/detail/config_def.hpp>
|
||||
|
||||
using boost::dummyT;
|
||||
|
||||
|
||||
struct mult_functor {
|
||||
typedef int result_type;
|
||||
typedef int argument_type;
|
||||
@@ -82,7 +87,7 @@ struct ptr_iterator
|
||||
ptr_iterator<V>
|
||||
, V*
|
||||
, V
|
||||
, std::random_access_iterator_tag
|
||||
, boost::random_access_traversal_tag
|
||||
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
|
||||
, V&
|
||||
#endif
|
||||
@@ -93,7 +98,7 @@ private:
|
||||
ptr_iterator<V>
|
||||
, V*
|
||||
, V
|
||||
, std::random_access_iterator_tag
|
||||
, boost::random_access_traversal_tag
|
||||
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
|
||||
, V&
|
||||
#endif
|
||||
@@ -112,6 +117,17 @@ public:
|
||||
{}
|
||||
};
|
||||
|
||||
// Non-functional iterator for category modification checking
|
||||
template <class Iter, class Traversal>
|
||||
struct modify_traversal
|
||||
: boost::iterator_adaptor<
|
||||
modify_traversal<Iter, Traversal>
|
||||
, Iter
|
||||
, boost::use_default
|
||||
, Traversal
|
||||
>
|
||||
{};
|
||||
|
||||
template <class T>
|
||||
struct fwd_iterator
|
||||
: boost::iterator_adaptor<
|
||||
@@ -167,6 +183,33 @@ struct constant_iterator
|
||||
: base_t(it) {}
|
||||
};
|
||||
|
||||
char (& traversal2(boost::incrementable_traversal_tag) )[1];
|
||||
char (& traversal2(boost::single_pass_traversal_tag ) )[2];
|
||||
char (& traversal2(boost::forward_traversal_tag ) )[3];
|
||||
char (& traversal2(boost::bidirectional_traversal_tag) )[4];
|
||||
char (& traversal2(boost::random_access_traversal_tag) )[5];
|
||||
|
||||
template <class Cat>
|
||||
struct traversal3
|
||||
{
|
||||
static typename boost::iterator_category_to_traversal<Cat>::type x;
|
||||
BOOST_STATIC_CONSTANT(std::size_t, value = sizeof(traversal2(x)));
|
||||
typedef char (&type)[value];
|
||||
};
|
||||
|
||||
template <class Cat>
|
||||
typename traversal3<Cat>::type traversal(Cat);
|
||||
|
||||
template <class Iter, class Trav>
|
||||
int static_assert_traversal(Iter* = 0, Trav* = 0)
|
||||
{
|
||||
typedef typename boost::iterator_category_to_traversal<
|
||||
BOOST_DEDUCED_TYPENAME Iter::iterator_category
|
||||
>::type t2;
|
||||
|
||||
return static_assert_same<Trav,t2>::value;
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
@@ -207,7 +250,17 @@ main()
|
||||
typedef ptr_iterator<int const> Iter1;
|
||||
test = static_assert_same<Iter1::value_type, int>::value;
|
||||
test = static_assert_same<Iter1::reference, const int&>::value;
|
||||
test = static_assert_same<Iter1::iterator_category::access, boost::readable_lvalue_iterator_tag>::value; test = static_assert_same<Iter1::pointer, const int*>::value;
|
||||
|
||||
#if !BOOST_WORKAROUND(__MWERKS__, <= 0x2407)
|
||||
BOOST_STATIC_ASSERT(boost::is_readable_iterator<Iter1>::value);
|
||||
# ifndef BOOST_NO_LVALUE_RETURN_DETECTION
|
||||
BOOST_STATIC_ASSERT(boost::is_lvalue_iterator<Iter1>::value);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) // borland drops constness
|
||||
test = static_assert_same<Iter1::pointer, int const*>::value;
|
||||
#endif
|
||||
}
|
||||
|
||||
{
|
||||
@@ -217,10 +270,19 @@ main()
|
||||
|
||||
test = static_assert_same<Iter::value_type, int>::value;
|
||||
test = static_assert_same<Iter::reference, int const&>::value;
|
||||
#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) // borland drops constness
|
||||
test = static_assert_same<Iter::pointer, int const*>::value;
|
||||
#endif
|
||||
|
||||
test = static_assert_same<BaseIter::iterator_category::access, boost::writable_lvalue_iterator_tag>::value;
|
||||
test = static_assert_same<Iter::iterator_category::access, boost::readable_lvalue_iterator_tag>::value;
|
||||
#ifndef BOOST_NO_LVALUE_RETURN_DETECTION
|
||||
BOOST_STATIC_ASSERT(boost::is_non_const_lvalue_iterator<BaseIter>::value);
|
||||
BOOST_STATIC_ASSERT(boost::is_lvalue_iterator<Iter>::value);
|
||||
#endif
|
||||
|
||||
typedef modify_traversal<BaseIter, boost::incrementable_traversal_tag> IncrementableIter;
|
||||
|
||||
static_assert_traversal<BaseIter,boost::random_access_traversal_tag>();
|
||||
static_assert_traversal<IncrementableIter,boost::incrementable_traversal_tag>();
|
||||
}
|
||||
|
||||
// Test the iterator_adaptor
|
||||
|
||||
@@ -12,14 +12,15 @@
|
||||
|
||||
int main()
|
||||
{
|
||||
{
|
||||
typedef boost::iterator_archetype<int,
|
||||
boost::writable_lvalue_iterator_tag,
|
||||
boost::random_access_traversal_tag> iter;
|
||||
typedef boost::iterator_archetype<
|
||||
int
|
||||
, boost::iterator_archetypes::writable_lvalue_iterator_t
|
||||
, boost::random_access_traversal_tag
|
||||
> iter;
|
||||
|
||||
boost::function_requires< boost_concepts::WritableLvalueIteratorConcept<iter> >();
|
||||
boost::function_requires< boost_concepts::RandomAccessTraversalConcept<iter> >();
|
||||
}
|
||||
return 0; // keep msvc happy
|
||||
|
||||
return 0; // keep msvc happy
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <boost/test/minimal.hpp>
|
||||
|
||||
#include <boost/iterator/permutation_iterator.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
|
||||
#include <vector>
|
||||
#include <list>
|
||||
@@ -23,8 +24,9 @@ void permutation_test()
|
||||
typedef std::list< int > index_type;
|
||||
|
||||
const int element_range_size = 10;
|
||||
const int index_size = 4;
|
||||
const int index_size = 7;
|
||||
|
||||
BOOST_STATIC_ASSERT(index_size <= element_range_size);
|
||||
element_range_type elements( element_range_size );
|
||||
for( element_range_type::iterator el_it = elements.begin(); el_it != elements.end(); ++el_it )
|
||||
{ *el_it = std::distance(elements.begin(), el_it); }
|
||||
@@ -34,57 +36,42 @@ void permutation_test()
|
||||
{ *i_it = element_range_size - index_size + std::distance(indices.begin(), i_it); }
|
||||
std::reverse( indices.begin(), indices.end() );
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
|
||||
typedef boost::permutation_iterator< element_range_type::iterator
|
||||
, index_type::iterator
|
||||
, boost::use_default
|
||||
, boost::use_default
|
||||
, element_range_type::reference > permutation_type;
|
||||
|
||||
permutation_type begin( elements.begin(), indices.begin() );
|
||||
permutation_type it = begin;
|
||||
permutation_type end( elements.begin(), indices.end() );
|
||||
|
||||
#else
|
||||
|
||||
typedef boost::permutation_iterator< element_range_type::iterator, index_type::iterator > permutation_type;
|
||||
permutation_type begin = boost::make_permutation_iterator( elements.begin(), indices.begin() );
|
||||
permutation_type it = begin;
|
||||
permutation_type end = boost::make_permutation_iterator( elements.begin(), indices.end() );
|
||||
|
||||
#endif
|
||||
|
||||
BOOST_CHECK( it == begin );
|
||||
BOOST_CHECK( it != end );
|
||||
|
||||
BOOST_CHECK( std::distance( begin, end ) == index_size );
|
||||
|
||||
for( index_type::iterator i_it = indices.begin(); it != end; ++i_it, ++it )
|
||||
for( index_type::iterator i_it1 = indices.begin(); it != end; ++i_it1, ++it )
|
||||
{
|
||||
BOOST_CHECK( *it == elements[ *i_it ] );
|
||||
BOOST_CHECK( *it == elements[ *i_it1 ] );
|
||||
}
|
||||
|
||||
it = begin;
|
||||
for( int i = 0; i < index_size ; i+=2, it+=2 )
|
||||
for( int i1 = 0; i1 < index_size - 1 ; i1+=2, it+=2 )
|
||||
{
|
||||
index_type::iterator i_it = indices.begin(); std::advance( i_it, i );
|
||||
BOOST_CHECK( *it == elements[ *i_it ] );
|
||||
index_type::iterator i_it2 = indices.begin();
|
||||
std::advance( i_it2, i1 );
|
||||
BOOST_CHECK( *it == elements[ *i_it2 ] );
|
||||
}
|
||||
|
||||
|
||||
it = begin + (index_size);
|
||||
BOOST_CHECK( it != begin );
|
||||
for( index_type::iterator i_it = --indices.end(); it-- != begin; --i_it )
|
||||
for( index_type::iterator i_it3 = indices.end(); it != begin; )
|
||||
{
|
||||
BOOST_CHECK( *it == elements[ *i_it ] );
|
||||
BOOST_CHECK( *--it == elements[ *--i_it3 ] );
|
||||
}
|
||||
|
||||
it = begin + (index_size - 1);
|
||||
for( int i = 0; i < index_size; i+=2, it-=2 )
|
||||
it = begin + index_size;
|
||||
for( int i2 = 0; i2 < index_size - 1; i2+=2, --it )
|
||||
{
|
||||
index_type::iterator i_it = --indices.end(); std::advance( i_it, -i );
|
||||
BOOST_CHECK( *it == elements[ *i_it ] );
|
||||
index_type::iterator i_it4 = --indices.end();
|
||||
std::advance( i_it4, -i2 );
|
||||
BOOST_CHECK( *--it == elements[ *i_it4 ] );
|
||||
}
|
||||
|
||||
}
|
||||
@@ -93,9 +80,5 @@ void permutation_test()
|
||||
int test_main(int, char *[])
|
||||
{
|
||||
permutation_test();
|
||||
|
||||
bool error_on_purpose = false;
|
||||
//BOOST_CHECK( error_on_purpose );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Executable → Regular
+1
-13
@@ -11,19 +11,6 @@
|
||||
|
||||
using boost::dummyT;
|
||||
|
||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
namespace boost
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template<> struct iterator_traits<dummyT*>
|
||||
: ptr_iter_traits<dummyT> {};
|
||||
template<> struct iterator_traits<dummyT const*>
|
||||
: ptr_iter_traits<dummyT const> {};
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Test reverse iterator
|
||||
int main()
|
||||
{
|
||||
@@ -87,6 +74,7 @@ int main()
|
||||
#if defined(__SGI_STL_PORT) \
|
||||
|| !BOOST_WORKAROUND(__GNUC__, <= 2) \
|
||||
&& !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) \
|
||||
&& !BOOST_WORKAROUND(__LIBCOMO_VERSION__, BOOST_TESTED_AT(29)) \
|
||||
&& !BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, <= 1)
|
||||
|
||||
boost::const_nonconst_iterator_test(i, ++j);
|
||||
|
||||
Executable → Regular
+6
-2
@@ -10,13 +10,17 @@
|
||||
|
||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
template <class T, class U>
|
||||
struct static_assert_same;
|
||||
struct static_assert_same_base;
|
||||
|
||||
template <class T>
|
||||
struct static_assert_same<T,T>
|
||||
struct static_assert_same_base<T,T>
|
||||
{
|
||||
enum { value = 1 };
|
||||
};
|
||||
|
||||
template <class T, class U>
|
||||
struct static_assert_same : static_assert_same_base<T,U> {};
|
||||
|
||||
#else
|
||||
# include <boost/mpl/if.hpp>
|
||||
# include <boost/mpl/bool.hpp>
|
||||
|
||||
@@ -27,18 +27,10 @@
|
||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
namespace boost { namespace detail
|
||||
{
|
||||
template<> struct iterator_traits<int*>
|
||||
: ptr_iter_traits<int> {};
|
||||
|
||||
template<> struct iterator_traits<std::pair<int, int>*>
|
||||
: ptr_iter_traits<std::pair<int, int> > {};
|
||||
|
||||
template<> struct iterator_traits<int const*>
|
||||
: ptr_iter_traits<int, int const> {};
|
||||
|
||||
template<> struct iterator_traits<std::pair<int, int> const*>
|
||||
: ptr_iter_traits<std::pair<int, int>, std::pair<int, int> const> {};
|
||||
|
||||
template<> struct function_object_result<int (*)(int)>
|
||||
{
|
||||
typedef int type;
|
||||
};
|
||||
}}
|
||||
#endif
|
||||
|
||||
@@ -192,17 +184,14 @@ main()
|
||||
for (int k2 = 0; k2 < N; ++k2)
|
||||
x[k2] = x[k2] * 2;
|
||||
|
||||
boost::input_iterator_test(boost::make_transform_iterator(y, mult_2)
|
||||
, x[0]
|
||||
, x[1]);
|
||||
boost::input_iterator_test(
|
||||
boost::make_transform_iterator(y, mult_2), x[0], x[1]);
|
||||
|
||||
boost::input_iterator_test(boost::make_transform_iterator(&y[0], mult_2)
|
||||
, x[0]
|
||||
, x[1]);
|
||||
boost::input_iterator_test(
|
||||
boost::make_transform_iterator(&y[0], mult_2), x[0], x[1]);
|
||||
|
||||
boost::random_access_readable_iterator_test(boost::make_transform_iterator(y, mult_2)
|
||||
, N
|
||||
, x);
|
||||
boost::random_access_readable_iterator_test(
|
||||
boost::make_transform_iterator(y, mult_2), N, x);
|
||||
|
||||
}
|
||||
|
||||
@@ -221,25 +210,34 @@ main()
|
||||
|
||||
}
|
||||
|
||||
std::copy(x,
|
||||
x + N,
|
||||
boost::make_transform_iterator((pair_t*)values, select_first()));
|
||||
std::copy(
|
||||
x
|
||||
, x + N
|
||||
, boost::make_transform_iterator((pair_t*)values, select_first())
|
||||
);
|
||||
|
||||
std::copy(y,
|
||||
y + N,
|
||||
boost::make_transform_iterator((pair_t*)values, select_second()));
|
||||
std::copy(
|
||||
y
|
||||
, y + N
|
||||
, boost::make_transform_iterator((pair_t*)values, select_second())
|
||||
);
|
||||
|
||||
boost::random_access_readable_iterator_test(boost::make_transform_iterator((pair_t*)values, value_select_first()),
|
||||
N,
|
||||
x);
|
||||
boost::random_access_readable_iterator_test(
|
||||
boost::make_transform_iterator((pair_t*)values, value_select_first())
|
||||
, N
|
||||
, x
|
||||
);
|
||||
|
||||
boost::random_access_readable_iterator_test(boost::make_transform_iterator((pair_t*)values, const_select_first()),
|
||||
N,
|
||||
x);
|
||||
boost::random_access_readable_iterator_test(
|
||||
boost::make_transform_iterator((pair_t*)values, const_select_first())
|
||||
, N, x
|
||||
);
|
||||
|
||||
boost::constant_lvalue_iterator_test(boost::make_transform_iterator((pair_t*)values, const_select_first()), x[0]);
|
||||
boost::constant_lvalue_iterator_test(
|
||||
boost::make_transform_iterator((pair_t*)values, const_select_first()), x[0]);
|
||||
|
||||
boost::mutable_lvalue_iterator_test(boost::make_transform_iterator((pair_t*)values, select_first()), x[0], 17);
|
||||
boost::non_const_lvalue_iterator_test(
|
||||
boost::make_transform_iterator((pair_t*)values, select_first()), x[0], 17);
|
||||
|
||||
}
|
||||
|
||||
|
||||
Executable → Regular
+29
-21
@@ -5,16 +5,16 @@
|
||||
// to its suitability for any purpose.
|
||||
#include <boost/iterator/iterator_adaptor.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
|
||||
#include "static_assert_same.hpp"
|
||||
|
||||
#include <boost/type_traits/broken_compiler_spec.hpp>
|
||||
|
||||
#include <boost/iterator/detail/minimum_category.hpp>
|
||||
|
||||
struct X { int a; };
|
||||
|
||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
namespace boost { namespace detail {
|
||||
template<> struct iterator_traits<X*>
|
||||
: ptr_iter_traits<X> {};
|
||||
}}
|
||||
#endif
|
||||
BOOST_TT_BROKEN_COMPILER_SPEC(X)
|
||||
|
||||
struct Xiter : boost::iterator_adaptor<Xiter,X*>
|
||||
{
|
||||
@@ -43,29 +43,32 @@ void category_test()
|
||||
using namespace boost::detail;
|
||||
|
||||
BOOST_STATIC_ASSERT((
|
||||
!is_tag<
|
||||
input_output_iterator_tag
|
||||
, std::input_iterator_tag>::value));
|
||||
|
||||
BOOST_STATIC_ASSERT((
|
||||
!is_tag<
|
||||
input_output_iterator_tag
|
||||
, std::output_iterator_tag>::value));
|
||||
|
||||
BOOST_STATIC_ASSERT((
|
||||
is_tag<
|
||||
!boost::is_convertible<
|
||||
std::input_iterator_tag
|
||||
, input_output_iterator_tag>::value));
|
||||
|
||||
BOOST_STATIC_ASSERT((
|
||||
is_tag<
|
||||
!boost::is_convertible<
|
||||
std::output_iterator_tag
|
||||
, input_output_iterator_tag>::value));
|
||||
|
||||
|
||||
BOOST_STATIC_ASSERT((
|
||||
is_tag<
|
||||
boost::is_convertible<
|
||||
input_output_iterator_tag
|
||||
, std::forward_iterator_tag>::value));
|
||||
, std::input_iterator_tag>::value));
|
||||
|
||||
BOOST_STATIC_ASSERT((
|
||||
boost::is_convertible<
|
||||
input_output_iterator_tag
|
||||
, std::output_iterator_tag>::value));
|
||||
|
||||
#if 0 // This seems wrong; we're not advertising
|
||||
// input_output_iterator_tag are we?
|
||||
BOOST_STATIC_ASSERT((
|
||||
boost::is_convertible<
|
||||
std::forward_iterator_tag
|
||||
, input_output_iterator_tag>::value));
|
||||
#endif
|
||||
|
||||
int test = static_assert_min_cat<
|
||||
std::input_iterator_tag,input_output_iterator_tag, std::input_iterator_tag
|
||||
@@ -75,9 +78,11 @@ void category_test()
|
||||
input_output_iterator_tag,std::input_iterator_tag, std::input_iterator_tag
|
||||
>::value;
|
||||
|
||||
#if 0
|
||||
test = static_assert_min_cat<
|
||||
input_output_iterator_tag,std::forward_iterator_tag, input_output_iterator_tag
|
||||
>::value;
|
||||
#endif
|
||||
|
||||
test = static_assert_min_cat<
|
||||
std::input_iterator_tag,std::forward_iterator_tag, std::input_iterator_tag
|
||||
@@ -87,9 +92,12 @@ void category_test()
|
||||
std::input_iterator_tag,std::random_access_iterator_tag, std::input_iterator_tag
|
||||
>::value;
|
||||
|
||||
#if 0 // This would be wrong: a random access iterator is not
|
||||
// neccessarily writable, as is an output iterator.
|
||||
test = static_assert_min_cat<
|
||||
std::output_iterator_tag,std::random_access_iterator_tag, std::output_iterator_tag
|
||||
>::value;
|
||||
#endif
|
||||
|
||||
(void)test;
|
||||
}
|
||||
|
||||
Executable
+910
@@ -0,0 +1,910 @@
|
||||
// (C) Copyright Dave Abrahams and Thomas Becker 2003. 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.
|
||||
//
|
||||
|
||||
// File:
|
||||
// =====
|
||||
// zip_iterator_test_main.cpp
|
||||
|
||||
// Author:
|
||||
// =======
|
||||
// Thomas Becker
|
||||
|
||||
// Created:
|
||||
// ========
|
||||
// Jul 15, 2003
|
||||
|
||||
// Purpose:
|
||||
// ========
|
||||
// Test driver for zip_iterator.hpp
|
||||
|
||||
// Compilers Tested:
|
||||
// =================
|
||||
// Metrowerks Codewarrior Pro 7.2, 8.3
|
||||
// gcc 2.95.3
|
||||
// gcc 3.2
|
||||
// Microsoft VC 6sp5 (test fails due to some compiler bug)
|
||||
// Microsoft VC 7 (works)
|
||||
// Microsoft VC 7.1
|
||||
// Intel 5
|
||||
// Intel 6
|
||||
// Intel 7.1
|
||||
// Intel 8
|
||||
// Borland 5.5.1 (broken due to lack of support from Boost.Tuples)
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Includes
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <boost/iterator/zip_iterator.hpp>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <set>
|
||||
#include <boost/tuple/tuple.hpp>
|
||||
#include <boost/iterator/transform_iterator.hpp>
|
||||
#include <boost/iterator/is_readable_iterator.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
#include <stddef.h>
|
||||
|
||||
template <class It>
|
||||
struct pure_traversal
|
||||
: boost::detail::pure_traversal_tag<
|
||||
typename boost::iterator_traversal<It>::type
|
||||
>
|
||||
{};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Das Main Funktion
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int main( void )
|
||||
{
|
||||
|
||||
std::cout << "\n"
|
||||
<< "***********************************************\n"
|
||||
<< "* *\n"
|
||||
<< "* Test driver for boost::zip_iterator *\n"
|
||||
<< "* Copyright Thomas Becker 2003 *\n"
|
||||
<< "* *\n"
|
||||
<< "***********************************************\n\n"
|
||||
<< std::flush;
|
||||
|
||||
size_t num_successful_tests = 0;
|
||||
size_t num_failed_tests = 0;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Make sure tuples are supported
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::cout << "Basic tuple support: "
|
||||
<< std::flush;
|
||||
|
||||
typedef boost::tuples::tuple<int, double> mytuple;
|
||||
mytuple t1;
|
||||
boost::tuples::get<0>(t1) = 42;
|
||||
boost::tuples::get<1>(t1) = 42.1;
|
||||
|
||||
if( 2 == boost::tuples::length<mytuple>::value &&
|
||||
42 == boost::tuples::get<0>(t1) &&
|
||||
42.1 == boost::tuples::get<1>(t1)
|
||||
)
|
||||
{
|
||||
++num_successful_tests;
|
||||
std::cout << "OK" << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
++num_failed_tests = 0;
|
||||
std::cout << "not OK" << std::endl;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Make sure iterator adaptor is supported
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::cout << "Basic iterator adaptor support: "
|
||||
<< std::flush;
|
||||
|
||||
std::set<int> s;
|
||||
s.insert(42);
|
||||
s.insert(43);
|
||||
s.insert(44);
|
||||
|
||||
typedef boost::transform_iterator<
|
||||
std::binder1st<std::plus<int> >,
|
||||
std::set<int>::iterator
|
||||
>
|
||||
add_seven_iterator;
|
||||
|
||||
typedef boost::transform_iterator<
|
||||
std::binder1st<std::plus<int> >,
|
||||
std::set<int>::const_iterator
|
||||
>
|
||||
const_add_seven_iterator;
|
||||
|
||||
add_seven_iterator set_run(s.begin(), std::bind1st(std::plus<int>(), 7));
|
||||
add_seven_iterator set_end(s.end(), std::bind1st(std::plus<int>(), 7));
|
||||
|
||||
const_add_seven_iterator const_set_run(s.begin(), std::bind1st(std::plus<int>(), 7));
|
||||
// set_run = const_set_run; // Error: can't convert from const to non-const
|
||||
const_set_run = set_run;
|
||||
|
||||
if( 49 == *set_run &&
|
||||
50 == *++set_run &&
|
||||
51 == *++set_run &&
|
||||
set_end == ++set_run &&
|
||||
49 == *const_set_run &&
|
||||
50 == *++const_set_run &&
|
||||
51 == *++const_set_run &&
|
||||
set_end == ++const_set_run
|
||||
)
|
||||
{
|
||||
++num_successful_tests;
|
||||
std::cout << "OK" << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
++num_failed_tests = 0;
|
||||
std::cout << "not OK" << std::endl;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Zip iterator construction and dereferencing
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::cout << "Zip iterator construction and dereferencing: "
|
||||
<< std::flush;
|
||||
|
||||
std::vector<double> vect1(3);
|
||||
vect1[0] = 42.;
|
||||
vect1[1] = 43.;
|
||||
vect1[2] = 44.;
|
||||
|
||||
std::set<int> intset;
|
||||
intset.insert(52);
|
||||
intset.insert(53);
|
||||
intset.insert(54);
|
||||
//
|
||||
|
||||
boost::zip_iterator<
|
||||
boost::tuples::tuple<
|
||||
std::set<int>::iterator
|
||||
, std::vector<double>::iterator
|
||||
>
|
||||
>
|
||||
zip_it_mixed(
|
||||
boost::make_tuple(
|
||||
intset.begin()
|
||||
, vect1.begin()
|
||||
)
|
||||
);
|
||||
|
||||
boost::tuples::tuple<int, double> val_tuple(
|
||||
*zip_it_mixed);
|
||||
|
||||
boost::tuples::tuple<const int&, double&> ref_tuple(
|
||||
*zip_it_mixed);
|
||||
|
||||
double dblOldVal = boost::tuples::get<1>(ref_tuple);
|
||||
boost::tuples::get<1>(ref_tuple) -= 41.;
|
||||
|
||||
if( 52 == boost::tuples::get<0>(val_tuple) &&
|
||||
42. == boost::tuples::get<1>(val_tuple) &&
|
||||
52 == boost::tuples::get<0>(ref_tuple) &&
|
||||
1. == boost::tuples::get<1>(ref_tuple) &&
|
||||
1. == *vect1.begin()
|
||||
)
|
||||
{
|
||||
++num_successful_tests;
|
||||
std::cout << "OK" << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
++num_failed_tests = 0;
|
||||
std::cout << "not OK" << std::endl;
|
||||
}
|
||||
|
||||
// Undo change to vect1
|
||||
boost::tuples::get<1>(ref_tuple) = dblOldVal;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Zip iterator with 12 components
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::cout << "Zip iterators with 12 components: "
|
||||
<< std::flush;
|
||||
|
||||
// Declare 12 containers
|
||||
//
|
||||
std::list<int> li1;
|
||||
li1.push_back(1);
|
||||
std::set<int> se1;
|
||||
se1.insert(2);
|
||||
std::vector<int> ve1;
|
||||
ve1.push_back(3);
|
||||
//
|
||||
std::list<int> li2;
|
||||
li2.push_back(4);
|
||||
std::set<int> se2;
|
||||
se2.insert(5);
|
||||
std::vector<int> ve2;
|
||||
ve2.push_back(6);
|
||||
//
|
||||
std::list<int> li3;
|
||||
li3.push_back(7);
|
||||
std::set<int> se3;
|
||||
se3.insert(8);
|
||||
std::vector<int> ve3;
|
||||
ve3.push_back(9);
|
||||
//
|
||||
std::list<int> li4;
|
||||
li4.push_back(10);
|
||||
std::set<int> se4;
|
||||
se4.insert(11);
|
||||
std::vector<int> ve4;
|
||||
ve4.push_back(12);
|
||||
|
||||
// typedefs for cons lists of iterators.
|
||||
typedef boost::tuples::cons<
|
||||
std::set<int>::iterator,
|
||||
boost::tuples::tuple<
|
||||
std::vector<int>::iterator,
|
||||
std::list<int>::iterator,
|
||||
std::set<int>::iterator,
|
||||
std::vector<int>::iterator,
|
||||
std::list<int>::iterator,
|
||||
std::set<int>::iterator,
|
||||
std::vector<int>::iterator,
|
||||
std::list<int>::iterator,
|
||||
std::set<int>::iterator,
|
||||
std::vector<int>::const_iterator
|
||||
>::inherited
|
||||
> cons_11_its_type;
|
||||
//
|
||||
typedef boost::tuples::cons<
|
||||
std::list<int>::const_iterator,
|
||||
cons_11_its_type
|
||||
> cons_12_its_type;
|
||||
|
||||
// typedefs for cons lists for dereferencing the zip iterator
|
||||
// made from the cons list above.
|
||||
typedef boost::tuples::cons<
|
||||
const int&,
|
||||
boost::tuples::tuple<
|
||||
int&,
|
||||
int&,
|
||||
const int&,
|
||||
int&,
|
||||
int&,
|
||||
const int&,
|
||||
int&,
|
||||
int&,
|
||||
const int&,
|
||||
const int&
|
||||
>::inherited
|
||||
> cons_11_refs_type;
|
||||
//
|
||||
typedef boost::tuples::cons<
|
||||
const int&,
|
||||
cons_11_refs_type
|
||||
> cons_12_refs_type;
|
||||
|
||||
// typedef for zip iterator with 12 elements
|
||||
typedef boost::zip_iterator<cons_12_its_type> zip_it_12_type;
|
||||
|
||||
// Declare a 12-element zip iterator.
|
||||
zip_it_12_type zip_it_12(
|
||||
cons_12_its_type(
|
||||
li1.begin(),
|
||||
cons_11_its_type(
|
||||
se1.begin(),
|
||||
boost::make_tuple(
|
||||
ve1.begin(),
|
||||
li2.begin(),
|
||||
se2.begin(),
|
||||
ve2.begin(),
|
||||
li3.begin(),
|
||||
se3.begin(),
|
||||
ve3.begin(),
|
||||
li4.begin(),
|
||||
se4.begin(),
|
||||
ve4.begin()
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
// Dereference, mess with the result a little.
|
||||
cons_12_refs_type zip_it_12_dereferenced(*zip_it_12);
|
||||
boost::tuples::get<9>(zip_it_12_dereferenced) = 42;
|
||||
|
||||
// Make a copy and move it a little to force some instantiations.
|
||||
zip_it_12_type zip_it_12_copy(zip_it_12);
|
||||
++zip_it_12_copy;
|
||||
|
||||
if( boost::tuples::get<11>(zip_it_12.get_iterator_tuple()) == ve4.begin() &&
|
||||
boost::tuples::get<11>(zip_it_12_copy.get_iterator_tuple()) == ve4.end() &&
|
||||
1 == boost::tuples::get<0>(zip_it_12_dereferenced) &&
|
||||
12 == boost::tuples::get<11>(zip_it_12_dereferenced) &&
|
||||
42 == *(li4.begin())
|
||||
)
|
||||
{
|
||||
++num_successful_tests;
|
||||
std::cout << "OK" << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
++num_failed_tests = 0;
|
||||
std::cout << "not OK" << std::endl;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Zip iterator incrementing and dereferencing
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::cout << "Zip iterator ++ and *: "
|
||||
<< std::flush;
|
||||
|
||||
std::vector<double> vect2(3);
|
||||
vect2[0] = 2.2;
|
||||
vect2[1] = 3.3;
|
||||
vect2[2] = 4.4;
|
||||
|
||||
boost::zip_iterator<
|
||||
boost::tuples::tuple<
|
||||
std::vector<double>::const_iterator,
|
||||
std::vector<double>::const_iterator
|
||||
>
|
||||
>
|
||||
zip_it_begin(
|
||||
boost::make_tuple(
|
||||
vect1.begin(),
|
||||
vect2.begin()
|
||||
)
|
||||
);
|
||||
|
||||
boost::zip_iterator<
|
||||
boost::tuples::tuple<
|
||||
std::vector<double>::const_iterator,
|
||||
std::vector<double>::const_iterator
|
||||
>
|
||||
>
|
||||
zip_it_run(
|
||||
boost::make_tuple(
|
||||
vect1.begin(),
|
||||
vect2.begin()
|
||||
)
|
||||
);
|
||||
|
||||
boost::zip_iterator<
|
||||
boost::tuples::tuple<
|
||||
std::vector<double>::const_iterator,
|
||||
std::vector<double>::const_iterator
|
||||
>
|
||||
>
|
||||
zip_it_end(
|
||||
boost::make_tuple(
|
||||
vect1.end(),
|
||||
vect2.end()
|
||||
)
|
||||
);
|
||||
|
||||
if( zip_it_run == zip_it_begin &&
|
||||
42. == boost::tuples::get<0>(*zip_it_run) &&
|
||||
2.2 == boost::tuples::get<1>(*zip_it_run) &&
|
||||
43. == boost::tuples::get<0>(*(++zip_it_run)) &&
|
||||
3.3 == boost::tuples::get<1>(*zip_it_run) &&
|
||||
44. == boost::tuples::get<0>(*(++zip_it_run)) &&
|
||||
4.4 == boost::tuples::get<1>(*zip_it_run) &&
|
||||
zip_it_end == ++zip_it_run
|
||||
)
|
||||
{
|
||||
++num_successful_tests;
|
||||
std::cout << "OK" << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
++num_failed_tests = 0;
|
||||
std::cout << "not OK" << std::endl;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Zip iterator decrementing and dereferencing
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::cout << "Zip iterator -- and *: "
|
||||
<< std::flush;
|
||||
|
||||
if( zip_it_run == zip_it_end &&
|
||||
zip_it_end == zip_it_run-- &&
|
||||
44. == boost::tuples::get<0>(*zip_it_run) &&
|
||||
4.4 == boost::tuples::get<1>(*zip_it_run) &&
|
||||
43. == boost::tuples::get<0>(*(--zip_it_run)) &&
|
||||
3.3 == boost::tuples::get<1>(*zip_it_run) &&
|
||||
42. == boost::tuples::get<0>(*(--zip_it_run)) &&
|
||||
2.2 == boost::tuples::get<1>(*zip_it_run) &&
|
||||
zip_it_begin == zip_it_run
|
||||
)
|
||||
{
|
||||
++num_successful_tests;
|
||||
std::cout << "OK" << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
++num_failed_tests = 0;
|
||||
std::cout << "not OK" << std::endl;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Zip iterator copy construction and equality
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::cout << "Zip iterator copy construction and equality: "
|
||||
<< std::flush;
|
||||
|
||||
boost::zip_iterator<
|
||||
boost::tuples::tuple<
|
||||
std::vector<double>::const_iterator,
|
||||
std::vector<double>::const_iterator
|
||||
>
|
||||
> zip_it_run_copy(zip_it_run);
|
||||
|
||||
if(zip_it_run == zip_it_run && zip_it_run == zip_it_run_copy)
|
||||
{
|
||||
++num_successful_tests;
|
||||
std::cout << "OK" << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
++num_failed_tests = 0;
|
||||
std::cout << "not OK" << std::endl;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Zip iterator inequality
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::cout << "Zip iterator inequality: "
|
||||
<< std::flush;
|
||||
|
||||
if(!(zip_it_run != zip_it_run_copy) && zip_it_run != ++zip_it_run_copy)
|
||||
{
|
||||
++num_successful_tests;
|
||||
std::cout << "OK" << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
++num_failed_tests = 0;
|
||||
std::cout << "not OK" << std::endl;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Zip iterator less than
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::cout << "Zip iterator less than: "
|
||||
<< std::flush;
|
||||
|
||||
// Note: zip_it_run_copy == zip_it_run + 1
|
||||
//
|
||||
if( zip_it_run < zip_it_run_copy &&
|
||||
!( zip_it_run < --zip_it_run_copy) &&
|
||||
zip_it_run == zip_it_run_copy
|
||||
)
|
||||
{
|
||||
++num_successful_tests;
|
||||
std::cout << "OK" << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
++num_failed_tests = 0;
|
||||
std::cout << "not OK" << std::endl;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Zip iterator less than or equal
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::cout << "zip iterator less than or equal: "
|
||||
<< std::flush;
|
||||
|
||||
// Note: zip_it_run_copy == zip_it_run
|
||||
//
|
||||
++zip_it_run;
|
||||
zip_it_run_copy += 2;
|
||||
|
||||
if( zip_it_run <= zip_it_run_copy &&
|
||||
zip_it_run <= --zip_it_run_copy &&
|
||||
!( zip_it_run <= --zip_it_run_copy) &&
|
||||
zip_it_run <= zip_it_run
|
||||
)
|
||||
{
|
||||
++num_successful_tests;
|
||||
std::cout << "OK" << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
++num_failed_tests = 0;
|
||||
std::cout << "not OK" << std::endl;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Zip iterator greater than
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::cout << "Zip iterator greater than: "
|
||||
<< std::flush;
|
||||
|
||||
// Note: zip_it_run_copy == zip_it_run - 1
|
||||
//
|
||||
if( zip_it_run > zip_it_run_copy &&
|
||||
!( zip_it_run > ++zip_it_run_copy) &&
|
||||
zip_it_run == zip_it_run_copy
|
||||
)
|
||||
{
|
||||
++num_successful_tests;
|
||||
std::cout << "OK" << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
++num_failed_tests = 0;
|
||||
std::cout << "not OK" << std::endl;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Zip iterator greater than or equal
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::cout << "Zip iterator greater than or equal: "
|
||||
<< std::flush;
|
||||
|
||||
++zip_it_run;
|
||||
|
||||
// Note: zip_it_run == zip_it_run_copy + 1
|
||||
//
|
||||
if( zip_it_run >= zip_it_run_copy &&
|
||||
--zip_it_run >= zip_it_run_copy &&
|
||||
! (zip_it_run >= ++zip_it_run_copy)
|
||||
)
|
||||
{
|
||||
++num_successful_tests;
|
||||
std::cout << "OK" << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
++num_failed_tests = 0;
|
||||
std::cout << "not OK" << std::endl;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Zip iterator + int
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::cout << "Zip iterator + int: "
|
||||
<< std::flush;
|
||||
|
||||
// Note: zip_it_run == zip_it_run_copy - 1
|
||||
//
|
||||
zip_it_run = zip_it_run + 2;
|
||||
++zip_it_run_copy;
|
||||
|
||||
if( zip_it_run == zip_it_run_copy && zip_it_run == zip_it_begin + 3 )
|
||||
{
|
||||
++num_successful_tests;
|
||||
std::cout << "OK" << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
++num_failed_tests = 0;
|
||||
std::cout << "not OK" << std::endl;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Zip iterator - int
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::cout << "Zip iterator - int: "
|
||||
<< std::flush;
|
||||
|
||||
// Note: zip_it_run == zip_it_run_copy, and both are at end position
|
||||
//
|
||||
zip_it_run = zip_it_run - 2;
|
||||
--zip_it_run_copy;
|
||||
--zip_it_run_copy;
|
||||
|
||||
if( zip_it_run == zip_it_run_copy && (zip_it_run - 1) == zip_it_begin )
|
||||
{
|
||||
++num_successful_tests;
|
||||
std::cout << "OK" << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
++num_failed_tests = 0;
|
||||
std::cout << "not OK" << std::endl;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Zip iterator +=
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::cout << "Zip iterator +=: "
|
||||
<< std::flush;
|
||||
|
||||
// Note: zip_it_run == zip_it_run_copy, and both are at begin + 1
|
||||
//
|
||||
zip_it_run += 2;
|
||||
if( zip_it_run == zip_it_begin + 3 )
|
||||
{
|
||||
++num_successful_tests;
|
||||
std::cout << "OK" << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
++num_failed_tests = 0;
|
||||
std::cout << "not OK" << std::endl;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Zip iterator -=
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::cout << "Zip iterator -=: "
|
||||
<< std::flush;
|
||||
|
||||
// Note: zip_it_run is at end position, zip_it_run_copy is at
|
||||
// begin plus one.
|
||||
//
|
||||
zip_it_run -= 2;
|
||||
if( zip_it_run == zip_it_run_copy )
|
||||
{
|
||||
++num_successful_tests;
|
||||
std::cout << "OK" << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
++num_failed_tests = 0;
|
||||
std::cout << "not OK" << std::endl;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Zip iterator getting member iterators
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::cout << "Zip iterator member iterators: "
|
||||
<< std::flush;
|
||||
|
||||
// Note: zip_it_run and zip_it_run_copy are both at
|
||||
// begin plus one.
|
||||
//
|
||||
if( boost::tuples::get<0>(zip_it_run.get_iterator_tuple()) == vect1.begin() + 1 &&
|
||||
boost::tuples::get<1>(zip_it_run.get_iterator_tuple()) == vect2.begin() + 1
|
||||
)
|
||||
{
|
||||
++num_successful_tests;
|
||||
std::cout << "OK" << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
++num_failed_tests = 0;
|
||||
std::cout << "not OK" << std::endl;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Making zip iterators
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::cout << "Making zip iterators: "
|
||||
<< std::flush;
|
||||
|
||||
std::vector<boost::tuples::tuple<double, double> >
|
||||
vect_of_tuples(3);
|
||||
|
||||
std::copy(
|
||||
boost::make_zip_iterator(
|
||||
boost::make_tuple(
|
||||
vect1.begin(),
|
||||
vect2.begin()
|
||||
)
|
||||
),
|
||||
boost::make_zip_iterator(
|
||||
boost::make_tuple(
|
||||
vect1.end(),
|
||||
vect2.end()
|
||||
)
|
||||
),
|
||||
vect_of_tuples.begin()
|
||||
);
|
||||
|
||||
if( 42. == boost::tuples::get<0>(*vect_of_tuples.begin()) &&
|
||||
2.2 == boost::tuples::get<1>(*vect_of_tuples.begin()) &&
|
||||
43. == boost::tuples::get<0>(*(vect_of_tuples.begin() + 1)) &&
|
||||
3.3 == boost::tuples::get<1>(*(vect_of_tuples.begin() + 1)) &&
|
||||
44. == boost::tuples::get<0>(*(vect_of_tuples.begin() + 2)) &&
|
||||
4.4 == boost::tuples::get<1>(*(vect_of_tuples.begin() + 2))
|
||||
)
|
||||
{
|
||||
++num_successful_tests;
|
||||
std::cout << "OK" << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
++num_failed_tests = 0;
|
||||
std::cout << "not OK" << std::endl;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Zip iterator non-const --> const conversion
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::cout << "Zip iterator non-const to const conversion: "
|
||||
<< std::flush;
|
||||
|
||||
boost::zip_iterator<
|
||||
boost::tuples::tuple<
|
||||
std::set<int>::const_iterator,
|
||||
std::vector<double>::const_iterator
|
||||
>
|
||||
>
|
||||
zip_it_const(
|
||||
boost::make_tuple(
|
||||
intset.begin(),
|
||||
vect2.begin()
|
||||
)
|
||||
);
|
||||
//
|
||||
boost::zip_iterator<
|
||||
boost::tuples::tuple<
|
||||
std::set<int>::iterator,
|
||||
std::vector<double>::const_iterator
|
||||
>
|
||||
>
|
||||
zip_it_half_const(
|
||||
boost::make_tuple(
|
||||
intset.begin(),
|
||||
vect2.begin()
|
||||
)
|
||||
);
|
||||
//
|
||||
boost::zip_iterator<
|
||||
boost::tuples::tuple<
|
||||
std::set<int>::iterator,
|
||||
std::vector<double>::iterator
|
||||
>
|
||||
>
|
||||
zip_it_non_const(
|
||||
boost::make_tuple(
|
||||
intset.begin(),
|
||||
vect2.begin()
|
||||
)
|
||||
);
|
||||
|
||||
zip_it_half_const = ++zip_it_non_const;
|
||||
zip_it_const = zip_it_half_const;
|
||||
++zip_it_const;
|
||||
// zip_it_non_const = ++zip_it_const; // Error: can't convert from const to non-const
|
||||
|
||||
if( 54 == boost::tuples::get<0>(*zip_it_const) &&
|
||||
4.4 == boost::tuples::get<1>(*zip_it_const) &&
|
||||
53 == boost::tuples::get<0>(*zip_it_half_const) &&
|
||||
3.3 == boost::tuples::get<1>(*zip_it_half_const)
|
||||
)
|
||||
{
|
||||
++num_successful_tests;
|
||||
std::cout << "OK" << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
++num_failed_tests = 0;
|
||||
std::cout << "not OK" << std::endl;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Zip iterator categories
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::cout << "Zip iterator categories: "
|
||||
<< std::flush;
|
||||
|
||||
// The big iterator of the previous test has vector, list, and set iterators.
|
||||
// Therefore, it must be bidirectional, but not random access.
|
||||
bool bBigItIsBidirectionalIterator = boost::is_convertible<
|
||||
boost::iterator_traversal<zip_it_12_type>::type
|
||||
, boost::bidirectional_traversal_tag
|
||||
>::value;
|
||||
|
||||
bool bBigItIsRandomAccessIterator = boost::is_convertible<
|
||||
boost::iterator_traversal<zip_it_12_type>::type
|
||||
, boost::random_access_traversal_tag
|
||||
>::value;
|
||||
|
||||
// A combining iterator with all vector iterators must have random access
|
||||
// traversal.
|
||||
//
|
||||
typedef boost::zip_iterator<
|
||||
boost::tuples::tuple<
|
||||
std::vector<double>::const_iterator,
|
||||
std::vector<double>::const_iterator
|
||||
>
|
||||
> all_vects_type;
|
||||
|
||||
bool bAllVectsIsRandomAccessIterator = boost::is_convertible<
|
||||
boost::iterator_traversal<all_vects_type>::type
|
||||
, boost::random_access_traversal_tag
|
||||
>::value;
|
||||
|
||||
// The big test.
|
||||
if( bBigItIsBidirectionalIterator &&
|
||||
! bBigItIsRandomAccessIterator &&
|
||||
bAllVectsIsRandomAccessIterator
|
||||
)
|
||||
{
|
||||
++num_successful_tests;
|
||||
std::cout << "OK" << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
++num_failed_tests = 0;
|
||||
std::cout << "not OK" << std::endl;
|
||||
}
|
||||
|
||||
// Done
|
||||
//
|
||||
std::cout << "\nTest Result:"
|
||||
<< "\n============"
|
||||
<< "\nNumber of successful tests: " << static_cast<unsigned int>(num_successful_tests)
|
||||
<< "\nNumber of failed tests: " << static_cast<unsigned int>(num_failed_tests)
|
||||
<< std::endl;
|
||||
|
||||
return num_failed_tests;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user