forked from boostorg/utility
Compare commits
111 Commits
svn-branch
...
svn-branch
Author | SHA1 | Date | |
---|---|---|---|
7c9c9c9a1c | |||
b0b821c0d1 | |||
aff985a563 | |||
db425222d5 | |||
e20af510f7 | |||
d8230c6a73 | |||
f5690787bf | |||
a4fd7b32dd | |||
f4336ec693 | |||
03d906976b | |||
4ba6a96822 | |||
1ea4140d56 | |||
351d4ecb15 | |||
7fbf84dcc6 | |||
3ff49b272d | |||
5b52e3d418 | |||
8c0eb498d3 | |||
48a81ef7ea | |||
f7610c9b26 | |||
1755eaf019 | |||
6b8b218efb | |||
333d79b345 | |||
f0fa436fe4 | |||
13e6d78fa8 | |||
7126ea2685 | |||
a37518cb4a | |||
64b3e8c3bd | |||
339937380e | |||
6156f0d302 | |||
00560e8e17 | |||
029ff9828f | |||
ec188c7c3e | |||
0a0296a5d0 | |||
6e26a5bbe7 | |||
dc1b6246a0 | |||
15f69eaf14 | |||
4774a0d325 | |||
be78ab72c9 | |||
0bc4a1b20d | |||
c8b674d105 | |||
b421d4725a | |||
1662bb5713 | |||
ad79a21abd | |||
19645a52e6 | |||
74c3077c9a | |||
1f29191329 | |||
4b636a7680 | |||
e6fc2555f3 | |||
e27d0fcf2a | |||
2643c33b20 | |||
71af1e77c8 | |||
99e7406bd9 | |||
413265f497 | |||
fe44cdf09b | |||
e413428d71 | |||
88b9822db7 | |||
24045c0cd7 | |||
d2aa9f4a84 | |||
d2a5fd169f | |||
4e350d9934 | |||
f3f697bbc8 | |||
c7c09696db | |||
dbcc58d984 | |||
8231310c4d | |||
2988140430 | |||
7387966005 | |||
e0a5a61375 | |||
66ecd70689 | |||
67f4f45653 | |||
1bf28b3de2 | |||
eb3c3435d7 | |||
8a81d8b16c | |||
bc9d8b13d0 | |||
4768b167ab | |||
591ff70ed1 | |||
7bf2ad0b22 | |||
409c79b2e4 | |||
d0410691a1 | |||
64e5115138 | |||
7ae912d83c | |||
2937f5876c | |||
8619c9b5c3 | |||
e4d5684f6b | |||
3d69cf95da | |||
18944572b7 | |||
3e9d0f80c2 | |||
a2c4d1990a | |||
404261c6ee | |||
87abc59612 | |||
cb98ddf7db | |||
7d2e6c9025 | |||
75eaa14a18 | |||
082d6e3b32 | |||
35b3770b6f | |||
5b9d20c7e2 | |||
5bbed2372e | |||
a9d407d239 | |||
3ca4a33a65 | |||
95197f427c | |||
84cdfb032c | |||
ec2ceb9c96 | |||
6286c893fd | |||
354aef0e8c | |||
139e33c36d | |||
e01de59cdd | |||
686f822dea | |||
9961d5c9af | |||
628be0d125 | |||
633e45f61a | |||
2f357c3805 | |||
cda0894d0d |
648
Collection.html
Normal file
648
Collection.html
Normal file
@ -0,0 +1,648 @@
|
||||
<HTML>
|
||||
<!--
|
||||
-- Copyright (c) Jeremy Siek 2000
|
||||
--
|
||||
-- Permission to use, copy, modify, distribute and sell this software
|
||||
-- and its documentation for any purpose is hereby granted without fee,
|
||||
-- provided that the above copyright notice appears in all copies and
|
||||
-- that both that copyright notice and this permission notice appear
|
||||
-- in supporting documentation. Silicon Graphics makes no
|
||||
-- representations about the suitability of this software for any
|
||||
-- purpose. It is provided "as is" without express or implied warranty.
|
||||
-->
|
||||
<Head>
|
||||
<Title>Collection</Title>
|
||||
</HEAD>
|
||||
|
||||
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"
|
||||
ALINK="#ff0000">
|
||||
<h1>
|
||||
<img src="../../c++boost.gif" alt="boost logo"
|
||||
width="277" align="middle" height="86">
|
||||
<br>Collection
|
||||
</h1>
|
||||
|
||||
<h3>Description</h3>
|
||||
|
||||
A Collection is a <i>concept</i> similar to the STL <a
|
||||
href="http://www.sgi.com/tech/stl/Container.html">Container</a>
|
||||
concept. A Collection provides iterators for accessing a range of
|
||||
elements and provides information about the number of elements in the
|
||||
Collection. However, a Collection has fewer requirements than a
|
||||
Container. The motivation for the Collection concept is that there are
|
||||
many useful Container-like types that do not meet the full
|
||||
requirements of Container, and many algorithms that can be written
|
||||
with this reduced set of requirements. To summarize the reduction
|
||||
in requirements:
|
||||
|
||||
<UL>
|
||||
<LI>It is not required to "own" its elements: the lifetime
|
||||
of an element in a Collection does not have to match the lifetime of
|
||||
the Collection object, though the lifetime of the element should cover
|
||||
the lifetime of the Collection object.
|
||||
<LI>The semantics of copying a Collection object is not defined (it
|
||||
could be a deep or shallow copy or not even support copying).
|
||||
<LI>The associated reference type of a Collection does
|
||||
not have to be a real C++ reference.
|
||||
</UL>
|
||||
|
||||
|
||||
Because of the reduced requirements, some care must be taken when
|
||||
writing code that is meant to be generic for all Collection types.
|
||||
In particular, a Collection object should be passed by-reference
|
||||
since assumptions can not be made about the behaviour of the
|
||||
copy constructor.
|
||||
|
||||
<p>
|
||||
|
||||
<h3>Associated types</h3>
|
||||
|
||||
<Table border>
|
||||
<TR>
|
||||
<TD VAlign=top>
|
||||
Value type
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<tt>X::value_type</tt>
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
The type of the object stored in a Collection.
|
||||
If the Collection is <i>mutable</i> then
|
||||
the value type must be <A
|
||||
href="http://www.sgi.com/tech/stl/Assignable.html">Assignable</A>.
|
||||
Otherwise the value type must be <a href="./CopyConstructible.html">CopyConstructible</a>.
|
||||
</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD VAlign=top>
|
||||
Iterator type
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<tt>X::iterator</tt>
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
The type of iterator used to iterate through a Collection's
|
||||
elements. The iterator's value type is expected to be the
|
||||
Collection's value type. A conversion
|
||||
from the iterator type to the const iterator type must exist.
|
||||
The iterator type must be an <A href="http://www.sgi.com/tech/stl/InputIterator.html">InputIterator</A>.
|
||||
</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD VAlign=top>
|
||||
Const iterator type
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<tt>X::const_iterator</tt>
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
A type of iterator that may be used to examine, but not to modify,
|
||||
a Collection's elements.
|
||||
</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD VAlign=top>
|
||||
Reference type
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<tt>X::reference</tt>
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
A type that behaves like a reference to the Collection's value type.
|
||||
<a href="#1">[1]</a>
|
||||
</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD VAlign=top>
|
||||
Const reference type
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<tt>X::const_reference</tt>
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
A type that behaves like a const reference to the Collection's value type.
|
||||
</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD VAlign=top>
|
||||
Pointer type
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<tt>X::pointer</tt>
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
A type that behaves as a pointer to the Collection's value type.
|
||||
</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD VAlign=top>
|
||||
Distance type
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<tt>X::difference_type</tt>
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
A signed integral type used to represent the distance between two
|
||||
of the Collection's iterators. This type must be the same as
|
||||
the iterator's distance type.
|
||||
</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD VAlign=top>
|
||||
Size type
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<tt>X::size_type</tt>
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
An unsigned integral type that can represent any nonnegative value
|
||||
of the Collection's distance type.
|
||||
</TD>
|
||||
</tr>
|
||||
</table>
|
||||
<h3>Notation</h3>
|
||||
<Table>
|
||||
<TR>
|
||||
<TD VAlign=top>
|
||||
<tt>X</tt>
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
A type that is a model of Collection.
|
||||
</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD VAlign=top>
|
||||
<tt>a</tt>, <tt>b</tt>
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
Object of type <tt>X</tt>.
|
||||
</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD VAlign=top>
|
||||
<tt>T</tt>
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
The value type of <tt>X</tt>.
|
||||
</TD>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h3>Valid expressions</h3>
|
||||
|
||||
The following expressions must be valid.
|
||||
<p>
|
||||
|
||||
<Table border>
|
||||
<TR>
|
||||
<TH>
|
||||
Name
|
||||
</TH>
|
||||
<TH>
|
||||
Expression
|
||||
</TH>
|
||||
<TH>
|
||||
Return type
|
||||
</TH>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD VAlign=top>
|
||||
Beginning of range
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<tt>a.begin()</tt>
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<tt>iterator</tt> if <tt>a</tt> is mutable, <tt>const_iterator</tt> otherwise
|
||||
</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD VAlign=top>
|
||||
End of range
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<tt>a.end()</tt>
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<tt>iterator</tt> if <tt>a</tt> is mutable, <tt>const_iterator</tt> otherwise
|
||||
</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD VAlign=top>
|
||||
Size
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<tt>a.size()</tt>
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<tt>size_type</tt>
|
||||
</TD>
|
||||
</TR>
|
||||
<!--
|
||||
<TR>
|
||||
<TD VAlign=top>
|
||||
Maximum size
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<tt>a.max_size()</tt>
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<tt>size_type</tt>
|
||||
</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
-->
|
||||
<TD VAlign=top>
|
||||
Empty Collection
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<tt>a.empty()</tt>
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
Convertible to <tt>bool</tt>
|
||||
</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD VAlign=top>
|
||||
Swap
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<tt>a.swap(b)</tt>
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<tt>void</tt>
|
||||
</TD>
|
||||
</tr>
|
||||
</table>
|
||||
<h3>Expression semantics</h3>
|
||||
|
||||
<Table border>
|
||||
<TR>
|
||||
<TH>
|
||||
Name
|
||||
</TH>
|
||||
<TH>
|
||||
Expression
|
||||
</TH>
|
||||
<TH>
|
||||
Semantics
|
||||
</TH>
|
||||
<TH>
|
||||
Postcondition
|
||||
</TH>
|
||||
</TR>
|
||||
<TD VAlign=top>
|
||||
<TR>
|
||||
<TD VAlign=top>
|
||||
Beginning of range
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<tt>a.begin()</tt>
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
Returns an iterator pointing to the first element in the Collection.
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<tt>a.begin()</tt> is either dereferenceable or past-the-end. It is
|
||||
past-the-end if and only if <tt>a.size() == 0</tt>.
|
||||
</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD VAlign=top>
|
||||
End of range
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<tt>a.end()</tt>
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
Returns an iterator pointing one past the last element in the
|
||||
Collection.
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<tt>a.end()</tt> is past-the-end.
|
||||
</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD VAlign=top>
|
||||
Size
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<tt>a.size()</tt>
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
Returns the size of the Collection, that is, its number of elements.
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<tt>a.size() >= 0
|
||||
</TD>
|
||||
</TR>
|
||||
<!--
|
||||
<TR>
|
||||
<TD VAlign=top>
|
||||
Maximum size
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<tt>a.max_size()</tt>
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
Returns the largest size that this Collection can ever have. <A href="#8">[8]</A>
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<tt>a.max_size() >= 0 && a.max_size() >= a.size()</tt>
|
||||
</TD>
|
||||
</TR>
|
||||
-->
|
||||
<TR>
|
||||
<TD VAlign=top>
|
||||
Empty Collection
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<tt>a.empty()</tt>
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
Equivalent to <tt>a.size() == 0</tt>. (But possibly faster.)
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
|
||||
</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD VAlign=top>
|
||||
Swap
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<tt>a.swap(b)</tt>
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
Equivalent to <tt>swap(a,b)</tt>
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
|
||||
</TD>
|
||||
</tr>
|
||||
</table>
|
||||
<h3>Complexity guarantees</h3>
|
||||
|
||||
<tt>begin()</tt> and <tt>end()</tt> are amortized constant time.
|
||||
<P>
|
||||
<tt>size()</tt> is at most linear in the Collection's
|
||||
size. <tt>empty()</tt> is amortized constant time.
|
||||
<P>
|
||||
<tt>swap()</tt> is at most linear in the size of the two collections.
|
||||
<h3>Invariants</h3>
|
||||
<Table border>
|
||||
<TR>
|
||||
<TD VAlign=top>
|
||||
Valid range
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
For any Collection <tt>a</tt>, <tt>[a.begin(), a.end())</tt> is a valid
|
||||
range.
|
||||
</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD VAlign=top>
|
||||
Range size
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<tt>a.size()</tt> is equal to the distance from <tt>a.begin()</tt> to <tt>a.end()</tt>.
|
||||
</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD VAlign=top>
|
||||
Completeness
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
An algorithm that iterates through the range <tt>[a.begin(), a.end())</tt>
|
||||
will pass through every element of <tt>a</tt>.
|
||||
</TD>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
<h3>Models</h3>
|
||||
<UL>
|
||||
<LI> <tt>array</tt>
|
||||
<LI> <tt>array_ptr</tt>
|
||||
<LI> <tt>vector<bool></tt>
|
||||
</UL>
|
||||
|
||||
|
||||
<h3>Collection Refinements</h3>
|
||||
|
||||
There are quite a few concepts that refine the Collection concept,
|
||||
similar to the concepts that refine the Container concept. Here
|
||||
is a brief overview of the refining concepts.
|
||||
|
||||
<h4>ForwardCollection</h4>
|
||||
The elements are arranged in some order that
|
||||
does not change spontaneously from one iteration to the next. As
|
||||
a result, a ForwardCollection is
|
||||
<A
|
||||
href="http://www.sgi.com/tech/stl/EqualityComparable.html">EqualityComparable</A>
|
||||
and
|
||||
<A
|
||||
href="http://www.sgi.com/tech/stl/LessThanComparable.html">LessThanComparable</A>.
|
||||
In addition, the iterator type of a ForwardCollection is a
|
||||
MultiPassInputIterator which is just an InputIterator with the added
|
||||
requirements that the iterator can be used to make multiple passes
|
||||
through a range, and that if <tt>it1 == it2</tt> and <tt>it1</tt> is
|
||||
dereferenceable then <tt>++it1 == ++it2</tt>. The ForwardCollection
|
||||
also has a <tt>front()</tt> method.
|
||||
|
||||
<p>
|
||||
<Table border>
|
||||
<TR>
|
||||
<TH>
|
||||
Name
|
||||
</TH>
|
||||
<TH>
|
||||
Expression
|
||||
</TH>
|
||||
<TH>
|
||||
Return type
|
||||
</TH>
|
||||
<TH>
|
||||
Semantics
|
||||
</TH>
|
||||
</TR>
|
||||
|
||||
<TR>
|
||||
<TD VAlign=top>
|
||||
Font
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<tt>a.front()</tt>
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<tt>reference</tt> if <tt>a</tt> is mutable, <br> <tt>const_reference</tt>
|
||||
otherwise.
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
Equivalent to <tt>*(a.first())</tt>.
|
||||
</TD>
|
||||
</TR>
|
||||
|
||||
</table>
|
||||
|
||||
|
||||
<h4>ReversibleCollection</h4>
|
||||
|
||||
The container provides access to iterators that traverse in both
|
||||
directions (forward and reverse). The iterator type must meet all of
|
||||
the requirements of
|
||||
<a href="http://www.sgi.com/tech/stl/BidirectionalIterator.html">BidirectionalIterator</a>
|
||||
except that the reference type does not have to be a real C++
|
||||
reference. The ReversibleCollection adds the following requirements
|
||||
to those of ForwardCollection.
|
||||
<p>
|
||||
|
||||
<Table border>
|
||||
<TR>
|
||||
<TH>
|
||||
Name
|
||||
</TH>
|
||||
<TH>
|
||||
Expression
|
||||
</TH>
|
||||
<TH>
|
||||
Return type
|
||||
</TH>
|
||||
<TH>
|
||||
Semantics
|
||||
</TH>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD VAlign=top>
|
||||
Beginning of range
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<tt>a.rbegin()</tt>
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<tt>reverse_iterator</tt> if <tt>a</tt> is mutable,
|
||||
<tt>const_reverse_iterator</tt> otherwise.
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
Equivalent to <tt>X::reverse_iterator(a.end())</tt>.
|
||||
</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD VAlign=top>
|
||||
End of range
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<tt>a.rend()</tt>
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<tt>reverse_iterator</tt> if <tt>a</tt> is mutable,
|
||||
<tt>const_reverse_iterator</tt> otherwise.
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
Equivalent to <tt>X::reverse_iterator(a.begin())</tt>.
|
||||
</TD>
|
||||
</tr>
|
||||
|
||||
<TR>
|
||||
<TD VAlign=top>
|
||||
Back
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<tt>a.back()</tt>
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<tt>reference</tt> if <tt>a</tt> is mutable, <br> <tt>const_reference</tt>
|
||||
otherwise.
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
Equivalent to <tt>*(--a.end())</tt>.
|
||||
</TD>
|
||||
</TR>
|
||||
|
||||
</table>
|
||||
|
||||
<h4>SequentialCollection</h4>
|
||||
|
||||
The elements are arranged in a strict linear order. No extra methods
|
||||
are required.
|
||||
|
||||
<h4>RandomAccessCollection</h4>
|
||||
|
||||
The iterators of a RandomAccessCollection satisfy all of the
|
||||
requirements of <a
|
||||
href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">RandomAccessIterator</a>
|
||||
except that the reference type does not have to be a real C++
|
||||
reference. In addition, a RandomAccessCollection provides
|
||||
an element access operator.
|
||||
|
||||
<p>
|
||||
|
||||
<Table border>
|
||||
<TR>
|
||||
<TH>
|
||||
Name
|
||||
</TH>
|
||||
<TH>
|
||||
Expression
|
||||
</TH>
|
||||
<TH>
|
||||
Return type
|
||||
</TH>
|
||||
<TH>
|
||||
Semantics
|
||||
</TH>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD VAlign=top>
|
||||
Element Access
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<tt>a[n]</tt>
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
<tt>reference</tt> if <tt>a</tt> is mutable,
|
||||
<tt>const_reference</tt> otherwise.
|
||||
</TD>
|
||||
<TD VAlign=top>
|
||||
Returns the nth element of the Collection.
|
||||
<tt>n</tt> must be convertible to <tt>size_type</tt>.
|
||||
Precondition: <tt>0 <= n < a.size()</tt>.
|
||||
</TD>
|
||||
</TR>
|
||||
|
||||
</table>
|
||||
|
||||
<h3>Notes</h3>
|
||||
|
||||
<P><A name="1">[1]</A>
|
||||
|
||||
The reference type does not have to be a real C++ reference. The
|
||||
requirements of the reference type depend on the context within which
|
||||
the Collection is being used. Specifically it depends on the
|
||||
requirements the context places on the value type of the Collection.
|
||||
The reference type of the Collection must meet the same requirements
|
||||
as the value type. In addition, the reference objects must be
|
||||
equivalent to the value type objects in the collection (which is
|
||||
trivially true if they are the same object). Also, in a mutable
|
||||
Collection, an assignment to the reference object must result in an
|
||||
assignment to the object in the Collection (again, which is trivially
|
||||
true if they are the same object, but non-trivial if the reference
|
||||
type is a proxy class).
|
||||
|
||||
<h3>See also</h3>
|
||||
<A href="http://www.sgi.com/tech/stl/Container.html">Container</A>
|
||||
|
||||
|
||||
<br>
|
||||
<HR>
|
||||
<TABLE>
|
||||
<TR valign=top>
|
||||
<TD nowrap>Copyright © 2000</TD><TD>
|
||||
<A HREF=http://www.boost.org/people/jeremy_siek.htm>Jeremy Siek</A>, Univ.of Notre Dame and C++ Library & Compiler Group/SGI (<A HREF="mailto:jsiek@engr.sgi.com">jsiek@engr.sgi.com</A>)
|
||||
</TD></TR></TABLE>
|
||||
|
||||
</BODY>
|
||||
</HTML>
|
46
addressof_test.cpp
Normal file
46
addressof_test.cpp
Normal file
@ -0,0 +1,46 @@
|
||||
// Copyright (C) 2002 Brad King (brad.king@kitware.com)
|
||||
// Doug Gregor (gregod@cs.rpi.edu)
|
||||
//
|
||||
// Permission to copy, use, sell and distribute this software is granted
|
||||
// provided this copyright notice appears in all copies.
|
||||
// Permission to modify the code and to distribute modified code is granted
|
||||
// provided this copyright notice appears in all copies, and a notice
|
||||
// that the code was modified is included with the copyright notice.
|
||||
//
|
||||
// This software is provided "as is" without express or implied warranty,
|
||||
// and with no claim as to its suitability for any purpose.
|
||||
|
||||
// For more information, see http://www.boost.org
|
||||
|
||||
#define BOOST_INCLUDE_MAIN
|
||||
#include <boost/test/test_tools.hpp>
|
||||
#include <boost/utility.hpp>
|
||||
|
||||
struct useless_type {};
|
||||
|
||||
class nonaddressable {
|
||||
public:
|
||||
void dummy(); // Silence GCC warning: all member of class are private
|
||||
|
||||
private:
|
||||
useless_type operator&() const;
|
||||
};
|
||||
|
||||
int test_main(int, char*[])
|
||||
{
|
||||
nonaddressable* px = new nonaddressable();
|
||||
|
||||
nonaddressable& x = *px;
|
||||
BOOST_TEST(boost::addressof(x) == px);
|
||||
|
||||
const nonaddressable& cx = *px;
|
||||
BOOST_TEST(boost::addressof(cx) == static_cast<const nonaddressable*>(px));
|
||||
|
||||
volatile nonaddressable& vx = *px;
|
||||
BOOST_TEST(boost::addressof(vx) == static_cast<volatile nonaddressable*>(px));
|
||||
|
||||
const volatile nonaddressable& cvx = *px;
|
||||
BOOST_TEST(boost::addressof(cvx) == static_cast<const volatile nonaddressable*>(px));
|
||||
|
||||
return 0;
|
||||
}
|
33
assert_test.cpp
Normal file
33
assert_test.cpp
Normal file
@ -0,0 +1,33 @@
|
||||
#if defined(_MSC_VER) && !defined(__ICL)
|
||||
#pragma warning(disable: 4786) // identifier truncated in debug info
|
||||
#pragma warning(disable: 4710) // function not inlined
|
||||
#pragma warning(disable: 4711) // function selected for automatic inline expansion
|
||||
#pragma warning(disable: 4514) // unreferenced inline removed
|
||||
#endif
|
||||
|
||||
//
|
||||
// assert_test.cpp - a test for boost/assert.hpp
|
||||
//
|
||||
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
#define BOOST_DEBUG 1
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <cstdio>
|
||||
|
||||
bool boost_error(char const * expr, char const * func, char const * file, long line)
|
||||
{
|
||||
std::printf("%s(%ld): Assertion '%s' failed in function '%s'\n", file, line, expr, func);
|
||||
return true; // fail w/ standard assert()
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
BOOST_ASSERT(0 == 1);
|
||||
}
|
@ -57,7 +57,7 @@ struct object_id_compare
|
||||
// A singleton of this type coordinates the acknowledgements
|
||||
// of objects being created and used.
|
||||
class object_registrar
|
||||
: boost::noncopyable
|
||||
: private boost::noncopyable
|
||||
{
|
||||
public:
|
||||
|
||||
|
249
binary_search_test.cpp
Normal file
249
binary_search_test.cpp
Normal file
@ -0,0 +1,249 @@
|
||||
// (C) Copyright David Abrahams 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.
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <climits>
|
||||
#include <iostream>
|
||||
#include <cassert>
|
||||
#include <stdlib.h> // for rand(). Would use cstdlib but VC6.4 doesn't put it in std::
|
||||
#include <list>
|
||||
#include <algorithm>
|
||||
#include <boost/detail/binary_search.hpp>
|
||||
|
||||
#if defined(__SGI_STL_PORT) ? defined(__SGI_STL_OWN_IOSTREAMS) : (!defined(__GNUC__) || __GNUC__ > 2)
|
||||
# define USE_SSTREAM
|
||||
#endif
|
||||
|
||||
#ifdef USE_SSTREAM
|
||||
# include <sstream>
|
||||
#else
|
||||
# include <strstream>
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
||||
typedef std::vector<std::string> string_vector;
|
||||
|
||||
const std::size_t sequence_length = 1000;
|
||||
|
||||
unsigned random_number()
|
||||
{
|
||||
return static_cast<unsigned>(::rand()) % sequence_length;
|
||||
}
|
||||
|
||||
# ifndef USE_SSTREAM
|
||||
class unfreezer {
|
||||
public:
|
||||
unfreezer(std::ostrstream& s) : m_stream(s) {}
|
||||
~unfreezer() { m_stream.freeze(false); }
|
||||
private:
|
||||
std::ostrstream& m_stream;
|
||||
};
|
||||
# endif
|
||||
|
||||
template <class T>
|
||||
void push_back_random_number_string(T& seq)
|
||||
{
|
||||
unsigned value = random_number();
|
||||
# if defined(__SGI_STL_PORT) ? defined(__SGI_STL_OWN_IOSTREAMS) : (!defined(__GNUC__) || __GNUC__ > 2)
|
||||
std::ostringstream s;
|
||||
s << value;
|
||||
seq.push_back(s.str());
|
||||
# else
|
||||
std::ostrstream s;
|
||||
auto unfreezer unfreeze(s);
|
||||
s << value << char(0);
|
||||
seq.push_back(std::string(s.str()));
|
||||
# endif
|
||||
}
|
||||
|
||||
inline unsigned to_int(unsigned x) { return x; }
|
||||
inline unsigned to_int(const std::string& x) { return atoi(x.c_str()); }
|
||||
|
||||
struct cmp
|
||||
{
|
||||
template <class A1, class A2>
|
||||
inline bool operator()(const A1& a1, const A2& a2) const
|
||||
{
|
||||
return to_int(a1) < to_int(a2);
|
||||
}
|
||||
};
|
||||
|
||||
inline bool operator<(const std::string& x, const unsigned y)
|
||||
{
|
||||
return to_int(x) < y;
|
||||
}
|
||||
|
||||
inline bool operator<(const unsigned y, const std::string& x)
|
||||
{
|
||||
return y < to_int(x);
|
||||
}
|
||||
|
||||
template <class T> void sort_by_value(T&);
|
||||
|
||||
template <>
|
||||
void sort_by_value(std::vector<std::string>& v)
|
||||
{
|
||||
std::sort(v.begin(), v.end(), cmp());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void random_sorted_sequence(T& seq)
|
||||
{
|
||||
seq.clear();
|
||||
for (std::size_t i = 0; i < sequence_length; ++i)
|
||||
{
|
||||
push_back_random_number_string(seq);
|
||||
}
|
||||
sort_by_value(seq);
|
||||
}
|
||||
|
||||
# if defined(BOOST_MSVC) && BOOST_MSVC < 1300 && !defined(__SGI_STL_PORT)
|
||||
// VC6's standard lib doesn't have a template member function for list::sort()
|
||||
template <>
|
||||
void random_sorted_sequence(std::list<std::string>& result)
|
||||
{
|
||||
std::vector<std::string> seq;
|
||||
seq.reserve(sequence_length);
|
||||
for (std::size_t i = 0; i < sequence_length; ++i)
|
||||
{
|
||||
push_back_random_number_string(seq);
|
||||
}
|
||||
sort_by_value(seq);
|
||||
result.resize(seq.size());
|
||||
std::copy(seq.begin(), seq.end(), result.begin());
|
||||
}
|
||||
#else
|
||||
template <>
|
||||
inline void sort_by_value(std::list<std::string>& l)
|
||||
{
|
||||
l.sort(cmp());
|
||||
}
|
||||
# endif
|
||||
|
||||
// A way to select the comparisons with/without a Compare parameter for testing.
|
||||
template <class Compare> struct searches
|
||||
{
|
||||
template <class Iterator, class Key>
|
||||
static Iterator lower_bound(Iterator start, Iterator finish, Key key, Compare cmp)
|
||||
{ return boost::detail::lower_bound(start, finish, key, cmp); }
|
||||
|
||||
template <class Iterator, class Key>
|
||||
static Iterator upper_bound(Iterator start, Iterator finish, Key key, Compare cmp)
|
||||
{ return boost::detail::upper_bound(start, finish, key, cmp); }
|
||||
|
||||
template <class Iterator, class Key>
|
||||
static std::pair<Iterator, Iterator> equal_range(Iterator start, Iterator finish, Key key, Compare cmp)
|
||||
{ return boost::detail::equal_range(start, finish, key, cmp); }
|
||||
|
||||
template <class Iterator, class Key>
|
||||
static bool binary_search(Iterator start, Iterator finish, Key key, Compare cmp)
|
||||
{ return boost::detail::binary_search(start, finish, key, cmp); }
|
||||
};
|
||||
|
||||
struct no_compare {};
|
||||
|
||||
template <> struct searches<no_compare>
|
||||
{
|
||||
template <class Iterator, class Key>
|
||||
static Iterator lower_bound(Iterator start, Iterator finish, Key key, no_compare)
|
||||
{ return boost::detail::lower_bound(start, finish, key); }
|
||||
|
||||
template <class Iterator, class Key>
|
||||
static Iterator upper_bound(Iterator start, Iterator finish, Key key, no_compare)
|
||||
{ return boost::detail::upper_bound(start, finish, key); }
|
||||
|
||||
template <class Iterator, class Key>
|
||||
static std::pair<Iterator, Iterator> equal_range(Iterator start, Iterator finish, Key key, no_compare)
|
||||
{ return boost::detail::equal_range(start, finish, key); }
|
||||
|
||||
template <class Iterator, class Key>
|
||||
static bool binary_search(Iterator start, Iterator finish, Key key, no_compare)
|
||||
{ return boost::detail::binary_search(start, finish, key); }
|
||||
};
|
||||
|
||||
template <class Sequence, class Compare>
|
||||
void test_loop(Sequence& x, Compare cmp, unsigned long test_count)
|
||||
{
|
||||
typedef typename Sequence::const_iterator const_iterator;
|
||||
|
||||
for (unsigned long i = 0; i < test_count; ++i)
|
||||
{
|
||||
random_sorted_sequence(x);
|
||||
const const_iterator start = x.begin();
|
||||
const const_iterator finish = x.end();
|
||||
|
||||
unsigned key = random_number();
|
||||
const const_iterator l = searches<Compare>::lower_bound(start, finish, key, cmp);
|
||||
const const_iterator u = searches<Compare>::upper_bound(start, finish, key, cmp);
|
||||
|
||||
bool found_l = false;
|
||||
bool found_u = false;
|
||||
std::size_t index = 0;
|
||||
std::size_t count = 0;
|
||||
unsigned last_value = 0;
|
||||
for (const_iterator p = start; p != finish; ++p)
|
||||
{
|
||||
if (p == l)
|
||||
found_l = true;
|
||||
|
||||
if (p == u)
|
||||
{
|
||||
assert(found_l);
|
||||
found_u = true;
|
||||
}
|
||||
|
||||
unsigned value = to_int(*p);
|
||||
assert(value >= last_value);
|
||||
last_value = value;
|
||||
|
||||
if (!found_l)
|
||||
{
|
||||
++index;
|
||||
assert(to_int(*p) < key);
|
||||
}
|
||||
else if (!found_u)
|
||||
{
|
||||
++count;
|
||||
assert(to_int(*p) == key);
|
||||
}
|
||||
else
|
||||
assert(to_int(*p) > key);
|
||||
}
|
||||
assert(found_l || l == finish);
|
||||
assert(found_u || u == finish);
|
||||
|
||||
std::pair<const_iterator, const_iterator>
|
||||
range = searches<Compare>::equal_range(start, finish, key, cmp);
|
||||
assert(range.first == l);
|
||||
assert(range.second == u);
|
||||
|
||||
bool found = searches<Compare>::binary_search(start, finish, key, cmp);
|
||||
assert(found == (u != l));
|
||||
std::cout << "found " << count << " copies of " << key << " at index " << index << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
std::vector<std::string> x;
|
||||
std::cout << "=== testing random-access iterators with <: ===\n";
|
||||
test_loop(x, no_compare(), 25);
|
||||
std::cout << "=== testing random-access iterators with compare: ===\n";
|
||||
test_loop(x, cmp(), 25);
|
||||
|
||||
std::list<std::string> y;
|
||||
std::cout << "=== testing bidirectional iterators with <: ===\n";
|
||||
test_loop(y, no_compare(), 25);
|
||||
std::cout << "=== testing bidirectional iterators with compare: ===\n";
|
||||
test_loop(y, cmp(), 25);
|
||||
std::cerr << "******TEST PASSED******\n";
|
||||
return 0;
|
||||
}
|
@ -5,7 +5,7 @@
|
||||
content="text/html; charset=iso-8859-1">
|
||||
<meta name="Template"
|
||||
content="C:\PROGRAM FILES\MICROSOFT OFFICE\OFFICE\html.dot">
|
||||
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
|
||||
<meta name="GENERATOR" content="Microsoft FrontPage Express 2.0">
|
||||
<title>Call Traits</title>
|
||||
</head>
|
||||
|
||||
@ -592,7 +592,8 @@ would prevent template argument deduction from functioning.</p>
|
||||
<p>The call_traits template will "optimize" the passing
|
||||
of a small built-in type as a function parameter, this mainly has
|
||||
an effect when the parameter is used within a loop body. In the
|
||||
following example (see <a href="algo_opt_examples.cpp">algo_opt_examples.cpp</a>),
|
||||
following example (see <a
|
||||
href="../type_traits/examples/fill_example.cpp">fill_example.cpp</a>),
|
||||
a version of std::fill is optimized in two ways: if the type
|
||||
passed is a single byte built-in type then std::memset is used to
|
||||
effect the fill, otherwise a conventional C++ implemention is
|
||||
@ -751,7 +752,8 @@ Hinnant and John Maddock.</p>
|
||||
<p>Maintained by <a href="mailto:John_Maddock@compuserve.com">John
|
||||
Maddock</a>, the latest version of this file can be found at <a
|
||||
href="http://www.boost.org/">www.boost.org</a>, and the boost
|
||||
discussion list at <a href="http://www.yahoogroups.com/list/boost">www.yahoogroups.com/list/boost</a>.</p>
|
||||
discussion list at <a
|
||||
href="http://www.yahoogroups.com/list/boost">www.yahoogroups.com/list/boost</a>.</p>
|
||||
|
||||
<p>.</p>
|
||||
|
||||
|
@ -6,6 +6,8 @@
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
|
||||
// standalone test program for <boost/call_traits.hpp>
|
||||
// 18 Mar 2002:
|
||||
// Changed some names to prevent conflicts with some new type_traits additions.
|
||||
// 03 Oct 2000:
|
||||
// Enabled extra tests for VC6.
|
||||
|
||||
@ -78,7 +80,7 @@ struct contained<T[N]>
|
||||
#endif
|
||||
|
||||
template <class T>
|
||||
contained<typename boost::call_traits<T>::value_type> wrap(const T& t)
|
||||
contained<typename boost::call_traits<T>::value_type> test_wrap_type(const T& t)
|
||||
{
|
||||
typedef typename boost::call_traits<T>::value_type ct;
|
||||
return contained<ct>(t);
|
||||
@ -160,10 +162,10 @@ struct call_traits_checker<T[N]>
|
||||
|
||||
//
|
||||
// check_wrap:
|
||||
template <class T, class U>
|
||||
void check_wrap(const contained<T>& w, const U& u)
|
||||
template <class W, class U>
|
||||
void check_wrap(const W& w, const U& u)
|
||||
{
|
||||
cout << "checking contained<" << typeid(T).name() << ">..." << endl;
|
||||
cout << "checking " << typeid(W).name() << "..." << endl;
|
||||
assert(w.value() == u);
|
||||
}
|
||||
|
||||
@ -204,25 +206,22 @@ int main(int argc, char *argv[ ])
|
||||
c2(i);
|
||||
int* pi = &i;
|
||||
int a[2] = {1,2};
|
||||
#if (defined(BOOST_MSVC6_MEMBER_TEMPLATES) || !defined(BOOST_NO_MEMBER_TEMPLATES)) && !defined(__ICL)
|
||||
#if defined(BOOST_MSVC6_MEMBER_TEMPLATES) && !defined(__ICL)
|
||||
call_traits_checker<int*> c3;
|
||||
c3(pi);
|
||||
call_traits_checker<int&> c4;
|
||||
c4(i);
|
||||
call_traits_checker<const int&> c5;
|
||||
c5(i);
|
||||
#if !defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(__MWERKS__)
|
||||
#if !defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(__MWERKS__) && !defined(__SUNPRO_CC)
|
||||
call_traits_checker<int[2]> c6;
|
||||
c6(a);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
check_wrap(wrap(2), 2);
|
||||
// compiler can't deduce this for some reason:
|
||||
//const char ca[4] = "abc";
|
||||
//check_wrap(wrap(ca), ca);
|
||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
check_wrap(wrap(a), a);
|
||||
check_wrap(test_wrap_type(2), 2);
|
||||
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(__SUNPRO_CC)
|
||||
check_wrap(test_wrap_type(a), a);
|
||||
check_make_pair(test::make_pair(a, a), a, a);
|
||||
#endif
|
||||
|
||||
@ -243,12 +242,12 @@ int main(int argc, char *argv[ ])
|
||||
type_test(int*&, boost::call_traits<int*>::reference)
|
||||
type_test(int*const&, boost::call_traits<int*>::const_reference)
|
||||
type_test(int*const, boost::call_traits<int*>::param_type)
|
||||
#if defined(BOOST_MSVC6_MEMBER_TEMPLATES) || !defined(BOOST_NO_MEMBER_TEMPLATES)
|
||||
#if defined(BOOST_MSVC6_MEMBER_TEMPLATES)
|
||||
type_test(int&, boost::call_traits<int&>::value_type)
|
||||
type_test(int&, boost::call_traits<int&>::reference)
|
||||
type_test(const int&, boost::call_traits<int&>::const_reference)
|
||||
type_test(int&, boost::call_traits<int&>::param_type)
|
||||
#if !(defined(__GNUC__) && (__GNUC__ < 4))
|
||||
#if !(defined(__GNUC__) && ((__GNUC__ < 3) || (__GNUC__ == 3) && (__GNUC_MINOR__ < 1)))
|
||||
type_test(int&, boost::call_traits<cr_type>::value_type)
|
||||
type_test(int&, boost::call_traits<cr_type>::reference)
|
||||
type_test(const int&, boost::call_traits<cr_type>::const_reference)
|
||||
@ -271,16 +270,26 @@ int main(int argc, char *argv[ ])
|
||||
type_test(const int(&)[3], boost::call_traits<const int[3]>::reference)
|
||||
type_test(const int(&)[3], boost::call_traits<const int[3]>::const_reference)
|
||||
type_test(const int*const, boost::call_traits<const int[3]>::param_type)
|
||||
// test with abstract base class:
|
||||
type_test(test_abc1, boost::call_traits<test_abc1>::value_type)
|
||||
type_test(test_abc1&, boost::call_traits<test_abc1>::reference)
|
||||
type_test(const test_abc1&, boost::call_traits<test_abc1>::const_reference)
|
||||
type_test(const test_abc1&, boost::call_traits<test_abc1>::param_type)
|
||||
#else
|
||||
std::cout << "You're compiler does not support partial template instantiation, skipping 8 tests (8 errors)" << std::endl;
|
||||
failures += 8;
|
||||
test_count += 8;
|
||||
std::cout << "You're compiler does not support partial template specialiation, skipping 8 tests (8 errors)" << std::endl;
|
||||
failures += 12;
|
||||
test_count += 12;
|
||||
#endif
|
||||
#else
|
||||
std::cout << "You're compiler does not support partial template instantiation, skipping 20 tests (20 errors)" << std::endl;
|
||||
failures += 20;
|
||||
test_count += 20;
|
||||
std::cout << "You're compiler does not support partial template specialiation, skipping 20 tests (20 errors)" << std::endl;
|
||||
failures += 24;
|
||||
test_count += 24;
|
||||
#endif
|
||||
// test with an incomplete type:
|
||||
type_test(incomplete_type, boost::call_traits<incomplete_type>::value_type)
|
||||
type_test(incomplete_type&, boost::call_traits<incomplete_type>::reference)
|
||||
type_test(const incomplete_type&, boost::call_traits<incomplete_type>::const_reference)
|
||||
type_test(const incomplete_type&, boost::call_traits<incomplete_type>::param_type)
|
||||
|
||||
return check_result(argc, argv);
|
||||
}
|
||||
@ -376,8 +385,10 @@ void call_traits_test<T, true>::assert_construct(typename boost::call_traits<T>:
|
||||
unused_variable(v3);
|
||||
unused_variable(v4);
|
||||
unused_variable(v5);
|
||||
#ifndef __BORLANDC__
|
||||
unused_variable(r2);
|
||||
unused_variable(cr2);
|
||||
#endif
|
||||
unused_variable(cr3);
|
||||
unused_variable(p2);
|
||||
unused_variable(p3);
|
||||
@ -389,26 +400,31 @@ void call_traits_test<T, true>::assert_construct(typename boost::call_traits<T>:
|
||||
template struct call_traits_test<int>;
|
||||
template struct call_traits_test<const int>;
|
||||
template struct call_traits_test<int*>;
|
||||
#if defined(BOOST_MSVC6_MEMBER_TEMPLATES) || !defined(BOOST_NO_MEMBER_TEMPLATES)
|
||||
#if defined(BOOST_MSVC6_MEMBER_TEMPLATES)
|
||||
template struct call_traits_test<int&>;
|
||||
template struct call_traits_test<const int&>;
|
||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(__SUNPRO_CC)
|
||||
template struct call_traits_test<int[2], true>;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
unsigned int expected_failures = 10;
|
||||
#if defined(BOOST_MSVC) && _MSC_VER <= 1300
|
||||
unsigned int expected_failures = 14;
|
||||
#elif defined(__SUNPRO_CC)
|
||||
unsigned int expected_failures = 11;
|
||||
#if(__SUNPRO_CC <= 0x520)
|
||||
unsigned int expected_failures = 18;
|
||||
#elif(__SUNPRO_CC < 0x530)
|
||||
unsigned int expected_failures = 17;
|
||||
#else
|
||||
unsigned int expected_failures = 6;
|
||||
#endif
|
||||
#elif defined(__BORLANDC__)
|
||||
unsigned int expected_failures = 2;
|
||||
#elif defined(__GNUC__)
|
||||
#elif (defined(__GNUC__) && ((__GNUC__ < 3) || (__GNUC__ == 3) && (__GNUC_MINOR__ < 1)))
|
||||
unsigned int expected_failures = 4;
|
||||
#elif defined(__HP_aCC)
|
||||
unsigned int expected_failures = 24;
|
||||
#else
|
||||
unsigned int expected_failures = 0;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -329,7 +329,7 @@ void compressed_pair_array_tester<T1, T2>::test(first_param_type p1, second_para
|
||||
BOOST_TEST(sizeof(T2) == sizeof(cp1.second()));
|
||||
}
|
||||
|
||||
int test_main(int, char **)
|
||||
int test_main(int, char *[])
|
||||
{
|
||||
// declare some variables to pass to the tester:
|
||||
non_empty1 ne1(2);
|
||||
|
@ -22,8 +22,8 @@ int main(int, char*[])
|
||||
// Example of using make_counting_iterator()
|
||||
std::cout << "counting from -5 to 4:" << std::endl;
|
||||
std::copy(boost::make_counting_iterator(-5),
|
||||
boost::make_counting_iterator(5),
|
||||
std::ostream_iterator<int>(std::cout, " "));
|
||||
boost::make_counting_iterator(5),
|
||||
std::ostream_iterator<int>(std::cout, " "));
|
||||
std::cout << std::endl;
|
||||
|
||||
// Example of using counting iterator to create an array of pointers.
|
||||
@ -31,23 +31,27 @@ int main(int, char*[])
|
||||
std::vector<int> numbers;
|
||||
// Fill "numbers" array with [0,N)
|
||||
std::copy(boost::make_counting_iterator(0), boost::make_counting_iterator(N),
|
||||
std::back_inserter(numbers));
|
||||
std::back_inserter(numbers));
|
||||
|
||||
std::vector<std::vector<int>::iterator> pointers;
|
||||
|
||||
// Use counting iterator to fill in the array of pointers.
|
||||
// causes an ICE with MSVC6
|
||||
#if !defined(BOOST_MSVC) || (BOOST_MSVC > 1200)
|
||||
std::copy(boost::make_counting_iterator(numbers.begin()),
|
||||
boost::make_counting_iterator(numbers.end()),
|
||||
std::back_inserter(pointers));
|
||||
boost::make_counting_iterator(numbers.end()),
|
||||
std::back_inserter(pointers));
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_MSVC) || (BOOST_MSVC > 1300)
|
||||
// Use indirect iterator to print out numbers by accessing
|
||||
// them through the array of pointers.
|
||||
std::cout << "indirectly printing out the numbers from 0 to "
|
||||
<< N << std::endl;
|
||||
<< N << std::endl;
|
||||
std::copy(boost::make_indirect_iterator(pointers.begin()),
|
||||
boost::make_indirect_iterator(pointers.end()),
|
||||
std::ostream_iterator<int>(std::cout, " "));
|
||||
boost::make_indirect_iterator(pointers.end()),
|
||||
std::ostream_iterator<int>(std::cout, " "));
|
||||
std::cout << std::endl;
|
||||
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
@ -27,7 +27,9 @@
|
||||
#include <climits>
|
||||
#include <iterator>
|
||||
#include <stdlib.h>
|
||||
#include <boost/tuple/tuple.hpp>
|
||||
#ifndef __BORLANDC__
|
||||
# include <boost/tuple/tuple.hpp>
|
||||
#endif
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <cassert>
|
||||
@ -72,8 +74,12 @@ void category_test(
|
||||
|
||||
// Try some binary searches on the range to show that it's ordered
|
||||
assert(std::binary_search(start, finish, *internal));
|
||||
CountingIterator x,y;
|
||||
boost::tie(x,y) = std::equal_range(start, finish, *internal);
|
||||
|
||||
// #including tuple crashed borland, so I had to give up on tie().
|
||||
std::pair<CountingIterator,CountingIterator> xy(
|
||||
std::equal_range(start, finish, *internal));
|
||||
CountingIterator x = xy.first, y = xy.second;
|
||||
|
||||
assert(boost::detail::distance(x, y) == 1);
|
||||
|
||||
// Show that values outside the range can't be found
|
||||
@ -234,14 +240,14 @@ int main()
|
||||
test_integer<unsigned int>();
|
||||
test_integer<long>();
|
||||
test_integer<unsigned long>();
|
||||
#if defined(ULLONG_MAX) || defined(ULONG_LONG_MAX)
|
||||
#if defined(BOOST_HAS_LONG_LONG)
|
||||
test_integer<long long>();
|
||||
test_integer<unsigned long long>();
|
||||
#endif
|
||||
|
||||
// wrapping an iterator or non-built-in integer type causes an INTERNAL
|
||||
// COMPILER ERROR in MSVC without STLport. I'm clueless as to why.
|
||||
#if !defined(BOOST_MSVC) || defined(__SGI_STL_PORT)
|
||||
#if !defined(BOOST_MSVC) || BOOST_MSVC > 1200 || defined(__SGI_STL_PORT)
|
||||
// Test user-defined type.
|
||||
test_integer<my_int1>();
|
||||
test_integer<my_int2>();
|
||||
@ -253,7 +259,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));
|
||||
|
32
current_function_test.cpp
Normal file
32
current_function_test.cpp
Normal file
@ -0,0 +1,32 @@
|
||||
#if defined(_MSC_VER) && !defined(__ICL)
|
||||
#pragma warning(disable: 4786) // identifier truncated in debug info
|
||||
#pragma warning(disable: 4710) // function not inlined
|
||||
#pragma warning(disable: 4711) // function selected for automatic inline expansion
|
||||
#pragma warning(disable: 4514) // unreferenced inline removed
|
||||
#endif
|
||||
|
||||
//
|
||||
// current_function_test.cpp - a test for boost/current_function.hpp
|
||||
//
|
||||
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
#include <boost/current_function.hpp>
|
||||
#include <cstdio>
|
||||
|
||||
void message(char const * file, long line, char const * func, char const * msg)
|
||||
{
|
||||
std::printf("%s(%ld): %s in function '%s'\n", file, line, msg, func);
|
||||
}
|
||||
|
||||
#define MESSAGE(msg) message(__FILE__, __LINE__, BOOST_CURRENT_FUNCTION, msg)
|
||||
|
||||
int main()
|
||||
{
|
||||
MESSAGE("assertion failed");
|
||||
}
|
@ -195,7 +195,7 @@ The policies type has only one public function, which is its constructor:
|
||||
|
||||
<pre>
|
||||
template <class Predicate, class BaseIterator>
|
||||
typename detail::filter_generator<Predicate, BaseIterator>::type
|
||||
typename filter_generator<Predicate, BaseIterator>::type
|
||||
make_filter_iterator(BaseIterator first, BaseIterator last, const Predicate& p = Predicate())
|
||||
</pre>
|
||||
|
||||
|
@ -7,7 +7,6 @@
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
@ -20,17 +19,26 @@ struct is_positive_number {
|
||||
|
||||
int main()
|
||||
{
|
||||
int numbers[] = { 0, -1, 4, -3, 5, 8, -2 };
|
||||
const int N = sizeof(numbers)/sizeof(int);
|
||||
|
||||
int numbers_[] = { 0, -1, 4, -3, 5, 8, -2 };
|
||||
const int N = sizeof(numbers_)/sizeof(int);
|
||||
|
||||
#ifdef BOOST_NO_STD_ITERATOR_TRAITS
|
||||
// Assume there won't be proper iterator traits for pointers. This
|
||||
// is just a wrapper for int* which has the right traits.
|
||||
typedef boost::iterator_adaptor<int*, boost::default_iterator_policies, int> base_iterator;
|
||||
#else
|
||||
typedef int* base_iterator;
|
||||
#endif
|
||||
base_iterator numbers(numbers_);
|
||||
|
||||
// Example using make_filter_iterator()
|
||||
std::copy(boost::make_filter_iterator<is_positive_number>(numbers, numbers + N),
|
||||
boost::make_filter_iterator<is_positive_number>(numbers + N, numbers + N),
|
||||
std::ostream_iterator<int>(std::cout, " "));
|
||||
boost::make_filter_iterator<is_positive_number>(numbers + N, numbers + N),
|
||||
std::ostream_iterator<int>(std::cout, " "));
|
||||
std::cout << std::endl;
|
||||
|
||||
// Example using filter_iterator_generator
|
||||
typedef boost::filter_iterator_generator<is_positive_number, int*, int>::type
|
||||
typedef boost::filter_iterator_generator<is_positive_number, base_iterator, int>::type
|
||||
FilterIter;
|
||||
is_positive_number predicate;
|
||||
FilterIter::policies_type policies(predicate, numbers + N);
|
||||
@ -42,10 +50,10 @@ int main()
|
||||
|
||||
// Another example using make_filter_iterator()
|
||||
std::copy(boost::make_filter_iterator(numbers, numbers + N,
|
||||
std::bind2nd(std::greater<int>(), -2)),
|
||||
boost::make_filter_iterator(numbers + N, numbers + N,
|
||||
std::bind2nd(std::greater<int>(), -2)),
|
||||
std::ostream_iterator<int>(std::cout, " "));
|
||||
std::bind2nd(std::greater<int>(), -2)),
|
||||
boost::make_filter_iterator(numbers + N, numbers + N,
|
||||
std::bind2nd(std::greater<int>(), -2)),
|
||||
std::ostream_iterator<int>(std::cout, " "));
|
||||
std::cout << std::endl;
|
||||
|
||||
|
||||
|
@ -33,7 +33,7 @@ int main(int, char*[])
|
||||
|
||||
std::string s = "";
|
||||
std::copy(x.begin(), x.end(),
|
||||
boost::make_function_output_iterator(string_appender(s)));
|
||||
boost::make_function_output_iterator(string_appender(s)));
|
||||
|
||||
std::cout << s << std::endl;
|
||||
|
||||
|
150
generator_iterator.htm
Normal file
150
generator_iterator.htm
Normal file
@ -0,0 +1,150 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>Generator Iterator Adaptor Documentation</title>
|
||||
</head>
|
||||
|
||||
<body bgcolor="#FFFFFF" text="#000000">
|
||||
|
||||
<img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="center" width="277" height="86">
|
||||
|
||||
<h1>Generator Iterator Adaptor</h1>
|
||||
Defined in header <a href="../../boost/generator_iterator.hpp">boost/generator_iterator.hpp</a>
|
||||
<p>
|
||||
The generator iterator adaptor makes it easier to create custom input
|
||||
iterators from 0-ary functions and function objects. The adaptor
|
||||
takes a
|
||||
<a href="http://www.sgi.com/tech/stl/Generator.html">Generator</a>
|
||||
and creates a model of
|
||||
<a href="http://www.sgi.com/tech/stl/InputIterator.html">Input Iterator</a>.
|
||||
Each increment retrieves an item from the generator and makes it
|
||||
available to be retrieved by dereferencing. The motivation for this
|
||||
iterator is that some concepts can be more naturally expressed as a
|
||||
generator, while most STL algorithms expect an iterator. An example
|
||||
is the <a href="../random/index.html">Random Number</a> library.
|
||||
|
||||
<h2>Synopsis</h2>
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
namespace boost {
|
||||
template <class Generator>
|
||||
class generator_iterator_policies;
|
||||
|
||||
template <class Generator>
|
||||
class generator_iterator_generator;
|
||||
|
||||
template <class Generator>
|
||||
typename generator_iterator_generator<Generator>::type
|
||||
make_generator_iterator(Generator & gen);
|
||||
}
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<hr>
|
||||
|
||||
<h2>The Generator Iterator Generator Class</h2>
|
||||
|
||||
The class generator_iterator_generator is a helper class whose purpose
|
||||
is to construct a generator iterator type. The template parameter for
|
||||
this class is the Generator function object type that is being
|
||||
wrapped. The generator iterator adaptor only holds a reference (or
|
||||
pointer) to the function object, therefore the function object must
|
||||
outlive the generator iterator adaptor constructed from it.
|
||||
|
||||
<pre>
|
||||
template <class Generator>
|
||||
class generator_iterator_generator
|
||||
{
|
||||
public:
|
||||
typedef <a href="iterator_adaptors.htm#iterator_adaptor">iterator_adaptor</a><...> type; // the resulting generator iterator type
|
||||
}
|
||||
</pre>
|
||||
|
||||
|
||||
<h3>Template Parameters</h3>
|
||||
|
||||
<table border>
|
||||
<tr>
|
||||
<th>Parameter</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><tt><a href="http://www.sgi.com/tech/stl/Generator.html">Generator</a></tt>
|
||||
<td>The generator (0-ary function object) type being
|
||||
wrapped. The return type of the function must be defined as
|
||||
<tt>Generator::result_type</tt>. The function object must be a model
|
||||
of
|
||||
<a href="http://www.sgi.com/tech/stl/Generator.html">Generator</a>.
|
||||
</td>
|
||||
</table>
|
||||
|
||||
<h3>Concept Model</h3>
|
||||
The generator iterator class is a model of
|
||||
<a href="http://www.sgi.com/tech/stl/InputIterator.html">Input Iterator</a>.
|
||||
|
||||
<h3>Members</h3>
|
||||
The generator iterator implements the member functions
|
||||
and operators required of the
|
||||
<a href="http://www.sgi.com/tech/stl/InputIterator.html">Input Iterator</a>
|
||||
concept.
|
||||
|
||||
<br>
|
||||
|
||||
<hr>
|
||||
<h2><a name="make_generator_iterator">The Generator Iterator Object Generator</a></h2>
|
||||
|
||||
The <tt>make_generator_iterator()</tt> function provides a
|
||||
convenient way to create generator iterator objects. The function
|
||||
saves the user the trouble of explicitly writing out the iterator
|
||||
types.
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
template <class Generator>
|
||||
typename generator_iterator_generator<Generator>::type
|
||||
make_function_output_iterator(Generator & gen);
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<hr>
|
||||
|
||||
|
||||
<h3>Example</h3>
|
||||
|
||||
The following program shows how <code>generator_iterator</code>
|
||||
transforms a generator into an input iterator.
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
#include <iostream>
|
||||
#include <boost/generator_iterator.hpp>
|
||||
|
||||
class my_generator
|
||||
{
|
||||
public:
|
||||
typedef int result_type;
|
||||
my_generator() : state(0) { }
|
||||
int operator()() { return ++state; }
|
||||
private:
|
||||
int state;
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
my_generator gen;
|
||||
boost::generator_iterator_generator<my_generator>::type it = boost::make_generator_iterator(gen);
|
||||
for(int i = 0; i < 10; ++i, ++it)
|
||||
std::cout << *it << std::endl;
|
||||
}
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<hr>
|
||||
|
||||
Written by Jens Maurer.
|
||||
|
||||
</body>
|
||||
</html>
|
@ -346,7 +346,7 @@ int main()
|
||||
test_integer<unsigned int>();
|
||||
test_integer<long>();
|
||||
test_integer<unsigned long>();
|
||||
#if defined(ULLONG_MAX) || defined(ULONG_LONG_MAX)
|
||||
#if defined(BOOST_HAS_LONG_LONG)
|
||||
test_integer<long long>();
|
||||
test_integer<unsigned long long>();
|
||||
#endif
|
||||
|
52
include/boost/assert.hpp
Normal file
52
include/boost/assert.hpp
Normal file
@ -0,0 +1,52 @@
|
||||
#ifndef BOOST_ASSERT_HPP_INCLUDED
|
||||
#define BOOST_ASSERT_HPP_INCLUDED
|
||||
|
||||
#if _MSC_VER >= 1020
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
//
|
||||
// boost/assert.hpp
|
||||
//
|
||||
// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
//
|
||||
// When BOOST_DEBUG is not defined, it defaults to 0 (off)
|
||||
// for compatibility with programs that do not expect asserts
|
||||
// in the smart pointer class templates.
|
||||
//
|
||||
// This default may be changed after an initial transition period.
|
||||
//
|
||||
|
||||
#ifndef BOOST_DEBUG
|
||||
#define BOOST_DEBUG 0
|
||||
#endif
|
||||
|
||||
#if BOOST_DEBUG
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#ifndef BOOST_ASSERT
|
||||
|
||||
#include <boost/current_function.hpp>
|
||||
|
||||
bool boost_error(char const * expr, char const * func, char const * file, long line);
|
||||
|
||||
# define BOOST_ASSERT(expr) ((expr) || !boost_error(#expr, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__) || (assert(expr), true))
|
||||
|
||||
#endif // #ifndef BOOST_ASSERT
|
||||
|
||||
#else // #if BOOST_DEBUG
|
||||
|
||||
#undef BOOST_ASSERT
|
||||
#define BOOST_ASSERT(expr) ((void)0)
|
||||
|
||||
#endif // #if BOOST_DEBUG
|
||||
|
||||
#endif // #ifndef BOOST_ASSERT_HPP_INCLUDED
|
60
include/boost/checked_delete.hpp
Normal file
60
include/boost/checked_delete.hpp
Normal file
@ -0,0 +1,60 @@
|
||||
#ifndef BOOST_CHECKED_DELETE_HPP_INCLUDED
|
||||
#define BOOST_CHECKED_DELETE_HPP_INCLUDED
|
||||
|
||||
#if _MSC_VER >= 1020
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
//
|
||||
// boost/checked_delete.hpp
|
||||
//
|
||||
// Copyright (c) 1999, 2000, 2001, 2002 boost.org
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
// verify that types are complete for increased safety
|
||||
|
||||
template< typename T > inline void checked_delete(T * x)
|
||||
{
|
||||
typedef char type_must_be_complete[sizeof(T)];
|
||||
delete x;
|
||||
}
|
||||
|
||||
template< typename T > inline void checked_array_delete(T * x)
|
||||
{
|
||||
typedef char type_must_be_complete[sizeof(T)];
|
||||
delete [] x;
|
||||
}
|
||||
|
||||
template<class T> struct checked_deleter
|
||||
{
|
||||
typedef void result_type;
|
||||
typedef T * argument_type;
|
||||
|
||||
void operator()(T * x)
|
||||
{
|
||||
checked_delete(x);
|
||||
}
|
||||
};
|
||||
|
||||
template<class T> struct checked_array_deleter
|
||||
{
|
||||
typedef void result_type;
|
||||
typedef T * argument_type;
|
||||
|
||||
void operator()(T * x)
|
||||
{
|
||||
checked_array_delete(x);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_CHECKED_DELETE_HPP_INCLUDED
|
56
include/boost/current_function.hpp
Normal file
56
include/boost/current_function.hpp
Normal file
@ -0,0 +1,56 @@
|
||||
#ifndef BOOST_CURRENT_FUNCTION_HPP_INCLUDED
|
||||
#define BOOST_CURRENT_FUNCTION_HPP_INCLUDED
|
||||
|
||||
#if _MSC_VER >= 1020
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
//
|
||||
// boost/current_function.hpp - BOOST_CURRENT_FUNCTION
|
||||
//
|
||||
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
inline void current_function_helper()
|
||||
{
|
||||
|
||||
#if defined(__GNUC__)
|
||||
|
||||
# define BOOST_CURRENT_FUNCTION __PRETTY_FUNCTION__
|
||||
|
||||
#elif defined(__FUNCSIG__)
|
||||
|
||||
# define BOOST_CURRENT_FUNCTION __FUNCSIG__
|
||||
|
||||
#elif defined(__BORLANDC__)
|
||||
|
||||
# define BOOST_CURRENT_FUNCTION __FUNC__
|
||||
|
||||
#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901)
|
||||
|
||||
# define BOOST_CURRENT_FUNCTION __func__
|
||||
|
||||
#else
|
||||
|
||||
# define BOOST_CURRENT_FUNCTION "(unknown)"
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_CURRENT_FUNCTION_HPP_INCLUDED
|
@ -34,20 +34,32 @@ namespace boost{
|
||||
|
||||
namespace detail{
|
||||
|
||||
template <typename T, bool isp, bool b1, bool b2>
|
||||
template <typename T, bool small_>
|
||||
struct ct_imp2
|
||||
{
|
||||
typedef const T& param_type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct ct_imp2<T, true>
|
||||
{
|
||||
typedef const T param_type;
|
||||
};
|
||||
|
||||
template <typename T, bool isp, bool b1>
|
||||
struct ct_imp
|
||||
{
|
||||
typedef const T& param_type;
|
||||
};
|
||||
|
||||
template <typename T, bool isp>
|
||||
struct ct_imp<T, isp, true, true>
|
||||
struct ct_imp<T, isp, true>
|
||||
{
|
||||
typedef T const param_type;
|
||||
typedef typename ct_imp2<T, sizeof(T) <= sizeof(void*)>::param_type param_type;
|
||||
};
|
||||
|
||||
template <typename T, bool b1, bool b2>
|
||||
struct ct_imp<T, true, b1, b2>
|
||||
template <typename T, bool b1>
|
||||
struct ct_imp<T, true, b1>
|
||||
{
|
||||
typedef T const param_type;
|
||||
};
|
||||
@ -67,7 +79,11 @@ public:
|
||||
// however compiler bugs prevent this - instead pass three bool's to
|
||||
// ct_imp<T,bool,bool,bool> and add an extra partial specialisation
|
||||
// of ct_imp to handle the logic. (JM)
|
||||
typedef typename detail::ct_imp<T, ::boost::is_pointer<typename remove_const<T>::type>::value, ::boost::is_arithmetic<typename remove_const<T>::type>::value, sizeof(T) <= sizeof(void*)>::param_type param_type;
|
||||
typedef typename detail::ct_imp<
|
||||
T,
|
||||
::boost::is_pointer<T>::value,
|
||||
::boost::is_arithmetic<T>::value
|
||||
>::param_type param_type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
@ -79,7 +95,7 @@ struct call_traits<T&>
|
||||
typedef T& param_type; // hh removed const
|
||||
};
|
||||
|
||||
#if defined(__BORLANDC__) && (__BORLANDC__ <= 0x551)
|
||||
#if defined(__BORLANDC__) && (__BORLANDC__ <= 0x560)
|
||||
// these are illegal specialisations; cv-qualifies applied to
|
||||
// references have no effect according to [8.3.2p1],
|
||||
// C++ Builder requires them though as it treats cv-qualified
|
||||
@ -109,7 +125,7 @@ struct call_traits<T&const volatile>
|
||||
typedef T& param_type; // hh removed const
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifndef __SUNPRO_CC
|
||||
template <typename T, std::size_t N>
|
||||
struct call_traits<T [N]>
|
||||
{
|
||||
@ -135,6 +151,7 @@ public:
|
||||
typedef const array_type& const_reference;
|
||||
typedef const T* const param_type;
|
||||
};
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
@ -32,6 +32,10 @@
|
||||
namespace boost
|
||||
{
|
||||
|
||||
template <class T1, class T2>
|
||||
class compressed_pair;
|
||||
|
||||
|
||||
// compressed_pair
|
||||
|
||||
namespace details
|
||||
@ -104,10 +108,10 @@ namespace details
|
||||
compressed_pair_imp(first_param_type x, second_param_type y)
|
||||
: first_(x), second_(y) {}
|
||||
|
||||
explicit compressed_pair_imp(first_param_type x)
|
||||
compressed_pair_imp(first_param_type x)
|
||||
: first_(x) {}
|
||||
|
||||
explicit compressed_pair_imp(second_param_type y)
|
||||
compressed_pair_imp(second_param_type y)
|
||||
: second_(y) {}
|
||||
|
||||
first_reference first() {return first_;}
|
||||
@ -116,10 +120,10 @@ namespace details
|
||||
second_reference second() {return second_;}
|
||||
second_const_reference second() const {return second_;}
|
||||
|
||||
void swap(compressed_pair_imp& y)
|
||||
void swap(::boost::compressed_pair<T1, T2>& y)
|
||||
{
|
||||
cp_swap(first_, y.first_);
|
||||
cp_swap(second_, y.second_);
|
||||
cp_swap(first_, y.first());
|
||||
cp_swap(second_, y.second());
|
||||
}
|
||||
private:
|
||||
first_type first_;
|
||||
@ -147,10 +151,10 @@ namespace details
|
||||
compressed_pair_imp(first_param_type x, second_param_type y)
|
||||
: first_type(x), second_(y) {}
|
||||
|
||||
explicit compressed_pair_imp(first_param_type x)
|
||||
compressed_pair_imp(first_param_type x)
|
||||
: first_type(x) {}
|
||||
|
||||
explicit compressed_pair_imp(second_param_type y)
|
||||
compressed_pair_imp(second_param_type y)
|
||||
: second_(y) {}
|
||||
|
||||
first_reference first() {return *this;}
|
||||
@ -159,10 +163,10 @@ namespace details
|
||||
second_reference second() {return second_;}
|
||||
second_const_reference second() const {return second_;}
|
||||
|
||||
void swap(compressed_pair_imp& y)
|
||||
void swap(::boost::compressed_pair<T1,T2>& y)
|
||||
{
|
||||
// no need to swap empty base class:
|
||||
cp_swap(second_, y.second_);
|
||||
cp_swap(second_, y.second());
|
||||
}
|
||||
private:
|
||||
second_type second_;
|
||||
@ -189,10 +193,10 @@ namespace details
|
||||
compressed_pair_imp(first_param_type x, second_param_type y)
|
||||
: second_type(y), first_(x) {}
|
||||
|
||||
explicit compressed_pair_imp(first_param_type x)
|
||||
compressed_pair_imp(first_param_type x)
|
||||
: first_(x) {}
|
||||
|
||||
explicit compressed_pair_imp(second_param_type y)
|
||||
compressed_pair_imp(second_param_type y)
|
||||
: second_type(y) {}
|
||||
|
||||
first_reference first() {return first_;}
|
||||
@ -201,10 +205,10 @@ namespace details
|
||||
second_reference second() {return *this;}
|
||||
second_const_reference second() const {return *this;}
|
||||
|
||||
void swap(compressed_pair_imp& y)
|
||||
void swap(::boost::compressed_pair<T1,T2>& y)
|
||||
{
|
||||
// no need to swap empty base class:
|
||||
cp_swap(first_, y.first_);
|
||||
cp_swap(first_, y.first());
|
||||
}
|
||||
|
||||
private:
|
||||
@ -233,10 +237,10 @@ namespace details
|
||||
compressed_pair_imp(first_param_type x, second_param_type y)
|
||||
: first_type(x), second_type(y) {}
|
||||
|
||||
explicit compressed_pair_imp(first_param_type x)
|
||||
compressed_pair_imp(first_param_type x)
|
||||
: first_type(x) {}
|
||||
|
||||
explicit compressed_pair_imp(second_param_type y)
|
||||
compressed_pair_imp(second_param_type y)
|
||||
: second_type(y) {}
|
||||
|
||||
first_reference first() {return *this;}
|
||||
@ -246,7 +250,7 @@ namespace details
|
||||
second_const_reference second() const {return *this;}
|
||||
//
|
||||
// no need to swap empty bases:
|
||||
void swap(compressed_pair_imp&) {}
|
||||
void swap(::boost::compressed_pair<T1,T2>&) {}
|
||||
};
|
||||
|
||||
// JM
|
||||
@ -272,7 +276,7 @@ namespace details
|
||||
compressed_pair_imp(first_param_type x, second_param_type)
|
||||
: first_type(x) {}
|
||||
|
||||
explicit compressed_pair_imp(first_param_type x)
|
||||
compressed_pair_imp(first_param_type x)
|
||||
: first_type(x) {}
|
||||
|
||||
first_reference first() {return *this;}
|
||||
@ -281,7 +285,7 @@ namespace details
|
||||
second_reference second() {return *this;}
|
||||
second_const_reference second() const {return *this;}
|
||||
|
||||
void swap(compressed_pair_imp&) {}
|
||||
void swap(::boost::compressed_pair<T1,T2>&) {}
|
||||
private:
|
||||
};
|
||||
|
||||
@ -305,7 +309,7 @@ namespace details
|
||||
compressed_pair_imp(first_param_type x, second_param_type y)
|
||||
: first_(x), second_(y) {}
|
||||
|
||||
explicit compressed_pair_imp(first_param_type x)
|
||||
compressed_pair_imp(first_param_type x)
|
||||
: first_(x), second_(x) {}
|
||||
|
||||
first_reference first() {return first_;}
|
||||
@ -314,10 +318,10 @@ namespace details
|
||||
second_reference second() {return second_;}
|
||||
second_const_reference second() const {return second_;}
|
||||
|
||||
void swap(compressed_pair_imp<T1, T2, 5>& y)
|
||||
void swap(::boost::compressed_pair<T1, T2>& y)
|
||||
{
|
||||
cp_swap(first_, y.first_);
|
||||
cp_swap(second_, y.second_);
|
||||
cp_swap(first_, y.first());
|
||||
cp_swap(second_, y.second());
|
||||
}
|
||||
private:
|
||||
first_type first_;
|
||||
@ -401,7 +405,10 @@ public:
|
||||
|
||||
compressed_pair() : base() {}
|
||||
compressed_pair(first_param_type x, second_param_type y) : base(x, y) {}
|
||||
explicit compressed_pair(first_param_type x) : base(x) {}
|
||||
#if !(defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x530))
|
||||
explicit
|
||||
#endif
|
||||
compressed_pair(first_param_type x) : base(x) {}
|
||||
|
||||
first_reference first() {return base::first();}
|
||||
first_const_reference first() const {return base::first();}
|
||||
@ -409,7 +416,7 @@ public:
|
||||
second_reference second() {return base::second();}
|
||||
second_const_reference second() const {return base::second();}
|
||||
|
||||
void swap(compressed_pair& y) { base::swap(y); }
|
||||
void swap(::boost::compressed_pair<T,T>& y) { base::swap(y); }
|
||||
};
|
||||
|
||||
template <class T1, class T2>
|
||||
|
@ -33,7 +33,7 @@
|
||||
|
||||
namespace boost{
|
||||
|
||||
#if defined(BOOST_MSVC6_MEMBER_TEMPLATES) || !defined(BOOST_NO_MEMBER_TEMPLATES)
|
||||
#ifdef BOOST_MSVC6_MEMBER_TEMPLATES
|
||||
//
|
||||
// use member templates to emulate
|
||||
// partial specialisation:
|
||||
@ -64,7 +64,8 @@ struct reference_call_traits
|
||||
typedef T const_reference;
|
||||
typedef T param_type;
|
||||
};
|
||||
template <bool simple, bool reference>
|
||||
|
||||
template <bool pointer, bool arithmetic, bool reference>
|
||||
struct call_traits_chooser
|
||||
{
|
||||
template <class T>
|
||||
@ -73,8 +74,9 @@ struct call_traits_chooser
|
||||
typedef standard_call_traits<T> type;
|
||||
};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct call_traits_chooser<true, false>
|
||||
struct call_traits_chooser<true, false, false>
|
||||
{
|
||||
template <class T>
|
||||
struct rebind
|
||||
@ -82,8 +84,9 @@ struct call_traits_chooser<true, false>
|
||||
typedef simple_call_traits<T> type;
|
||||
};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct call_traits_chooser<false, true>
|
||||
struct call_traits_chooser<false, false, true>
|
||||
{
|
||||
template <class T>
|
||||
struct rebind
|
||||
@ -91,12 +94,50 @@ struct call_traits_chooser<false, true>
|
||||
typedef reference_call_traits<T> type;
|
||||
};
|
||||
};
|
||||
|
||||
template <bool size_is_small>
|
||||
struct call_traits_sizeof_chooser2
|
||||
{
|
||||
template <class T>
|
||||
struct small_rebind
|
||||
{
|
||||
typedef simple_call_traits<T> small_type;
|
||||
};
|
||||
};
|
||||
|
||||
template<>
|
||||
struct call_traits_sizeof_chooser2<false>
|
||||
{
|
||||
template <class T>
|
||||
struct small_rebind
|
||||
{
|
||||
typedef standard_call_traits<T> small_type;
|
||||
};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct call_traits_chooser<false, true, false>
|
||||
{
|
||||
template <class T>
|
||||
struct rebind
|
||||
{
|
||||
enum { sizeof_choice = (sizeof(T) <= sizeof(void*)) };
|
||||
typedef call_traits_sizeof_chooser2<(sizeof(T) <= sizeof(void*))> chooser;
|
||||
typedef typename chooser::template small_rebind<T> bound_type;
|
||||
typedef typename bound_type::small_type type;
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
template <typename T>
|
||||
struct call_traits
|
||||
{
|
||||
private:
|
||||
typedef detail::call_traits_chooser<(is_pointer<T>::value || is_arithmetic<T>::value) && sizeof(T) <= sizeof(void*), is_reference<T>::value> chooser;
|
||||
typedef detail::call_traits_chooser<
|
||||
::boost::is_pointer<T>::value,
|
||||
::boost::is_arithmetic<T>::value,
|
||||
::boost::is_reference<T>::value
|
||||
> chooser;
|
||||
typedef typename chooser::template rebind<T> bound_type;
|
||||
typedef typename bound_type::type call_traits_type;
|
||||
public:
|
||||
|
@ -10,8 +10,8 @@
|
||||
/* Release notes:
|
||||
20 Jan 2001:
|
||||
Fixed obvious bugs (David Abrahams)
|
||||
07 Oct 2000:
|
||||
Added better single argument constructor support.
|
||||
07 Oct 2000:
|
||||
Added better single argument constructor support.
|
||||
03 Oct 2000:
|
||||
Added VC6 support (JM).
|
||||
23rd July 2000:
|
||||
@ -38,7 +38,7 @@
|
||||
|
||||
namespace boost
|
||||
{
|
||||
#if defined(BOOST_MSVC6_MEMBER_TEMPLATES) || !defined(BOOST_NO_MEMBER_TEMPLATES)
|
||||
#ifdef BOOST_MSVC6_MEMBER_TEMPLATES
|
||||
//
|
||||
// use member templates to emulate
|
||||
// partial specialisation. Note that due to
|
||||
@ -168,7 +168,7 @@ public:
|
||||
compressed_pair_1(const ::boost::compressed_pair<T1,T2>& x)
|
||||
: T2(x.second()), _first(x.first()) {}
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300
|
||||
// Total weirdness. If the assignment to _first is moved after
|
||||
// the call to the inherited operator=, then this breaks graph/test/graph.cpp
|
||||
// by way of iterator_adaptor.
|
||||
|
73
include/boost/generator_iterator.hpp
Normal file
73
include/boost/generator_iterator.hpp
Normal file
@ -0,0 +1,73 @@
|
||||
// (C) Copyright Jens Maurer 2001. 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.
|
||||
//
|
||||
// Revision History:
|
||||
|
||||
// 15 Nov 2001 Jens Maurer
|
||||
// created.
|
||||
|
||||
#ifndef BOOST_ITERATOR_ADAPTOR_GENERATOR_ITERATOR_HPP
|
||||
#define BOOST_ITERATOR_ADAPTOR_GENERATOR_ITERATOR_HPP
|
||||
|
||||
#include <boost/iterator_adaptors.hpp>
|
||||
#include <boost/ref.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
template<class Generator>
|
||||
class generator_iterator_policies
|
||||
{
|
||||
public:
|
||||
generator_iterator_policies() { }
|
||||
|
||||
template<class Base>
|
||||
void initialize(Base& base) {
|
||||
m_value = (*base)();
|
||||
}
|
||||
|
||||
// The Iter template argument is necessary for compatibility with a MWCW
|
||||
// bug workaround
|
||||
template <class IteratorAdaptor>
|
||||
void increment(IteratorAdaptor& iter) {
|
||||
m_value = (*iter.base())();
|
||||
}
|
||||
|
||||
template <class IteratorAdaptor>
|
||||
const typename Generator::result_type&
|
||||
dereference(const IteratorAdaptor&) const
|
||||
{ return m_value; }
|
||||
|
||||
template <class IteratorAdaptor1, class IteratorAdaptor2>
|
||||
bool equal(const IteratorAdaptor1& x, const IteratorAdaptor2& y) const
|
||||
{ return x.base() == y.base() &&
|
||||
x.policies().m_value == y.policies().m_value; }
|
||||
|
||||
private:
|
||||
typename Generator::result_type m_value;
|
||||
};
|
||||
|
||||
template<class Generator>
|
||||
struct generator_iterator_generator
|
||||
{
|
||||
typedef iterator_adaptor<Generator*, generator_iterator_policies<Generator>,
|
||||
typename Generator::result_type, const typename Generator::result_type&,
|
||||
const typename Generator::result_type*, std::input_iterator_tag,
|
||||
long> type;
|
||||
};
|
||||
|
||||
template <class Generator>
|
||||
inline typename generator_iterator_generator<Generator>::type
|
||||
make_generator_iterator(Generator & gen)
|
||||
{
|
||||
typedef typename generator_iterator_generator<Generator>::type result_t;
|
||||
return result_t(&gen);
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
|
||||
#endif // BOOST_ITERATOR_ADAPTOR_GENERATOR_ITERATOR_HPP
|
||||
|
@ -9,6 +9,12 @@
|
||||
// See http://www.boost.org for most recent version including documentation.
|
||||
|
||||
// Revision History
|
||||
// 02 Dec 01 Bug fixed in random_access_iteratable. (Helmut Zeisel)
|
||||
// 28 Sep 01 Factored out iterator operator groups. (Daryle Walker)
|
||||
// 27 Aug 01 'left' form for non commutative operators added;
|
||||
// additional classes for groups of related operators added;
|
||||
// workaround for empty base class optimization
|
||||
// bug of GCC 3.0 (Helmut Zeisel)
|
||||
// 25 Jun 01 output_iterator_helper changes: removed default template
|
||||
// parameters, added support for self-proxying, additional
|
||||
// documentation and tests (Aleksey Gurtovoy)
|
||||
@ -81,7 +87,14 @@
|
||||
namespace boost {
|
||||
namespace detail {
|
||||
|
||||
// Helmut Zeisel, empty base class optimization bug with GCC 3.0.0
|
||||
#if defined(__GNUC__) && __GNUC__==3 && __GNUC_MINOR__==0 && __GNU_PATCHLEVEL__==0
|
||||
class empty_base {
|
||||
bool dummy;
|
||||
};
|
||||
#else
|
||||
class empty_base {};
|
||||
#endif
|
||||
|
||||
} // namespace detail
|
||||
} // namespace boost
|
||||
@ -168,6 +181,13 @@ struct subtractable2 : B
|
||||
friend T operator-(T x, const U& y) { return x -= y; }
|
||||
};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||
struct subtractable2_left : B
|
||||
{
|
||||
friend T operator-(const U& x, const T& y)
|
||||
{ T result(x); return result -= y; }
|
||||
};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base>
|
||||
struct subtractable1 : B
|
||||
{
|
||||
@ -180,6 +200,13 @@ struct dividable2 : B
|
||||
friend T operator/(T x, const U& y) { return x /= y; }
|
||||
};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||
struct dividable2_left : B
|
||||
{
|
||||
friend T operator/(const U& x, const T& y)
|
||||
{ T result(x); return result /= y; }
|
||||
};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base>
|
||||
struct dividable1 : B
|
||||
{
|
||||
@ -192,6 +219,13 @@ struct modable2 : B
|
||||
friend T operator%(T x, const U& y) { return x %= y; }
|
||||
};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||
struct modable2_left : B
|
||||
{
|
||||
friend T operator%(const U& x, const T& y)
|
||||
{ T result(x); return result %= y; }
|
||||
};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base>
|
||||
struct modable1 : B
|
||||
{
|
||||
@ -463,12 +497,125 @@ struct shiftable1
|
||||
, right_shiftable1<T, B
|
||||
> > {};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||
struct ring_operators2
|
||||
: additive2<T, U
|
||||
, subtractable2_left<T, U
|
||||
, multipliable2<T, U, B
|
||||
> > > {};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base>
|
||||
struct ring_operators1
|
||||
: additive1<T
|
||||
, multipliable1<T, B
|
||||
> > {};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||
struct ordered_ring_operators2
|
||||
: ring_operators2<T, U
|
||||
, totally_ordered2<T, U, B
|
||||
> > {};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base>
|
||||
struct ordered_ring_operators1
|
||||
: ring_operators1<T
|
||||
, totally_ordered1<T, B
|
||||
> > {};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||
struct field_operators2
|
||||
: ring_operators2<T, U
|
||||
, dividable2<T, U
|
||||
, dividable2_left<T, U, B
|
||||
> > > {};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base>
|
||||
struct field_operators1
|
||||
: ring_operators1<T
|
||||
, dividable1<T, B
|
||||
> > {};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||
struct ordered_field_operators2
|
||||
: field_operators2<T, U
|
||||
, totally_ordered2<T, U, B
|
||||
> > {};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base>
|
||||
struct ordered_field_operators1
|
||||
: field_operators1<T
|
||||
, totally_ordered1<T, B
|
||||
> > {};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||
struct euclidian_ring_operators2
|
||||
: ring_operators2<T, U
|
||||
, dividable2<T, U
|
||||
, dividable2_left<T, U
|
||||
, modable2<T, U
|
||||
, modable2_left<T, U, B
|
||||
> > > > > {};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base>
|
||||
struct euclidian_ring_operators1
|
||||
: ring_operators1<T
|
||||
, dividable1<T
|
||||
, modable1<T, B
|
||||
> > > {};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||
struct ordered_euclidian_ring_operators2
|
||||
: totally_ordered2<T, U
|
||||
, euclidian_ring_operators2<T, U, B
|
||||
> > {};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base>
|
||||
struct ordered_euclidian_ring_operators1
|
||||
: totally_ordered1<T
|
||||
, euclidian_ring_operators1<T, B
|
||||
> > {};
|
||||
|
||||
template <class T, class P, class B = ::boost::detail::empty_base>
|
||||
struct input_iteratable
|
||||
: equality_comparable1<T
|
||||
, incrementable<T
|
||||
, dereferenceable<T, P, B
|
||||
> > > {};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base>
|
||||
struct output_iteratable
|
||||
: incrementable<T, B
|
||||
> {};
|
||||
|
||||
template <class T, class P, class B = ::boost::detail::empty_base>
|
||||
struct forward_iteratable
|
||||
: input_iteratable<T, P, B
|
||||
> {};
|
||||
|
||||
template <class T, class P, class B = ::boost::detail::empty_base>
|
||||
struct bidirectional_iteratable
|
||||
: forward_iteratable<T, P
|
||||
, decrementable<T, B
|
||||
> > {};
|
||||
|
||||
// To avoid repeated derivation from equality_comparable,
|
||||
// which is an indirect base class of bidirectional_iterable,
|
||||
// random_access_iteratable must not be derived from totally_ordered1
|
||||
// but from less_than_comparable1 only. (Helmut Zeisel, 02-Dec-2001)
|
||||
template <class T, class P, class D, class R, class B = ::boost::detail::empty_base>
|
||||
struct random_access_iteratable
|
||||
: bidirectional_iteratable<T, P
|
||||
, less_than_comparable1<T
|
||||
, additive2<T, D
|
||||
, indexable<T, D, R, B
|
||||
> > > > {};
|
||||
|
||||
#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE
|
||||
} // namespace boost
|
||||
#endif // BOOST_NO_OPERATORS_IN_NAMESPACE
|
||||
|
||||
|
||||
// BOOST_IMPORT_TEMPLATE1 .. BOOST_IMPORT_TEMPLATE3 -
|
||||
// BOOST_IMPORT_TEMPLATE1 .. BOOST_IMPORT_TEMPLATE4 -
|
||||
//
|
||||
// When BOOST_NO_OPERATORS_IN_NAMESPACE is defined we need a way to import an
|
||||
// operator template into the boost namespace. BOOST_IMPORT_TEMPLATE1 is used
|
||||
@ -479,6 +626,7 @@ struct shiftable1
|
||||
#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE
|
||||
|
||||
// The template is already in boost so we have nothing to do.
|
||||
# define BOOST_IMPORT_TEMPLATE4(template_name)
|
||||
# define BOOST_IMPORT_TEMPLATE3(template_name)
|
||||
# define BOOST_IMPORT_TEMPLATE2(template_name)
|
||||
# define BOOST_IMPORT_TEMPLATE1(template_name)
|
||||
@ -489,6 +637,7 @@ struct shiftable1
|
||||
|
||||
// Bring the names in with a using-declaration
|
||||
// to avoid stressing the compiler.
|
||||
# define BOOST_IMPORT_TEMPLATE4(template_name) using ::template_name;
|
||||
# define BOOST_IMPORT_TEMPLATE3(template_name) using ::template_name;
|
||||
# define BOOST_IMPORT_TEMPLATE2(template_name) using ::template_name;
|
||||
# define BOOST_IMPORT_TEMPLATE1(template_name) using ::template_name;
|
||||
@ -497,6 +646,10 @@ struct shiftable1
|
||||
|
||||
// Otherwise, because a Borland C++ 5.5 bug prevents a using declaration
|
||||
// from working, we are forced to use inheritance for that compiler.
|
||||
# define BOOST_IMPORT_TEMPLATE4(template_name) \
|
||||
template <class T, class U, class V, class W, class B = ::boost::detail::empty_base> \
|
||||
struct template_name : ::template_name<T, U, V, W, B> {};
|
||||
|
||||
# define BOOST_IMPORT_TEMPLATE3(template_name) \
|
||||
template <class T, class U, class V, class B = ::boost::detail::empty_base> \
|
||||
struct template_name : ::template_name<T, U, V, B> {};
|
||||
@ -542,6 +695,15 @@ template<class T> struct is_chained_base {
|
||||
|
||||
} // namespace boost
|
||||
|
||||
// Import a 4-type-argument operator template into boost (if neccessary) and
|
||||
// provide a specialization of 'is_chained_base<>' for it.
|
||||
# define BOOST_OPERATOR_TEMPLATE4(template_name4) \
|
||||
BOOST_IMPORT_TEMPLATE4(template_name4) \
|
||||
template<class T, class U, class V, class W, class B> \
|
||||
struct is_chained_base< ::boost::template_name4<T, U, V, W, B> > { \
|
||||
typedef ::boost::detail::true_t value; \
|
||||
};
|
||||
|
||||
// Import a 3-type-argument operator template into boost (if neccessary) and
|
||||
// provide a specialization of 'is_chained_base<>' for it.
|
||||
# define BOOST_OPERATOR_TEMPLATE3(template_name3) \
|
||||
@ -610,6 +772,8 @@ BOOST_OPERATOR_TEMPLATE1(template_name##1)
|
||||
|
||||
#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
|
||||
# define BOOST_OPERATOR_TEMPLATE4(template_name4) \
|
||||
BOOST_IMPORT_TEMPLATE4(template_name4)
|
||||
# define BOOST_OPERATOR_TEMPLATE3(template_name3) \
|
||||
BOOST_IMPORT_TEMPLATE3(template_name3)
|
||||
# define BOOST_OPERATOR_TEMPLATE2(template_name2) \
|
||||
@ -632,8 +796,11 @@ BOOST_OPERATOR_TEMPLATE(equality_comparable)
|
||||
BOOST_OPERATOR_TEMPLATE(multipliable)
|
||||
BOOST_OPERATOR_TEMPLATE(addable)
|
||||
BOOST_OPERATOR_TEMPLATE(subtractable)
|
||||
BOOST_OPERATOR_TEMPLATE2(subtractable2_left)
|
||||
BOOST_OPERATOR_TEMPLATE(dividable)
|
||||
BOOST_OPERATOR_TEMPLATE2(dividable2_left)
|
||||
BOOST_OPERATOR_TEMPLATE(modable)
|
||||
BOOST_OPERATOR_TEMPLATE2(modable2_left)
|
||||
BOOST_OPERATOR_TEMPLATE(xorable)
|
||||
BOOST_OPERATOR_TEMPLATE(andable)
|
||||
BOOST_OPERATOR_TEMPLATE(orable)
|
||||
@ -658,14 +825,27 @@ BOOST_OPERATOR_TEMPLATE(integer_arithmetic)
|
||||
BOOST_OPERATOR_TEMPLATE(bitwise)
|
||||
BOOST_OPERATOR_TEMPLATE1(unit_steppable)
|
||||
BOOST_OPERATOR_TEMPLATE(shiftable)
|
||||
BOOST_OPERATOR_TEMPLATE(ring_operators)
|
||||
BOOST_OPERATOR_TEMPLATE(ordered_ring_operators)
|
||||
BOOST_OPERATOR_TEMPLATE(field_operators)
|
||||
BOOST_OPERATOR_TEMPLATE(ordered_field_operators)
|
||||
BOOST_OPERATOR_TEMPLATE(euclidian_ring_operators)
|
||||
BOOST_OPERATOR_TEMPLATE(ordered_euclidian_ring_operators)
|
||||
BOOST_OPERATOR_TEMPLATE2(input_iteratable)
|
||||
BOOST_OPERATOR_TEMPLATE1(output_iteratable)
|
||||
BOOST_OPERATOR_TEMPLATE2(forward_iteratable)
|
||||
BOOST_OPERATOR_TEMPLATE2(bidirectional_iteratable)
|
||||
BOOST_OPERATOR_TEMPLATE4(random_access_iteratable)
|
||||
|
||||
#undef BOOST_OPERATOR_TEMPLATE
|
||||
#undef BOOST_OPERATOR_TEMPLATE4
|
||||
#undef BOOST_OPERATOR_TEMPLATE3
|
||||
#undef BOOST_OPERATOR_TEMPLATE2
|
||||
#undef BOOST_OPERATOR_TEMPLATE1
|
||||
#undef BOOST_IMPORT_TEMPLATE1
|
||||
#undef BOOST_IMPORT_TEMPLATE2
|
||||
#undef BOOST_IMPORT_TEMPLATE3
|
||||
#undef BOOST_IMPORT_TEMPLATE4
|
||||
|
||||
// The following 'operators' classes can only be used portably if the derived class
|
||||
// declares ALL of the required member operators.
|
||||
@ -699,20 +879,18 @@ template <class T,
|
||||
class P = V const *,
|
||||
class R = V const &>
|
||||
struct input_iterator_helper
|
||||
: equality_comparable1<T
|
||||
, incrementable<T
|
||||
, dereferenceable<T, P
|
||||
: input_iteratable<T, P
|
||||
, boost::iterator<std::input_iterator_tag, V, D, P, R
|
||||
> > > > {};
|
||||
> > {};
|
||||
|
||||
template<class Derived>
|
||||
template<class T>
|
||||
struct output_iterator_helper
|
||||
: boost::incrementable<Derived
|
||||
: output_iteratable<T
|
||||
, boost::iterator<std::output_iterator_tag, void, void, void, void
|
||||
> >
|
||||
{
|
||||
Derived& operator*() { return static_cast<Derived&>(*this); }
|
||||
Derived& operator++() { return static_cast<Derived&>(*this); }
|
||||
T& operator*() { return static_cast<T&>(*this); }
|
||||
T& operator++() { return static_cast<T&>(*this); }
|
||||
};
|
||||
|
||||
template <class T,
|
||||
@ -721,11 +899,9 @@ template <class T,
|
||||
class P = V*,
|
||||
class R = V&>
|
||||
struct forward_iterator_helper
|
||||
: equality_comparable1<T
|
||||
, incrementable<T
|
||||
, dereferenceable<T, P
|
||||
: forward_iteratable<T, P
|
||||
, boost::iterator<std::forward_iterator_tag, V, D, P, R
|
||||
> > > > {};
|
||||
> > {};
|
||||
|
||||
template <class T,
|
||||
class V,
|
||||
@ -733,11 +909,9 @@ template <class T,
|
||||
class P = V*,
|
||||
class R = V&>
|
||||
struct bidirectional_iterator_helper
|
||||
: equality_comparable1<T
|
||||
, unit_steppable<T
|
||||
, dereferenceable<T, P
|
||||
: bidirectional_iteratable<T, P
|
||||
, boost::iterator<std::bidirectional_iterator_tag, V, D, P, R
|
||||
> > > > {};
|
||||
> > {};
|
||||
|
||||
template <class T,
|
||||
class V,
|
||||
@ -745,13 +919,9 @@ template <class T,
|
||||
class P = V*,
|
||||
class R = V&>
|
||||
struct random_access_iterator_helper
|
||||
: totally_ordered1<T
|
||||
, unit_steppable<T
|
||||
, dereferenceable<T, P
|
||||
, additive2<T, D
|
||||
, indexable<T, D, R
|
||||
: random_access_iteratable<T, P, D, R
|
||||
, boost::iterator<std::random_access_iterator_tag, V, D, P, R
|
||||
> > > > > >
|
||||
> >
|
||||
{
|
||||
friend D requires_difference_operator(const T& x, const T& y) {
|
||||
return x - y;
|
||||
|
@ -1,16 +1,19 @@
|
||||
#ifndef BOOST_REF_HPP_INCLUDED
|
||||
#define BOOST_REF_HPP_INCLUDED
|
||||
# define BOOST_REF_HPP_INCLUDED
|
||||
|
||||
#if _MSC_VER >= 1020
|
||||
#pragma once
|
||||
#endif
|
||||
# if _MSC_VER+0 >= 1020
|
||||
# pragma once
|
||||
# endif
|
||||
|
||||
# include <boost/config.hpp>
|
||||
# include <boost/utility/addressof.hpp>
|
||||
|
||||
//
|
||||
// ref.hpp - ref/cref, useful helper functions
|
||||
//
|
||||
// Version 1.00.0003 (2001-08-22)
|
||||
//
|
||||
// Copyright (C) 1999, 2000 Jaakko J<>rvi (jaakko.jarvi@cs.utu.fi)
|
||||
// Copyright (C) 2001, 2002 Peter Dimov
|
||||
// Copyright (C) 2002 David Abrahams
|
||||
//
|
||||
// Permission to copy, use, modify, sell and distribute this software
|
||||
// is granted provided this copyright notice appears in all copies.
|
||||
@ -26,30 +29,134 @@ namespace boost
|
||||
template<class T> class reference_wrapper
|
||||
{
|
||||
public:
|
||||
typedef T type;
|
||||
|
||||
explicit reference_wrapper(T & t): t_(t) {}
|
||||
#if defined(BOOST_MSVC) && (BOOST_MSVC < 1300)
|
||||
|
||||
operator T & () const { return t_; }
|
||||
explicit reference_wrapper(T& t): t_(&t) {}
|
||||
|
||||
T & get() const { return t_; }
|
||||
#else
|
||||
|
||||
explicit reference_wrapper(T& t): t_(addressof(t)) {}
|
||||
|
||||
#endif
|
||||
|
||||
operator T& () const { return *t_; }
|
||||
|
||||
T& get() const { return *t_; }
|
||||
|
||||
T* get_pointer() const { return t_; }
|
||||
|
||||
private:
|
||||
|
||||
T & t_;
|
||||
|
||||
reference_wrapper & operator= (reference_wrapper const &);
|
||||
T* t_;
|
||||
};
|
||||
|
||||
template<class T> inline reference_wrapper<T> ref(T & t)
|
||||
# if defined(__BORLANDC__) && (__BORLANDC__ <= 0x570)
|
||||
# define BOOST_REF_CONST
|
||||
# else
|
||||
# define BOOST_REF_CONST const
|
||||
# endif
|
||||
|
||||
template<class T> inline reference_wrapper<T> BOOST_REF_CONST ref(T & t)
|
||||
{
|
||||
return reference_wrapper<T>(t);
|
||||
}
|
||||
|
||||
template<class T> inline reference_wrapper<T const> cref(T const & t)
|
||||
template<class T> inline reference_wrapper<T const> BOOST_REF_CONST cref(T const & t)
|
||||
{
|
||||
return reference_wrapper<T const>(t);
|
||||
}
|
||||
|
||||
# undef BOOST_REF_CONST
|
||||
|
||||
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
template<typename T>
|
||||
class is_reference_wrapper
|
||||
{
|
||||
public:
|
||||
BOOST_STATIC_CONSTANT(bool, value = false);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class is_reference_wrapper<reference_wrapper<T> >
|
||||
{
|
||||
public:
|
||||
BOOST_STATIC_CONSTANT(bool, value = true);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class unwrap_reference
|
||||
{
|
||||
public:
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class unwrap_reference<reference_wrapper<T> >
|
||||
{
|
||||
public:
|
||||
typedef T type;
|
||||
};
|
||||
# else // no partial specialization
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#include <boost/type.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
typedef char (&yes_reference_wrapper_t)[1];
|
||||
typedef char (&no_reference_wrapper_t)[2];
|
||||
|
||||
no_reference_wrapper_t is_reference_wrapper_test(...);
|
||||
|
||||
template<typename T>
|
||||
yes_reference_wrapper_t is_reference_wrapper_test(type< reference_wrapper<T> >);
|
||||
|
||||
template<bool wrapped>
|
||||
struct reference_unwrapper
|
||||
{
|
||||
template <class T>
|
||||
struct apply
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
};
|
||||
|
||||
template<>
|
||||
struct reference_unwrapper<true>
|
||||
{
|
||||
template <class T>
|
||||
struct apply
|
||||
{
|
||||
typedef typename T::type type;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
class is_reference_wrapper
|
||||
{
|
||||
public:
|
||||
BOOST_STATIC_CONSTANT(
|
||||
bool, value = (
|
||||
sizeof(detail::is_reference_wrapper_test(type<T>()))
|
||||
== sizeof(detail::yes_reference_wrapper_t)));
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class unwrap_reference
|
||||
: public detail::reference_unwrapper<
|
||||
is_reference_wrapper<T>::value
|
||||
>::template apply<T>
|
||||
{};
|
||||
|
||||
# endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_REF_HPP_INCLUDED
|
||||
|
@ -13,37 +13,14 @@
|
||||
#ifndef BOOST_UTILITY_HPP
|
||||
#define BOOST_UTILITY_HPP
|
||||
|
||||
#include <boost/config.hpp> // broken compiler workarounds
|
||||
#include <boost/static_assert.hpp>
|
||||
|
||||
// certain headers are part of the <utility.hpp> interface
|
||||
|
||||
#include <boost/checked_delete.hpp>
|
||||
#include <boost/utility/base_from_member.hpp>
|
||||
|
||||
#include <cstddef> // for size_t
|
||||
#include <utility> // for std::pair
|
||||
#include <boost/utility/addressof.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
// checked_delete() and checked_array_delete() -----------------------------//
|
||||
|
||||
// verify that types are complete for increased safety
|
||||
|
||||
template< typename T >
|
||||
inline void checked_delete(T * x)
|
||||
{
|
||||
BOOST_STATIC_ASSERT( sizeof(T) != 0 ); // assert type complete at point
|
||||
// of instantiation
|
||||
delete x;
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
inline void checked_array_delete(T * x)
|
||||
{
|
||||
BOOST_STATIC_ASSERT( sizeof(T) != 0 ); // assert type complete at point
|
||||
// of instantiation
|
||||
delete [] x;
|
||||
}
|
||||
|
||||
// next() and prior() template functions -----------------------------------//
|
||||
|
||||
// Helper functions for classes like bidirectional iterators not supporting
|
||||
|
31
include/boost/utility/addressof.hpp
Normal file
31
include/boost/utility/addressof.hpp
Normal file
@ -0,0 +1,31 @@
|
||||
// Copyright (C) 2002 Brad King (brad.king@kitware.com)
|
||||
// Doug Gregor (gregod@cs.rpi.edu)
|
||||
// Peter Dimov
|
||||
//
|
||||
// Permission to copy, use, sell and distribute this software is granted
|
||||
// provided this copyright notice appears in all copies.
|
||||
// Permission to modify the code and to distribute modified code is granted
|
||||
// provided this copyright notice appears in all copies, and a notice
|
||||
// that the code was modified is included with the copyright notice.
|
||||
//
|
||||
// This software is provided "as is" without express or implied warranty,
|
||||
// and with no claim as to its suitability for any purpose.
|
||||
|
||||
// For more information, see http://www.boost.org
|
||||
|
||||
#ifndef BOOST_UTILITY_ADDRESSOF_HPP
|
||||
#define BOOST_UTILITY_ADDRESSOF_HPP
|
||||
|
||||
namespace boost {
|
||||
|
||||
// Do not make addressof() inline. Breaks MSVC 7. (Peter Dimov)
|
||||
|
||||
template <typename T> T* addressof(T& v)
|
||||
{
|
||||
return reinterpret_cast<T*>(
|
||||
&const_cast<char&>(reinterpret_cast<const volatile char &>(v)));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // BOOST_UTILITY_ADDRESSOF_HPP
|
82
include/boost/utility/value_init.hpp
Normal file
82
include/boost/utility/value_init.hpp
Normal file
@ -0,0 +1,82 @@
|
||||
// (C) 2002, Fernando Luis Cacciola Carballal.
|
||||
//
|
||||
// This material is provided "as is", with absolutely no warranty expressed
|
||||
// or implied. Any use is at your own risk.
|
||||
//
|
||||
// Permission to use or copy this software for any purpose is hereby granted
|
||||
// without fee, provided the above notices are retained on all copies.
|
||||
// Permission to modify the code and to distribute modified code is granted,
|
||||
// provided the above notices are retained, and a notice that the code was
|
||||
// modified is included with the above copyright notice.
|
||||
//
|
||||
// 21 Ago 2002 (Created) Fernando Cacciola
|
||||
//
|
||||
#ifndef BOOST_UTILITY_VALUE_INIT_21AGO2002_HPP
|
||||
#define BOOST_UTILITY_VALUE_INIT_21AGO2002_HPP
|
||||
|
||||
#include "boost/detail/select_type.hpp"
|
||||
#include "boost/type_traits/cv_traits.hpp"
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace vinit_detail {
|
||||
|
||||
template<class T>
|
||||
class const_T_base
|
||||
{
|
||||
protected :
|
||||
|
||||
const_T_base() : x() {}
|
||||
|
||||
T x ;
|
||||
} ;
|
||||
|
||||
template<class T>
|
||||
struct non_const_T_base
|
||||
{
|
||||
protected :
|
||||
|
||||
non_const_T_base() : x() {}
|
||||
|
||||
mutable T x ;
|
||||
} ;
|
||||
|
||||
template<class T>
|
||||
struct select_base
|
||||
{
|
||||
typedef typename
|
||||
detail::if_true< ::boost::is_const<T>::value >
|
||||
::template then< const_T_base<T>, non_const_T_base<T> >::type type ;
|
||||
} ;
|
||||
|
||||
} // namespace vinit_detail
|
||||
|
||||
template<class T>
|
||||
class value_initialized : private vinit_detail::select_base<T>::type
|
||||
{
|
||||
public :
|
||||
|
||||
value_initialized() {}
|
||||
|
||||
operator T&() const { return this->x ; }
|
||||
|
||||
T& data() const { return this->x ; }
|
||||
|
||||
} ;
|
||||
|
||||
template<class T>
|
||||
T const& get ( value_initialized<T> const& x )
|
||||
{
|
||||
return x.data() ;
|
||||
}
|
||||
template<class T>
|
||||
T& get ( value_initialized<T>& x )
|
||||
{
|
||||
return x.data() ;
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -26,12 +26,8 @@ template < typename MemberType, int UniqueID = 0 >
|
||||
|
||||
class noncopyable;
|
||||
|
||||
template < class A, class B >
|
||||
class tied;
|
||||
|
||||
// Also has a few function templates
|
||||
|
||||
|
||||
} // namespace boost
|
||||
|
||||
|
||||
|
34
index.html
Normal file
34
index.html
Normal file
@ -0,0 +1,34 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Language" content="en-us">
|
||||
<meta name="GENERATOR" content="Microsoft FrontPage 5.0">
|
||||
<meta name="ProgId" content="FrontPage.Editor.Document">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
|
||||
<title>Boost Utility Library</title>
|
||||
</head>
|
||||
|
||||
<body bgcolor="#FFFFFF">
|
||||
|
||||
<h1><IMG SRC="../../c++boost.gif" WIDTH="276" HEIGHT="86" align="center">Boost
|
||||
Utility Library</h1>
|
||||
<p>The Boost Utility Library isn't really a single library at all. It is
|
||||
just a collection for components too small to be called libraries in their own
|
||||
right.</p>
|
||||
<p>But that doesn't mean there isn't useful stuff here. Take a look:</p>
|
||||
<blockquote>
|
||||
<p><a href="base_from_member.html">base_from_member</a><br>
|
||||
<a href="call_traits.htm">call_traits.htm</a><br>
|
||||
<a href="compressed_pair.htm">compressed_pair.htm</a><br>
|
||||
<a href="operators.htm">operators.htm</a><br>
|
||||
<a href="tie.html">tie</a><br>
|
||||
<a href="utility.htm">utility.htm</a></p>
|
||||
</blockquote>
|
||||
<hr>
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->07 May, 2002<!--webbot bot="Timestamp" endspan i-checksum="13976" --></p>
|
||||
<p> </p>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
@ -33,8 +33,8 @@ int main(int, char*[])
|
||||
|
||||
char mutable_characters[N];
|
||||
char* pointers_to_mutable_chars[N];
|
||||
for (int i = 0; i < N; ++i)
|
||||
pointers_to_mutable_chars[i] = &mutable_characters[i];
|
||||
for (int j = 0; j < N; ++j)
|
||||
pointers_to_mutable_chars[j] = &mutable_characters[j];
|
||||
|
||||
PairGen::iterator mutable_indirect_first(pointers_to_mutable_chars),
|
||||
mutable_indirect_last(pointers_to_mutable_chars + N);
|
||||
@ -42,19 +42,21 @@ int main(int, char*[])
|
||||
const_indirect_last(pointers_to_chars + N);
|
||||
|
||||
std::transform(const_indirect_first, const_indirect_last,
|
||||
mutable_indirect_first, std::bind1st(std::plus<char>(), 1));
|
||||
mutable_indirect_first, std::bind1st(std::plus<char>(), 1));
|
||||
|
||||
std::copy(mutable_indirect_first, mutable_indirect_last,
|
||||
std::ostream_iterator<char>(std::cout, ","));
|
||||
std::ostream_iterator<char>(std::cout, ","));
|
||||
std::cout << std::endl;
|
||||
|
||||
|
||||
// Example of using make_indirect_iterator()
|
||||
|
||||
#if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
|
||||
std::copy(boost::make_indirect_iterator(pointers_to_chars),
|
||||
boost::make_indirect_iterator(pointers_to_chars + N),
|
||||
std::ostream_iterator<char>(std::cout, ","));
|
||||
boost::make_indirect_iterator(pointers_to_chars + N),
|
||||
std::ostream_iterator<char>(std::cout, ","));
|
||||
std::cout << std::endl;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ typedef std::set<storage::iterator> iterator_set;
|
||||
void more_indirect_iterator_tests()
|
||||
{
|
||||
// For some reason all heck breaks loose in the compiler under these conditions.
|
||||
#if !defined(BOOST_MSVC) || !defined(__STL_DEBUG)
|
||||
#if !defined(BOOST_MSVC) || BOOST_MSVC > 1200 || !defined(__STL_DEBUG)
|
||||
storage store(1000);
|
||||
std::generate(store.begin(), store.end(), rand);
|
||||
|
||||
@ -46,7 +46,7 @@ void more_indirect_iterator_tests()
|
||||
|
||||
typedef boost::indirect_iterator_pair_generator<
|
||||
pointer_deque::iterator
|
||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
#ifdef BOOST_NO_STD_ITERATOR_TRAITS
|
||||
, int
|
||||
#endif
|
||||
> IndirectDeque;
|
||||
@ -75,7 +75,7 @@ void more_indirect_iterator_tests()
|
||||
|
||||
typedef boost::indirect_iterator_generator<
|
||||
iterator_set::iterator
|
||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
#ifdef BOOST_NO_STD_ITERATOR_TRAITS
|
||||
, int
|
||||
#endif
|
||||
>::type indirect_set_iterator;
|
||||
@ -117,7 +117,7 @@ main()
|
||||
ptr[k] = array + k;
|
||||
|
||||
typedef boost::indirect_iterator_generator<dummyT**
|
||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
#ifdef BOOST_NO_STD_ITERATOR_TRAITS
|
||||
, dummyT
|
||||
#endif
|
||||
>::type indirect_iterator;
|
||||
@ -127,7 +127,7 @@ main()
|
||||
indirect_iterator i(ptr);
|
||||
boost::random_access_iterator_test(i, N, array);
|
||||
|
||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
#ifndef BOOST_NO_STD_ITERATOR_TRAITS
|
||||
boost::random_access_iterator_test(boost::make_indirect_iterator(ptr), N, array);
|
||||
#endif
|
||||
|
||||
@ -139,7 +139,7 @@ main()
|
||||
|
||||
dummyT*const* const_ptr = ptr;
|
||||
|
||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
#ifndef BOOST_NO_STD_ITERATOR_TRAITS
|
||||
boost::random_access_iterator_test(boost::make_indirect_iterator(const_ptr), N, array);
|
||||
#endif
|
||||
boost::const_nonconst_iterator_test(i, ++j);
|
||||
|
@ -4,7 +4,9 @@
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
|
||||
// 8 Mar 2001 Jeremy Siek
|
||||
// 04 Nov 2001 Jeremy Siek
|
||||
// Updated with respect to new named parameter interface.
|
||||
// 08 Mar 2001 Jeremy Siek
|
||||
// Initial checkin.
|
||||
|
||||
#include <boost/iterator_adaptors.hpp>
|
||||
@ -19,16 +21,15 @@ main()
|
||||
{
|
||||
using boost::dummyT;
|
||||
dummyT array[] = { dummyT(0), dummyT(1), dummyT(2),
|
||||
dummyT(3), dummyT(4), dummyT(5) };
|
||||
dummyT(3), dummyT(4), dummyT(5) };
|
||||
typedef boost::iterator_adaptor<dummyT*,
|
||||
boost::default_iterator_policies, dummyT> my_iter;
|
||||
my_iter mi(array);
|
||||
|
||||
{
|
||||
typedef boost::iterator_adaptor<my_iter, boost::default_iterator_policies,
|
||||
boost::iterator_traits_generator
|
||||
::reference<dummyT>
|
||||
::iterator_category<std::input_iterator_tag> > iter_type;
|
||||
boost::reference_is<dummyT>,
|
||||
boost::iterator_category_is<std::input_iterator_tag> > iter_type;
|
||||
|
||||
BOOST_STATIC_ASSERT((boost::is_same<iter_type::iterator_category*,
|
||||
std::input_iterator_tag*>::value));
|
||||
@ -42,12 +43,11 @@ main()
|
||||
{
|
||||
typedef boost::iterator_adaptor<dummyT*,
|
||||
boost::default_iterator_policies,
|
||||
boost::iterator_traits_generator
|
||||
::value_type<dummyT>
|
||||
::reference<const dummyT&>
|
||||
::pointer<const dummyT*>
|
||||
::iterator_category<std::forward_iterator_tag>
|
||||
::difference_type<std::ptrdiff_t> > adaptor_type;
|
||||
boost::value_type_is<dummyT>,
|
||||
boost::reference_is<const dummyT&>,
|
||||
boost::pointer_is<const dummyT*> ,
|
||||
boost::iterator_category_is<std::forward_iterator_tag>,
|
||||
boost::difference_type_is<std::ptrdiff_t> > adaptor_type;
|
||||
|
||||
adaptor_type i(array);
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
#include <functional>
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <boost/pending/iterator_adaptors.hpp>
|
||||
#include <boost/iterator_adaptors.hpp>
|
||||
#include <boost/pending/integer_range.hpp>
|
||||
|
||||
int
|
||||
@ -21,8 +21,7 @@ main(int, char*[])
|
||||
int x[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
|
||||
|
||||
typedef std::binder1st< std::multiplies<int> > Function;
|
||||
typedef boost::transform_iterator<Function, int*,
|
||||
boost::iterator<std::random_access_iterator_tag, int>
|
||||
typedef boost::transform_iterator_generator<Function, int*
|
||||
>::type doubling_iterator;
|
||||
|
||||
doubling_iterator i(x, std::bind1st(std::multiplies<int>(), 2)),
|
||||
|
@ -9,6 +9,10 @@
|
||||
// See http://www.boost.org for most recent version including documentation.
|
||||
|
||||
// Revision History
|
||||
// 30 Nov 01 Added permutation_iterator.(Toon Knapen)
|
||||
// 19 Nov 01 Added generator_iterator. (Jens Maurer)
|
||||
// 04 Nov 01 Updated with respect to change in named parameters.
|
||||
// (Jeremy Siek)
|
||||
// 08 Mar 01 Moved indirect and transform tests to separate files.
|
||||
// (Jeremy Siek)
|
||||
// 19 Feb 01 Take adavantage of improved iterator_traits to do more tests
|
||||
@ -47,15 +51,20 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <numeric>
|
||||
|
||||
#include <boost/iterator_adaptors.hpp>
|
||||
#include <boost/generator_iterator.hpp>
|
||||
#include <boost/pending/iterator_tests.hpp>
|
||||
#include <boost/pending/integer_range.hpp>
|
||||
#include <boost/concept_archetype.hpp>
|
||||
#include <boost/type_traits/same_traits.hpp>
|
||||
#include <boost/permutation_iterator.hpp>
|
||||
#include <stdlib.h>
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
#include <set>
|
||||
#include <list>
|
||||
|
||||
struct my_iterator_tag : public std::random_access_iterator_tag { };
|
||||
|
||||
@ -97,6 +106,18 @@ typedef std::deque<int> storage;
|
||||
typedef std::deque<int*> pointer_deque;
|
||||
typedef std::set<storage::iterator> iterator_set;
|
||||
|
||||
template <class T> struct foo;
|
||||
|
||||
void blah(int) { }
|
||||
|
||||
struct my_gen
|
||||
{
|
||||
typedef int result_type;
|
||||
my_gen() : n(0) { }
|
||||
int operator()() { return ++n; }
|
||||
int n;
|
||||
};
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
@ -105,17 +126,61 @@ main()
|
||||
const int N = sizeof(array)/sizeof(dummyT);
|
||||
|
||||
// sanity check, if this doesn't pass the test is buggy
|
||||
boost::random_access_iterator_test(array,N,array);
|
||||
boost::random_access_iterator_test(array, N, array);
|
||||
|
||||
// Check that the policy concept checks and the default policy
|
||||
// implementation match up.
|
||||
boost::function_requires<
|
||||
boost::RandomAccessIteratorPoliciesConcept<
|
||||
boost::default_iterator_policies, int*,
|
||||
boost::default_iterator_policies,
|
||||
boost::iterator_adaptor<storage::iterator, boost::default_iterator_policies>,
|
||||
boost::iterator<std::random_access_iterator_tag, int, std::ptrdiff_t,
|
||||
int*, int&>
|
||||
> >();
|
||||
|
||||
// Test the named parameters
|
||||
{
|
||||
// Test computation of defaults
|
||||
typedef boost::iterator_adaptor<int*, boost::default_iterator_policies,
|
||||
boost::value_type_is<int> > Iter1;
|
||||
// don't use std::iterator_traits here to avoid VC++ problems
|
||||
BOOST_STATIC_ASSERT((boost::is_same<Iter1::value_type, int>::value));
|
||||
BOOST_STATIC_ASSERT((boost::is_same<Iter1::reference, int&>::value));
|
||||
BOOST_STATIC_ASSERT((boost::is_same<Iter1::pointer, int*>::value));
|
||||
BOOST_STATIC_ASSERT((boost::is_same<Iter1::difference_type, std::ptrdiff_t>::value));
|
||||
BOOST_STATIC_ASSERT((boost::is_same<Iter1::iterator_category, std::random_access_iterator_tag>::value));
|
||||
}
|
||||
{
|
||||
// Test computation of default when the Value is const
|
||||
typedef boost::iterator_adaptor<std::list<int>::iterator,
|
||||
boost::default_iterator_policies,
|
||||
boost::value_type_is<const int> > Iter1;
|
||||
BOOST_STATIC_ASSERT((boost::is_same<Iter1::value_type, int>::value));
|
||||
#if defined(__BORLANDC__) || defined(BOOST_MSVC) && BOOST_MSVC <= 1300
|
||||
// We currently don't know how to workaround this bug.
|
||||
BOOST_STATIC_ASSERT((boost::is_same<Iter1::reference, int&>::value));
|
||||
BOOST_STATIC_ASSERT((boost::is_same<Iter1::pointer, int*>::value));
|
||||
#else
|
||||
BOOST_STATIC_ASSERT((boost::is_same<Iter1::reference, const int&>::value));
|
||||
BOOST_STATIC_ASSERT((boost::is_same<Iter1::pointer, const int*>::value));
|
||||
#endif
|
||||
}
|
||||
{
|
||||
// Test with no defaults
|
||||
typedef boost::iterator_adaptor<int*, boost::default_iterator_policies,
|
||||
boost::reference_is<long>,
|
||||
boost::pointer_is<float*>,
|
||||
boost::value_type_is<char>,
|
||||
boost::iterator_category_is<std::input_iterator_tag>,
|
||||
boost::difference_type_is<int>
|
||||
> Iter1;
|
||||
BOOST_STATIC_ASSERT((boost::is_same<Iter1::value_type, char>::value));
|
||||
BOOST_STATIC_ASSERT((boost::is_same<Iter1::reference, long>::value));
|
||||
BOOST_STATIC_ASSERT((boost::is_same<Iter1::pointer, float*>::value));
|
||||
BOOST_STATIC_ASSERT((boost::is_same<Iter1::difference_type, int>::value));
|
||||
BOOST_STATIC_ASSERT((boost::is_same<Iter1::iterator_category, std::input_iterator_tag>::value));
|
||||
}
|
||||
|
||||
// Test the iterator_adaptor
|
||||
{
|
||||
boost::iterator_adaptor<dummyT*, boost::default_iterator_policies, dummyT> i(array);
|
||||
@ -159,7 +224,7 @@ main()
|
||||
std::reverse(reversed, reversed + N);
|
||||
|
||||
typedef boost::reverse_iterator_generator<dummyT*
|
||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) || defined(BOOST_NO_STD_ITERATOR_TRAITS)
|
||||
, dummyT
|
||||
#endif
|
||||
>::type reverse_iterator;
|
||||
@ -167,13 +232,13 @@ main()
|
||||
reverse_iterator i(reversed + N);
|
||||
boost::random_access_iterator_test(i, N, array);
|
||||
|
||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_NO_STD_ITERATOR_TRAITS)
|
||||
boost::random_access_iterator_test(boost::make_reverse_iterator(reversed + N), N, array);
|
||||
#endif
|
||||
|
||||
typedef boost::reverse_iterator_generator<const dummyT*
|
||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
, const dummyT
|
||||
#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) || defined(BOOST_NO_STD_ITERATOR_TRAITS)
|
||||
, dummyT, const dummyT&, const dummyT
|
||||
#endif
|
||||
>::type const_reverse_iterator;
|
||||
|
||||
@ -182,7 +247,7 @@ main()
|
||||
|
||||
const dummyT* const_reversed = reversed;
|
||||
|
||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_NO_STD_ITERATOR_TRAITS)
|
||||
boost::random_access_iterator_test(boost::make_reverse_iterator(const_reversed + N), N, array);
|
||||
#endif
|
||||
|
||||
@ -217,7 +282,7 @@ main()
|
||||
|
||||
// Many compilers' builtin deque iterators don't interoperate well, though
|
||||
// STLport fixes that problem.
|
||||
#if defined(__SGI_STL_PORT) || !defined(__GNUC__) && !defined(__BORLANDC__) && !defined(BOOST_MSVC)
|
||||
#if defined(__SGI_STL_PORT) || !defined(__GNUC__) && !defined(__BORLANDC__) && (!defined(BOOST_MSVC) || BOOST_MSVC > 1200)
|
||||
boost::const_nonconst_iterator_test(i, ++j);
|
||||
#endif
|
||||
}
|
||||
@ -235,7 +300,7 @@ main()
|
||||
typedef boost::detail::non_bidirectional_category<dummyT*>::type category;
|
||||
|
||||
typedef boost::filter_iterator_generator<one_or_four, dummyT*
|
||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) || defined(BOOST_NO_STD_ITERATOR_TRAITS)
|
||||
, dummyT
|
||||
#endif
|
||||
>::type filter_iter;
|
||||
@ -244,8 +309,8 @@ main()
|
||||
// Borland is choking on accessing the policies_type explicitly
|
||||
// from the filter_iter.
|
||||
boost::forward_iterator_test(make_filter_iterator(array, array+N,
|
||||
one_or_four()),
|
||||
dummyT(1), dummyT(4));
|
||||
one_or_four()),
|
||||
dummyT(1), dummyT(4));
|
||||
#else
|
||||
filter_iter i(array, filter_iter::policies_type(one_or_four(), array + N));
|
||||
boost::forward_iterator_test(i, dummyT(1), dummyT(4));
|
||||
@ -262,7 +327,7 @@ main()
|
||||
// On compilers not supporting partial specialization, we can do more type
|
||||
// deduction with deque iterators than with pointers... unless the library
|
||||
// is broken ;-(
|
||||
#if !defined(BOOST_MSVC) || defined(__SGI_STL_PORT)
|
||||
#if !defined(BOOST_MSVC) || BOOST_MSVC > 1200 || defined(__SGI_STL_PORT)
|
||||
std::deque<dummyT> array2;
|
||||
std::copy(array+0, array+N, std::back_inserter(array2));
|
||||
boost::forward_iterator_test(
|
||||
@ -274,7 +339,7 @@ main()
|
||||
dummyT(1), dummyT(4));
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_MSVC) // This just freaks MSVC out completely
|
||||
#if !defined(BOOST_MSVC) || BOOST_MSVC > 1200 // This just freaks MSVC out completely
|
||||
boost::forward_iterator_test(
|
||||
boost::make_filter_iterator<one_or_four>(
|
||||
boost::make_reverse_iterator(array2.end()),
|
||||
@ -283,7 +348,7 @@ main()
|
||||
dummyT(4), dummyT(1));
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_NO_STD_ITERATOR_TRAITS)
|
||||
boost::forward_iterator_test(
|
||||
boost::make_filter_iterator(array+0, array+N, one_or_four()),
|
||||
dummyT(1), dummyT(4));
|
||||
@ -306,12 +371,12 @@ main()
|
||||
#else
|
||||
typedef boost::iterator_adaptor<boost::forward_iterator_archetype<dummyT>,
|
||||
boost::default_iterator_policies,
|
||||
boost::iterator_traits_generator
|
||||
::value_type<dummyT>
|
||||
::reference<const dummyT&>
|
||||
::pointer<const dummyT*>
|
||||
::iterator_category<std::forward_iterator_tag>
|
||||
::difference_type<std::ptrdiff_t> > adaptor_type;
|
||||
boost::reference_is<const dummyT&>,
|
||||
boost::pointer_is<const dummyT*> ,
|
||||
boost::iterator_category_is<std::forward_iterator_tag>,
|
||||
boost::value_type_is<dummyT>,
|
||||
boost::difference_type_is<std::ptrdiff_t>
|
||||
> adaptor_type;
|
||||
#endif
|
||||
adaptor_type i(forward_iter);
|
||||
int zero = 0;
|
||||
@ -330,6 +395,55 @@ main()
|
||||
if (zero) // don't do this, just make sure it compiles
|
||||
assert((*i).m_x == i->foo());
|
||||
}
|
||||
|
||||
{
|
||||
// check generator_iterator
|
||||
my_gen g1;
|
||||
boost::generator_iterator_generator<my_gen>::type gen =
|
||||
boost::make_generator_iterator(g1);
|
||||
assert(*gen == 1);
|
||||
++gen;
|
||||
gen++;
|
||||
assert(*gen == 3);
|
||||
}
|
||||
|
||||
{
|
||||
// check permutation_iterator
|
||||
typedef std::deque< int > element_range_type;
|
||||
typedef std::list< int > index_type;
|
||||
|
||||
static const int element_range_size = 10;
|
||||
static const int index_size = 4;
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
index_type indices( index_size );
|
||||
|
||||
for(index_type::iterator i_it = indices.begin();
|
||||
i_it != indices.end();
|
||||
++i_it)
|
||||
{
|
||||
*i_it = element_range_size - index_size
|
||||
+ std::distance(indices.begin(), i_it );
|
||||
}
|
||||
|
||||
std::reverse( indices.begin(), indices.end() );
|
||||
|
||||
typedef boost::permutation_iterator_generator< element_range_type::iterator, index_type::iterator >::type permutation_type;
|
||||
permutation_type begin = boost::make_permutation_iterator( elements.begin(), indices.begin() );
|
||||
permutation_type end = boost::make_permutation_iterator( elements.begin(), indices.end() );
|
||||
|
||||
int expected_outcome[] = { 9, 8, 7, 6 };
|
||||
assert( std::equal( begin, end, expected_outcome ) );
|
||||
}
|
||||
|
||||
std::cout << "test successful " << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
@ -26,6 +26,37 @@
|
||||
"../../more/generic_programming.html#adaptors">adaptors</a> which apply
|
||||
specific useful behaviors to arbitrary base iterators.
|
||||
|
||||
<h2>Backward Compatibility Note</h2>
|
||||
|
||||
<p>The library's interface has changed since it was first released, breaking
|
||||
backward compatibility:
|
||||
|
||||
<ol>
|
||||
|
||||
<li><a href="#policies">Policies classes</a> now operate on instances of the
|
||||
whole <tt>iterator_adaptor</tt> object, rather than just operating on the
|
||||
<tt>Base</tt> object. This change not only gives the policies class access
|
||||
to both members of a pair of interacting iterators, but also eliminates the
|
||||
need for the ugly <tt>type<Reference></tt> and
|
||||
<tt>type<Difference></tt> parameters to various policy functions.
|
||||
|
||||
<li>The <a href="#named_template_parameters">Named Template Parameter</a>
|
||||
interface has been made simpler, easier to use, and compatible with more
|
||||
compilers.
|
||||
|
||||
</ol>
|
||||
|
||||
<h2>Other Documentation</h2>
|
||||
|
||||
<p><a href="iterator_adaptors.pdf">``Policy Adaptors and the Boost Iterator
|
||||
Adaptor Library''</a> is a technical paper describing this library and the
|
||||
powerful design pattern on which it is based. It was presented at the <a
|
||||
href="http://www.oonumerics.org/tmpw01">C++ Template Workshop</a> at OOPSLA
|
||||
2001; the slides from the talk are available <a
|
||||
href="iterator_adaptors.ppt">here</a>. Please note that while the slides
|
||||
incorporate the minor interface changes described in the previous section,
|
||||
the paper does not.
|
||||
|
||||
<h2>Table of Contents</h2>
|
||||
|
||||
<ul>
|
||||
@ -61,6 +92,8 @@
|
||||
|
||||
<li><a href="#declaration_synopsis">Declaration Synopsis</a>
|
||||
|
||||
<li><a href="#portability">Portability</a>
|
||||
|
||||
<li><a href="#notes">Notes</a>
|
||||
</ul>
|
||||
|
||||
@ -91,6 +124,12 @@
|
||||
"../../boost/function_output_iterator.hpp">boost/function_output_iterator.hpp</a></tt><br>
|
||||
|
||||
<a href="function_output_iterator.htm">Function Output Iterator Adaptor</a>
|
||||
<li>Header <tt><a href="../../boost/generator_iterator.hpp">boost/generator_iterator.hpp</a></tt><br>
|
||||
<a href="generator_iterator.htm">Generator Iterator Adaptor</a>
|
||||
<li>Header <tt><a href="../../boost/permutation_iterator.hpp">boost/permutation_iterator.hpp</a></tt><br>
|
||||
<a href="permutation_iterator.htm">Permutation Iterator Adaptor</a>
|
||||
<li>Header <tt><a href="../../boost/shared_container_iterator.hpp">boost/shared_container_iterator.hpp</a></tt><br>
|
||||
<a href="shared_container_iterator.html">Shared_Container Iterator Adaptor</a>
|
||||
</ul>
|
||||
|
||||
<p><b><a href="../../people/dave_abrahams.htm">Dave
|
||||
@ -114,7 +153,14 @@
|
||||
"filter_iterator.htm">filter_</a></tt> iterator generators and made some
|
||||
simplifications to the main <tt><a href=
|
||||
"#iterator_adaptor">iterator_adaptor</a></tt> template.<br>
|
||||
|
||||
<b><a href="../../people/jens_maurer.htm">Jens Maurer</a></b>
|
||||
contributed the <a href="generator_iterator.htm">generator iterator</a>
|
||||
adaptor.<br>
|
||||
Toon Knapen contributed the <a href="permutation_iterator.htm">permutation
|
||||
iterator</a> adaptor.<br>
|
||||
<b><a href="../../people/ronald_garcia.htm">Ronald Garcia</a></b>
|
||||
contributed the <a href="shared_container_iterator.html">shared container iterator</a>
|
||||
adaptor.<br>
|
||||
|
||||
<h2><a name="iterator_adaptor">Class template</a>
|
||||
<tt>iterator_adaptor</tt></h2>
|
||||
@ -131,11 +177,11 @@
|
||||
<p><tt>iterator_adaptor</tt> is declared like this:
|
||||
<pre>
|
||||
template <class Base, class Policies,
|
||||
class ValueOrNamedParams = typename std::iterator_traits<Base>::value_type,
|
||||
class ReferenceOrNamedParams = <i>...(see below)</i>,
|
||||
class PointerOrNamedParams = <i>...(see below)</i>,
|
||||
class CategoryOrNamedParams = typename std::iterator_traits<Base>::iterator_category,
|
||||
class DistanceOrNamedParams = typename std::iterator_traits<Base>::difference_type>
|
||||
class ValueOrNamedParam = typename std::iterator_traits<Base>::value_type,
|
||||
class ReferenceOrNamedParam = <i>...(see below)</i>,
|
||||
class PointerOrNamedParam = <i>...(see below)</i>,
|
||||
class CategoryOrNamedParam = typename std::iterator_traits<Base>::iterator_category,
|
||||
class DistanceOrNamedParam = typename std::iterator_traits<Base>::difference_type>
|
||||
struct iterator_adaptor;
|
||||
</pre>
|
||||
|
||||
@ -143,7 +189,7 @@ struct iterator_adaptor;
|
||||
|
||||
<p>Although <tt>iterator_adaptor</tt> takes seven template parameters,
|
||||
defaults have been carefully chosen to minimize the number of parameters
|
||||
you must supply in most cases, especially if <tt>BaseType</tt> is an
|
||||
you must supply in most cases, especially if <tt>Base</tt> is an
|
||||
iterator.
|
||||
|
||||
<table border="1" summary="iterator_adaptor template parameters">
|
||||
@ -152,17 +198,26 @@ struct iterator_adaptor;
|
||||
|
||||
<th>Description
|
||||
|
||||
<tr>
|
||||
<td><tt>BaseType</tt>
|
||||
<th>Requirements
|
||||
|
||||
<td>The type being wrapped.
|
||||
<tr>
|
||||
<td><tt>Base</tt>
|
||||
|
||||
<td>The data type on which the resulting iterator is based. Do
|
||||
not be misled by the name "Base": this is not a base
|
||||
class.
|
||||
|
||||
<td>
|
||||
<a href="http://www.sgi.com/tech/stl/Assignable.html">Assignable</a>,
|
||||
<a href="http://www.sgi.com/tech/stl/DefaultConstructible.html">Default Constructible</a>
|
||||
|
||||
<tr>
|
||||
<td><tt>Policies</tt>
|
||||
|
||||
<td>A <a href="../../more/generic_programming.html#policy">policy
|
||||
class</a> that supplies core functionality to the resulting iterator. A
|
||||
detailed description can be found <a href="#policies">below</a>.
|
||||
class</a> that supplies core functionality to the resulting iterator.
|
||||
|
||||
<td>See table <a href="#policies">below</a>.
|
||||
|
||||
<tr>
|
||||
<td><tt>Value</tt>
|
||||
@ -173,7 +228,7 @@ struct iterator_adaptor;
|
||||
"#1">[1]</a>. If the <tt>value_type</tt> you wish to use is an abstract
|
||||
base class see note <a href="#5">[5]</a>.<br>
|
||||
<b>Default:</b>
|
||||
<tt>std::iterator_traits<BaseType>::value_type</tt> <a href=
|
||||
<tt>std::iterator_traits<Base>::value_type</tt> <a href=
|
||||
"#2">[2]</a>
|
||||
|
||||
<tr>
|
||||
@ -183,36 +238,57 @@ struct iterator_adaptor;
|
||||
particular, the result type of <tt>operator*()</tt>.<br>
|
||||
<b>Default:</b> If <tt>Value</tt> is supplied, <tt>Value&</tt> is
|
||||
used. Otherwise
|
||||
<tt>std::iterator_traits<BaseType>::reference</tt> is used.
|
||||
<tt>std::iterator_traits<Base>::reference</tt> is used. <a href="#7">[7]</a>
|
||||
|
||||
<td><a
|
||||
href="http://www.sgi.com/tech/stl/ForwardIterator.html">ForwardIterators</a>,
|
||||
<a
|
||||
href="http://www.sgi.com/tech/stl/BidirectionalIterator.html">BidirectionalIterators</a>,
|
||||
and <a
|
||||
href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">RandomAccessIterators</a>
|
||||
require that Reference is a true reference type (e.g. not a proxy).
|
||||
|
||||
<tr>
|
||||
<td><tt>Pointer</tt>
|
||||
|
||||
<td>The <tt>pointer</tt> type of the resulting iterator, and in
|
||||
particular, the result type of <tt>operator->()</tt>.<br>
|
||||
<b>Default:</b> If <tt>Value</tt> was supplied, then <tt>Value*</tt>,
|
||||
otherwise <tt>std::iterator_traits<BaseType>::pointer</tt>.
|
||||
<b>Default:</b> If <tt>Value</tt> was not supplied, <tt>std::iterator_traits<Base>::pointer</tt>. <a
|
||||
href="#7">[7]</a> Otherwise, if <code>iterator_category</code> is
|
||||
<code>input_iterator</code>, then a class yielding
|
||||
<tt>Value*</tt> when <code>operator->()</code> is applied.
|
||||
Otherwise, <tt>Value*</tt>.
|
||||
|
||||
<td><code>value_type*</code> or a
|
||||
class which yields <code>value_type*</code> when
|
||||
<code>operator->()</code> is applied.
|
||||
|
||||
<tr>
|
||||
<td><tt>Category</tt>
|
||||
|
||||
<td>The <tt>iterator_category</tt> type for the resulting iterator.<br>
|
||||
<b>Default:</b>
|
||||
<tt>std::iterator_traits<BaseType>::iterator_category</tt>
|
||||
<tt>std::iterator_traits<Base>::iterator_category</tt>
|
||||
|
||||
<td>One of
|
||||
<code>std::input_iterator_tag</code>,
|
||||
<code>std::output_iterator_tag</code>,
|
||||
<code>std::forward_iterator_tag</code>,
|
||||
<code>std::bidirectional_iterator_tag</code>, or
|
||||
<code>std::random_access_iterator_tag</code>.
|
||||
|
||||
<tr>
|
||||
<td><tt>Distance</tt>
|
||||
|
||||
<td>The <tt>difference_type</tt> for the resulting iterator.<br>
|
||||
<b>Default:</b>
|
||||
<tt>std::iterator_traits<BaseType>::difference_type</tt>
|
||||
<tt>std::iterator_traits<Base>::difference_type</tt>
|
||||
<td>A signed integral type
|
||||
|
||||
<tr>
|
||||
<td><tt>NamedParams</tt>
|
||||
<td><tt>NamedParam</tt>
|
||||
|
||||
<td>A list of named template parameters generated using the
|
||||
<a href="#iterator_traits_generator">
|
||||
<tt>iterator_traits_generator</tt></a> class (see below).
|
||||
<td>A named template parameter (see below).
|
||||
</table>
|
||||
|
||||
<h3><a name="named_template_parameters">Named Template Parameters</a></h3>
|
||||
@ -223,59 +299,32 @@ struct iterator_adaptor;
|
||||
template parameter, but use the defaults for the third through
|
||||
fifth. As a solution to these problems we provide a mechanism for
|
||||
naming the last five template parameters, and providing them in
|
||||
any order through the <tt>iterator_traits_generator</tt> class.
|
||||
|
||||
any order through a set of named template parameters. The following
|
||||
classes are provided for specifying the parameters. Any of these
|
||||
classes can be used for any of the last five template parameters
|
||||
of <tt>iterator_adaptor</tt>.
|
||||
<blockquote>
|
||||
<pre>
|
||||
<a name="iterator_traits_generator">class iterator_traits_generator</a>
|
||||
{
|
||||
public:
|
||||
template <class Value>
|
||||
struct value_type : public <i>recursive magic</i> { };
|
||||
|
||||
template <class Reference>
|
||||
struct reference : public <i>recursive magic</i> { };
|
||||
|
||||
template <class Pointer>
|
||||
struct pointer : public <i>recursive magic</i> { };
|
||||
|
||||
template <class Distance>
|
||||
struct difference_type : public <i>recursive magic</i> { };
|
||||
|
||||
template <class Category>
|
||||
struct iterator_category : public <i>recursive magic</i> { };
|
||||
};
|
||||
template <class Value> struct value_type_is;
|
||||
template <class Reference> struct reference_is;
|
||||
template <class Pointer> struct pointer_is;
|
||||
template <class Distance> struct difference_type_is;
|
||||
template <class Category> struct iterator_category_is;
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
The <tt>iterator_traits_generator</tt> is used to create a list of
|
||||
of template arguments. For example, suppose you want to set the
|
||||
<tt>Reference</tt> and <tt>Category</tt> parameters, and use the
|
||||
defaults for the rest. Then you can use the traits generator as
|
||||
follows:
|
||||
For example, the following adapts <tt>foo_iterator</tt> to create
|
||||
an <a href=
|
||||
"http://www.sgi.com/tech/stl/InputIterator.html">InputIterator</a>
|
||||
with <tt>reference</tt> type <tt>foo</tt>, and whose other traits
|
||||
are determined according to the defaults described <a
|
||||
href="#template_parameters">above</a>.
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
iterator_traits_generator::reference<foo>::category<std::input_iterator_tag>
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
This generated type can then be passed into the <tt>iterator_adaptor</tt>
|
||||
class to replace any of the last five parameters. If you use the traits
|
||||
generator in the <i>i</i>th parameter position, then the parameters <i>i</i>
|
||||
through 7 will use the types specified in the generator. For example, the
|
||||
following adapts <tt>foo_iterator</tt> to create an <a href=
|
||||
"http://www.sgi.com/tech/stl/InputIterator.html">InputIterator</a> with
|
||||
<tt>reference</tt> type <tt>foo</tt>, and whose other traits are determined
|
||||
according to the defaults described <a href="#template_parameters">above</a>.
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
iterator_adaptor<foo_iterator, foo_policies,
|
||||
iterator_traits_generator
|
||||
::reference<foo>
|
||||
::iterator_category<std::input_iterator_tag>
|
||||
>
|
||||
typedef iterator_adaptor<foo_iterator, foo_policies,
|
||||
reference_is<foo>, iterator_category_is<std::input_iterator_tag>
|
||||
> MyIterator;
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
@ -297,12 +346,16 @@ iterator_adaptor<foo_iterator, foo_policies,
|
||||
|
||||
<table border="1" summary="iterator_adaptor Policies operations">
|
||||
<caption>
|
||||
<b>Core Iterator Operations</b><br>
|
||||
<tt>T</tt>: adapted iterator type; <tt>p</tt>: object of type T; <tt>n</tt>: <tt>T::size_type</tt>; <tt>x</tt>: <tt>T::difference_type</tt>; <tt>p1</tt>, <tt>p2</tt>: iterators
|
||||
<b>Policies Class Requirements</b><br>
|
||||
<tt><b>T</b></tt>: adapted iterator type; <tt><b>x, y</b></tt>: objects of type
|
||||
T; <tt><b>p</b></tt>: <tt>T::policies_type</tt>
|
||||
<tt><b>d</b></tt>:
|
||||
<tt>T::difference_type</tt>; <tt><b>i1</b></tt>, <tt><b>i2</b></tt>:
|
||||
<tt>T::base_type</tt>
|
||||
</caption>
|
||||
|
||||
<tr>
|
||||
<th>Operation
|
||||
<th>Expression
|
||||
|
||||
<th>Effects
|
||||
|
||||
@ -311,7 +364,7 @@ iterator_adaptor<foo_iterator, foo_policies,
|
||||
<th>Required for Iterator Categories
|
||||
|
||||
<tr>
|
||||
<td><tt>initialize</tt>
|
||||
<td nowrap><tt>p.initialize(b)</tt>
|
||||
|
||||
<td>optionally modify base iterator during iterator construction
|
||||
|
||||
@ -323,79 +376,66 @@ iterator_adaptor<foo_iterator, foo_policies,
|
||||
"http://www.sgi.com/tech/stl/ForwardIterator.html">Forward</a>/ <a
|
||||
href=
|
||||
"http://www.sgi.com/tech/stl/BidirectionalIterator.html">Bidirectional</a>/
|
||||
<a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random
|
||||
Access</a>
|
||||
<a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random Access</a>
|
||||
|
||||
|
||||
<tr>
|
||||
<td><tt>dereference</tt>
|
||||
<td nowrap><tt>p.dereference(x)</tt>
|
||||
|
||||
<td>returns an element of the iterator's <tt>reference</tt> type
|
||||
|
||||
<td><tt>*p</tt>, <tt>p[n]</tt>
|
||||
<td><tt>*x</tt>, <tt>x[d]</tt>
|
||||
|
||||
|
||||
<tr>
|
||||
<td><tt>equal</tt>
|
||||
<td nowrap><tt>p.equal(x, y)</tt>
|
||||
|
||||
<td>tests the iterator for equality
|
||||
|
||||
<td><tt>p1 == p2</tt>, <tt>p1 != p2</tt>
|
||||
<td><tt>i1 == i2</tt>, <tt>i1 != i2</tt>
|
||||
|
||||
<tr>
|
||||
<td><tt>increment</tt>
|
||||
<td nowrap><tt>p.increment(x)</tt>
|
||||
|
||||
<td>increments the iterator
|
||||
|
||||
<td><tt>++p</tt>, <tt>p++</tt>
|
||||
<td><tt>++x</tt>, <tt>x++</tt>
|
||||
|
||||
<tr>
|
||||
<td><tt>decrement</tt>
|
||||
<td nowrap><tt>p.decrement(x)</tt>
|
||||
|
||||
<td>decrements the iterator
|
||||
|
||||
<td><tt>--p</tt>, <tt>p--</tt>
|
||||
<td><tt>--x</tt>, <tt>x--</tt>
|
||||
|
||||
<td><a href=
|
||||
"http://www.sgi.com/tech/stl/BidirectionalIterator.html">Bidirectional</a>/
|
||||
<a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random
|
||||
Access</a>
|
||||
<a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random Access</a>
|
||||
|
||||
<tr>
|
||||
<td><tt>less</tt>
|
||||
|
||||
<td>imposes a <a href=
|
||||
"http://www.sgi.com/tech/stl/StrictWeakOrdering.html">Strict Weak
|
||||
Ordering</a> relation on iterators
|
||||
|
||||
<td>
|
||||
<tt>p1 < p2</tt>,
|
||||
<tt>p1 <= p2</tt>,
|
||||
<tt>p1 > p2</tt>,
|
||||
<tt>p1 >= p2</tt>
|
||||
|
||||
<td rowspan="3"><a href=
|
||||
"http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random
|
||||
Access</a>
|
||||
|
||||
<tr>
|
||||
<td><tt>distance</tt>
|
||||
<td nowrap><tt>p.distance(x, y)</tt>
|
||||
|
||||
<td>measures the distance between iterators
|
||||
|
||||
<td><tt>p1 - p2</tt>
|
||||
<td><tt>y - x</tt>, <tt>x < y</tt>
|
||||
|
||||
<td rowspan="2"><a href=
|
||||
"http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random
|
||||
Access</a>
|
||||
|
||||
<tr>
|
||||
<td><tt>advance</tt>
|
||||
<td nowrap><tt>p.advance(x, n)</tt>
|
||||
|
||||
<td>adds an integer offset to iterators
|
||||
|
||||
<td>
|
||||
<tt>p + x</tt>,
|
||||
<tt>x + p</tt>,
|
||||
<tt>p += x</tt>,
|
||||
<tt>p - x</tt>,
|
||||
<tt>p -= x</tt>
|
||||
<tt>x + d</tt>,
|
||||
<tt>d + x</tt>,
|
||||
|
||||
<br>
|
||||
<tt>x += d</tt>,
|
||||
<tt>x - d</tt>,<br>
|
||||
<tt>x -= d</tt>
|
||||
|
||||
</table>
|
||||
|
||||
@ -414,40 +454,40 @@ iterator_adaptor<foo_iterator, foo_policies,
|
||||
<pre>
|
||||
struct <a name="default_iterator_policies">default_iterator_policies</a>
|
||||
{
|
||||
template <class BaseType>
|
||||
void initialize(BaseType&)
|
||||
{ }
|
||||
// Some of these members were defined static, but Borland got confused
|
||||
// and thought they were non-const. Also, Sun C++ does not like static
|
||||
// function templates.
|
||||
|
||||
template <class Reference, class BaseType>
|
||||
Reference dereference(type<Reference>, const BaseType& x) const
|
||||
{ return *x; }
|
||||
template <class Base>
|
||||
void initialize(Base&)
|
||||
{ }
|
||||
|
||||
template <class BaseType>
|
||||
void increment(BaseType& x)
|
||||
{ ++x; }
|
||||
template <class IteratorAdaptor>
|
||||
typename IteratorAdaptor::reference dereference(const IteratorAdaptor& x) const
|
||||
{ return *x.base(); }
|
||||
|
||||
template <class BaseType1, class BaseType2>
|
||||
bool equal(const BaseType1& x, const BaseType2& y) const
|
||||
{ return x == y; }
|
||||
template <class IteratorAdaptor>
|
||||
void increment(IteratorAdaptor& x)
|
||||
{ ++x.base(); }
|
||||
|
||||
template <class BaseType>
|
||||
void decrement(BaseType& x)
|
||||
{ --x; }
|
||||
template <class IteratorAdaptor>
|
||||
void decrement(IteratorAdaptor& x)
|
||||
{ --x.base(); }
|
||||
|
||||
template <class BaseType, class DifferenceType>
|
||||
void advance(BaseType& x, DifferenceType n)
|
||||
{ x += n; }
|
||||
template <class IteratorAdaptor, class DifferenceType>
|
||||
void advance(IteratorAdaptor& x, DifferenceType n)
|
||||
{ x.base() += n; }
|
||||
|
||||
template <class Difference, class BaseType1, class BaseType2>
|
||||
Difference distance(type<Difference>, const BaseType1& x, const BaseType2& y) const
|
||||
{ return y - x; }
|
||||
template <class IteratorAdaptor1, class IteratorAdaptor2>
|
||||
typename IteratorAdaptor1::difference_type
|
||||
distance(const IteratorAdaptor1& x, const IteratorAdaptor2& y) const
|
||||
{ return y.base() - x.base(); }
|
||||
|
||||
template <class BaseType1, class BaseType2>
|
||||
bool less(const BaseType1& x, const BaseType2& y) const
|
||||
{ return x < y; }
|
||||
template <class IteratorAdaptor1, class IteratorAdaptor2>
|
||||
bool equal(const IteratorAdaptor1& x, const IteratorAdaptor2& y) const
|
||||
{ return x.base() == y.base(); }
|
||||
};
|
||||
</pre>
|
||||
</blockquote>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>Template member functions are used throughout
|
||||
<tt>default_iterator_policies</tt> so that it can be employed with a wide
|
||||
@ -480,15 +520,30 @@ struct <a name="default_iterator_policies">default_iterator_policies</a>
|
||||
iterator_adaptor(const
|
||||
iterator_adaptor<B,Policies,V,R,P,Category,Distance>&)</tt>
|
||||
<br><br>
|
||||
This constructor allows for conversion from non-<tt>const</tt> to
|
||||
This constructor allows for conversion from mutable to
|
||||
constant adapted iterators. See <a href=
|
||||
"#iterator_interactions">below</a> for more details.<br>
|
||||
Requires: <tt>B</tt> is convertible to <tt>Base</tt>.
|
||||
|
||||
<tr>
|
||||
<td><tt>base_type base() const;</tt>
|
||||
<td><tt>const base_type& base() const;</tt>
|
||||
<br><br>
|
||||
Return a const reference to the base object.
|
||||
|
||||
<tr> <td><tt>base_type& base();</tt>
|
||||
<br><br>
|
||||
Return a copy of the base object.
|
||||
Return a reference to the base object. This is to give the policies object
|
||||
access to the base object. See <a href="#policies">above</a> for policies
|
||||
iterator_adaptor interaction.<a href="#8">[8]</a>
|
||||
|
||||
<tr>
|
||||
<td><tt>const Policies& policies() const;</tt>
|
||||
<br><br>
|
||||
Return a const reference to the policies object.
|
||||
|
||||
<tr> <td><tt>Policies& policies();</tt>
|
||||
<br><br>
|
||||
Return a reference to the policies object.
|
||||
</table>
|
||||
|
||||
<h3><a name="example">Example</a></h3>
|
||||
@ -506,40 +561,37 @@ struct <a name="default_iterator_policies">default_iterator_policies</a>
|
||||
argument and that we'll need to be able to deduce the <tt>result_type</tt>
|
||||
of the function so we can use it for the adapted iterator's
|
||||
<tt>value_type</tt>. <a href=
|
||||
"http://www.sgi.com/Technology/STL/AdaptableUnaryFunction.html">AdaptableUnaryFunction</a>
|
||||
"http://www.sgi.com/tech/stl/AdaptableUnaryFunction.html">AdaptableUnaryFunction</a>
|
||||
is the <a href="../../more/generic_programming.html#concept">Concept</a>
|
||||
that fulfills those requirements.
|
||||
|
||||
<p>To implement a transform iterator we will only change one of the base
|
||||
iterator's behaviors, so the <tt>transform_iterator_policies</tt> class can
|
||||
inherit the rest from <tt>default_iterator_policies</tt>. We will define
|
||||
the <tt>dereference()</tt> member function, which is used to implement
|
||||
inherit the rest from <tt>default_iterator_policies</tt>. We will define the
|
||||
<tt>dereference()</tt> member function, which is used to implement
|
||||
<tt>operator*()</tt> of the adapted iterator. The implementation will
|
||||
dereference the base iterator and apply the function object. The
|
||||
<tt>type<Reference></tt> parameter is used to convey the appropriate
|
||||
return type. The complete code for <tt>transform_iterator_policies</tt>
|
||||
is:<br>
|
||||
dereference the base iterator and apply the function object. The complete
|
||||
code for <tt>transform_iterator_policies</tt> is:<br>
|
||||
<br>
|
||||
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
template <class AdaptableUnaryFunction>
|
||||
struct transform_iterator_policies : public default_iterator_policies
|
||||
{
|
||||
<blockquote><pre>
|
||||
template <class AdaptableUnaryFunction>
|
||||
struct transform_iterator_policies : public default_iterator_policies
|
||||
{
|
||||
transform_iterator_policies() { }
|
||||
|
||||
transform_iterator_policies(const AdaptableUnaryFunction& f)
|
||||
: m_f(f) { }
|
||||
|
||||
template <class Reference, class BaseIterator>
|
||||
Reference dereference(type<Reference>, const BaseIterator& i) const
|
||||
{ return m_f(*i); }
|
||||
: m_f(f) { }
|
||||
|
||||
template <class IteratorAdaptor>
|
||||
typename IteratorAdaptor::reference
|
||||
dereference(const IteratorAdaptor& iter) const
|
||||
{ return m_f(*iter.base()); }
|
||||
|
||||
AdaptableUnaryFunction m_f;
|
||||
};
|
||||
</pre>
|
||||
</blockquote>
|
||||
};
|
||||
|
||||
</pre></blockquote>
|
||||
|
||||
<p>The next step is to use the <tt>iterator_adaptor</tt> template to
|
||||
construct the transform iterator type. The nicest way to package the
|
||||
@ -575,7 +627,7 @@ public:
|
||||
|
||||
<p>As a finishing touch, we will create an <a href=
|
||||
"../../more/generic_programming.html#object_generator">object generator</a>
|
||||
for the transform iterator. This is a function that makes it more
|
||||
for the transform iterator. Our object generator makes it more
|
||||
convenient to create a transform iterator.<br>
|
||||
<br>
|
||||
|
||||
@ -658,7 +710,7 @@ int main(int, char*[])
|
||||
|
||||
<li>Interoperable iterators can be freely mixed in comparison expressions
|
||||
so long as the <tt>Policies</tt> class has <tt>equal</tt> (and, for
|
||||
random access iterators, <tt>less</tt>) members that can accept both
|
||||
random access iterators, <tt>distance</tt>) members that can accept both
|
||||
<tt>Base</tt> types in either order.
|
||||
|
||||
<li>Interoperable iterators can be freely mixed in subtraction
|
||||
@ -712,11 +764,12 @@ they share the same <tt>Policies</tt> and since <tt>Category</tt> and
|
||||
the projection <tt>const_iterator</tt>.
|
||||
|
||||
<li> Since <tt>projection_iterator_policies</tt> implements only the
|
||||
<tt>dereference</tt> operation, and inherits all other behaviors from <tt><a
|
||||
href="#default_iterator_policies">default_iterator_policies</a></tt>, which has
|
||||
fully-templatized <tt>equal</tt>, <tt>less</tt>, and <tt>distance</tt>
|
||||
operations, the <tt>iterator</tt> and <tt>const_iterator</tt> can be freely
|
||||
mixed in comparison and subtraction expressions.
|
||||
<tt>dereference</tt> operation, and inherits all other behaviors from
|
||||
<tt><a
|
||||
href="#default_iterator_policies">default_iterator_policies</a></tt>,
|
||||
which has fully-templatized <tt>equal</tt> and <tt>distance</tt>
|
||||
operations, the <tt>iterator</tt> and <tt>const_iterator</tt> can be
|
||||
freely mixed in comparison and subtraction expressions.
|
||||
|
||||
</ul>
|
||||
|
||||
@ -724,7 +777,7 @@ mixed in comparison and subtraction expressions.
|
||||
|
||||
<p>There is an unlimited number of ways the <tt>iterator_adaptors</tt>
|
||||
class can be used to create iterators. One interesting exercise would be to
|
||||
re-implement the iterators of <tt>std::list</tt> and <tt>std::slist</tt>
|
||||
re-implement the iterators of <tt>std::list</tt> and <tt>slist</tt>
|
||||
using <tt>iterator_adaptors</tt>, where the adapted <tt>Iterator</tt> types
|
||||
would be node pointers.
|
||||
|
||||
@ -761,7 +814,8 @@ struct iterator_adaptor
|
||||
iterator_adaptor();
|
||||
explicit iterator_adaptor(const Base&, const Policies& = Policies());
|
||||
|
||||
base_type base() const;
|
||||
base_type& base();
|
||||
const base_type& base() const;
|
||||
|
||||
template <class B, class V, class R, class P>
|
||||
iterator_adaptor(
|
||||
@ -806,6 +860,19 @@ bool operator==(const iterator_adaptor<B1,P,V1,R1,P1,C,D>&,
|
||||
// and similarly for operators !=, <, <=, >=, >
|
||||
</pre>
|
||||
|
||||
<h3><a name="portability">Portability</a></h3>
|
||||
|
||||
<p>Generally, the iterator adaptors library can be compiled with all compilers
|
||||
supporting iterator traits and type traits.</p>
|
||||
|
||||
<p>Microsoft VC++ is not able to handle iterator adaptors based on a
|
||||
<code>vector<T>::iterator</code> without specifying all template paramters explicitly.
|
||||
In case not all template parameters are specified explicitly, the iterator adaptors
|
||||
library will deduce these types using iterator_traits. But since in VC++ a
|
||||
<code>vector<T>::iterator</code> is a <code>T*</code>, VC++ can't handle using
|
||||
iterator_traits due to the lack of partial template specialization.</p>
|
||||
|
||||
|
||||
<h3><a name="notes">Notes</a></h3>
|
||||
|
||||
<p><a name="1">[1]</a> The standard specifies that the <tt>value_type</tt>
|
||||
@ -814,12 +881,12 @@ bool operator==(const iterator_adaptor<B1,P,V1,R1,P1,C,D>&,
|
||||
<tt>reference</tt> types for all <a href=
|
||||
"http://www.sgi.com/tech/stl/ForwardIterator.html">Forward Iterators</a> are
|
||||
<tt>const T*</tt> and <tt>const T&</tt>, respectively. Stripping the
|
||||
<tt>const</tt>-ness of <tt>Value</tt> allows you to easily
|
||||
make a <tt>const</tt> iterator adaptor by supplying a <tt>const</tt> type
|
||||
for <tt>Value</tt>, and allowing the defaults for the <tt>Pointer</tt> and
|
||||
<tt>Reference</tt> parameters to take effect. Although compilers that don't
|
||||
support partial specialization won't strip <tt>const</tt> for you, having a
|
||||
<tt>const value_type</tt> is often harmless in practice.
|
||||
<tt>const</tt>-ness of <tt>Value</tt> allows you to easily make a constant
|
||||
iterator by supplying a <tt>const</tt> type for <tt>Value</tt>, and allowing
|
||||
the defaults for the <tt>Pointer</tt> and <tt>Reference</tt> parameters to
|
||||
take effect. Although compilers that don't support partial specialization
|
||||
won't strip <tt>const</tt> for you, having a <tt>const value_type</tt> is
|
||||
often harmless in practice.
|
||||
|
||||
<p><a name="2">[2]</a> If your compiler does not support partial
|
||||
specialization and the base iterator is a builtin pointer type, you
|
||||
@ -885,10 +952,22 @@ bool operator==(const iterator_adaptor<B1,P,V1,R1,P1,C,D>&,
|
||||
*x = i;
|
||||
</pre>
|
||||
|
||||
<p><a name="7">[7]</a>
|
||||
If you are using a compiler that does not have a version of
|
||||
<tt>std::iterator_traits</tt> that works for pointers (i.e., if your
|
||||
compiler does not support partial specialization) then if the
|
||||
<tt>Base</tt> type is a const pointer, then the correct defaults
|
||||
for the <tt>reference</tt> and <tt>pointer</tt> types can not be
|
||||
deduced. You must specify these types explicitly.
|
||||
<p><a name="8">[8]</a>
|
||||
Exposing the base object might be considered as being dangerous.
|
||||
A possible fix would require compiler support for template friends.
|
||||
As this is not widely available today, the base object remains exposed for now.
|
||||
|
||||
<hr>
|
||||
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->18 Sep 2001<!--webbot bot="Timestamp" endspan i-checksum="14941" -->
|
||||
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->30 Nov 2001<!--webbot bot="Timestamp" endspan i-checksum="15239" -->
|
||||
|
||||
|
||||
<p>© Copyright Dave Abrahams and Jeremy Siek 2001. Permission to copy,
|
||||
|
BIN
iterator_adaptors.pdf
Normal file
BIN
iterator_adaptors.pdf
Normal file
Binary file not shown.
BIN
iterator_adaptors.ppt
Normal file
BIN
iterator_adaptors.ppt
Normal file
Binary file not shown.
@ -85,15 +85,17 @@ template <class Iterator,
|
||||
struct non_portable_tests
|
||||
{
|
||||
// Unfortunately, the VC6 standard library doesn't supply these :(
|
||||
typedef typename boost::detail::iterator_traits<Iterator>::pointer test_pt;
|
||||
typedef typename boost::detail::iterator_traits<Iterator>::reference test_rt;
|
||||
BOOST_STATIC_ASSERT((
|
||||
boost::is_same<
|
||||
typename boost::detail::iterator_traits<Iterator>::pointer,
|
||||
::boost::is_same<
|
||||
test_pt,
|
||||
pointer
|
||||
>::value));
|
||||
|
||||
|
||||
BOOST_STATIC_ASSERT((
|
||||
boost::is_same<
|
||||
typename boost::detail::iterator_traits<Iterator>::reference,
|
||||
::boost::is_same<
|
||||
test_rt,
|
||||
reference
|
||||
>::value));
|
||||
};
|
||||
@ -102,15 +104,17 @@ template <class Iterator,
|
||||
class value_type, class difference_type, class pointer, class reference, class category>
|
||||
struct portable_tests
|
||||
{
|
||||
typedef typename boost::detail::iterator_traits<Iterator>::difference_type test_dt;
|
||||
typedef typename boost::detail::iterator_traits<Iterator>::iterator_category test_cat;
|
||||
BOOST_STATIC_ASSERT((
|
||||
boost::is_same<
|
||||
typename boost::detail::iterator_traits<Iterator>::difference_type,
|
||||
::boost::is_same<
|
||||
test_dt,
|
||||
difference_type
|
||||
>::value));
|
||||
|
||||
|
||||
BOOST_STATIC_ASSERT((
|
||||
boost::is_same<
|
||||
typename boost::detail::iterator_traits<Iterator>::iterator_category,
|
||||
::boost::is_same<
|
||||
test_cat,
|
||||
category
|
||||
>::value));
|
||||
};
|
||||
@ -121,9 +125,10 @@ template <class Iterator,
|
||||
struct input_iterator_test
|
||||
: portable_tests<Iterator,value_type,difference_type,pointer,reference,category>
|
||||
{
|
||||
typedef typename boost::detail::iterator_traits<Iterator>::value_type test_vt;
|
||||
BOOST_STATIC_ASSERT((
|
||||
boost::is_same<
|
||||
typename boost::detail::iterator_traits<Iterator>::value_type,
|
||||
::boost::is_same<
|
||||
test_vt,
|
||||
value_type
|
||||
>::value));
|
||||
};
|
||||
|
@ -75,6 +75,12 @@ protected:
|
||||
|
||||
}; // test_opr_base
|
||||
|
||||
#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
|
||||
// A definition is required even for integral static constants
|
||||
const std::size_t test_opr_base::fruit_length;
|
||||
const std::size_t test_opr_base::scratch_length;
|
||||
#endif
|
||||
|
||||
template <typename T, typename R = T&, typename P = T*>
|
||||
class test_opr
|
||||
: public test_opr_base
|
||||
@ -94,7 +100,8 @@ public:
|
||||
|
||||
private:
|
||||
// Test data
|
||||
static iter_type const fruit_begin, fruit_end;
|
||||
static iter_type const fruit_begin;
|
||||
static iter_type const fruit_end;
|
||||
|
||||
// Test parts
|
||||
static void post_increment_test();
|
||||
@ -117,12 +124,12 @@ test_opr_base::scratch_array_type
|
||||
test_opr_base::scratch = "";
|
||||
|
||||
template <typename T, typename R, typename P>
|
||||
typename test_opr<T, R, P>::iter_type const
|
||||
test_opr<T, R, P>::fruit_begin( fruit );
|
||||
typename test_opr<T, R, P>::iter_type const
|
||||
test_opr<T, R, P>::fruit_begin = test_iter<T,R,P>( fruit );
|
||||
|
||||
template <typename T, typename R, typename P>
|
||||
typename test_opr<T, R, P>::iter_type const
|
||||
test_opr<T, R, P>::fruit_end( fruit + fruit_length );
|
||||
test_opr<T, R, P>::fruit_end = test_iter<T,R,P>( fruit + fruit_length );
|
||||
|
||||
|
||||
// Main testing function
|
||||
|
@ -20,7 +20,7 @@
|
||||
|
||||
namespace
|
||||
{
|
||||
class DontTreadOnMe : boost::noncopyable
|
||||
class DontTreadOnMe : private boost::noncopyable
|
||||
{
|
||||
public:
|
||||
DontTreadOnMe() { std::cout << "defanged!" << std::endl; }
|
||||
@ -35,4 +35,4 @@ int main()
|
||||
object1 = object2;
|
||||
return 0;
|
||||
} // main
|
||||
|
||||
|
||||
|
@ -347,7 +347,7 @@ void test(Number* = 0)
|
||||
|
||||
// factoring out difference_type for the assert below confused Borland :(
|
||||
typedef boost::detail::is_signed<
|
||||
#ifndef BOOST_MSVC
|
||||
#if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
|
||||
typename
|
||||
#endif
|
||||
boost::detail::numeric_traits<Number>::difference_type
|
||||
@ -374,7 +374,7 @@ int main()
|
||||
test<unsigned int>();
|
||||
test<long>();
|
||||
test<unsigned long>();
|
||||
#if defined(ULLONG_MAX) || defined(ULONG_LONG_MAX)
|
||||
#if defined(BOOST_HAS_LONG_LONG) && !defined(BOOST_NO_INTEGRAL_INT64_T)
|
||||
test<long long>();
|
||||
test<unsigned long long>();
|
||||
#elif defined(BOOST_MSVC)
|
||||
|
317
operators.htm
317
operators.htm
@ -30,7 +30,11 @@ provided by the class.</p>
|
||||
</ul></li>
|
||||
<li><a href="#usage">Usage</a>
|
||||
<ul>
|
||||
<li><a href="#two_arg">Two-Argument Template Forms</a></li>
|
||||
<li><a href="#two_arg">Two-Argument Template Forms</a>
|
||||
<ul>
|
||||
<li><a href="#two_arg_gen">General Considerations</a></li>
|
||||
<li><a href="#mixed_arithmetics">Mixed arithmetics</a></li>
|
||||
</ul></li>
|
||||
<li><a href="#chaining">Base Class Chaining and Object Size</a></li>
|
||||
<li><a href="#explicit_instantiation">Separate, Explicit
|
||||
Instantiation</a></li>
|
||||
@ -39,7 +43,10 @@ provided by the class.</p>
|
||||
<li><a href="#example">Example</a></li>
|
||||
<li><a href="#arithmetic">Arithmetic operators</a>
|
||||
<ul>
|
||||
<li><a href="#smpl_oprs">Simple Arithmetic Operators</a></li>
|
||||
<li><a href="#smpl_oprs">Simple Arithmetic Operators</a>
|
||||
<ul>
|
||||
<li><a href="#ordering">Ordering Note</a></li>
|
||||
</ul></li>
|
||||
<li><a href="#grpd_oprs">Grouped Arithmetic Operators</a></li>
|
||||
<li><a href="#ex_oprs">Example Templates</a></li>
|
||||
<li><a href="#a_demo">Arithmetic Operators Demonstration
|
||||
@ -49,8 +56,12 @@ provided by the class.</p>
|
||||
Helpers</a>
|
||||
<ul>
|
||||
<li><a href="#dereference">Dereference operators</a></li>
|
||||
<li><a href="#iterator">Iterator Helpers</a></li>
|
||||
<li><a href="#iterator_helpers_notes">Iterator Helper Notes</a></li>
|
||||
<li><a href="#grpd_iter_oprs">Grouped Iterator Operators</a></li>
|
||||
<li><a href="#iterator">Iterator Helpers</a>
|
||||
<ul>
|
||||
<li><a href="#iterator_helpers_notes">Iterator Helper
|
||||
Notes</a></li>
|
||||
</ul></li>
|
||||
<li><a href="#i_demo">Iterator Demonstration and Test
|
||||
Program</a></li>
|
||||
</ul></li>
|
||||
@ -151,6 +162,8 @@ domains, <i>i.e.</i> eventually more useful.</p>
|
||||
|
||||
<h3><a name="two_arg">Two-Argument</a> Template Forms</h3>
|
||||
|
||||
<h4><a name="two_arg_gen">General Considerations</a></h4>
|
||||
|
||||
<p>The arguments to a binary operator commonly have identical types, but
|
||||
it is not unusual to want to define operators which combine different
|
||||
types. For <a href="#example">example</a>, one might want to multiply a
|
||||
@ -176,6 +189,46 @@ trailing <code>'1'</code> are provided for symmetry and to enable
|
||||
certain applications of the <a href="#chaining">base class chaining</a>
|
||||
technique.</p>
|
||||
|
||||
<h4><a name="mixed_arithmetics">Mixed Arithmetics</a></h4>
|
||||
|
||||
<p>Another application of the two-argument template forms is for
|
||||
mixed arithmetics between a type <code>T</code> and a type <code>U</code>
|
||||
that is convertible to <code>T</code>. In this case there are two ways
|
||||
where the two-argument template forms are helpful: one is to provide
|
||||
the respective signatures for operator overloading, the second is
|
||||
performance.</p>
|
||||
|
||||
<p>With respect to the operator overloading assume <i>e.g.</i> that
|
||||
<code>U</code> is <code>int</code>, that <code>T</code> is an user-defined
|
||||
unlimited integer type, and that <code>double operator-(double, const
|
||||
T&)</code> exists. If one wants to compute <code>int - T</code> and
|
||||
does not provide <code>T operator-(int, const T&)</code>, the
|
||||
compiler will consider <code>double operator-(double, const T&)</code>
|
||||
to be a better match than <code>T operator-(const T&, const
|
||||
T&)</code>, which will probably be different from the user's intention.
|
||||
To define a complete set of operator signatures, additional 'left' forms
|
||||
of the two-argument template forms are provided (<code><a
|
||||
href="#subtractable2_left">subtractable2_left<T, U></a></code>,
|
||||
<code><a href="#dividable2_left">dividable2_left<T, U></a></code>,
|
||||
<code><a href="#modable2_left">modable2_left<T, U></a></code>) that
|
||||
define the signatures for non-commutative operators where <code>U</code>
|
||||
appears on the left hand side (<code>operator-(const U&, const
|
||||
T&)</code>, <code>operator/(const U&, const T&)</code>,
|
||||
<code>operator%(const U&, const T&)</code>).</p>
|
||||
|
||||
<p>With respect to the performance observe that when one uses the
|
||||
single type binary operator for mixed type arithmetics, the type
|
||||
<code>U</code> argument has to be converted to type <code>T</code>. In
|
||||
practice, however, there are often more efficient implementations of,
|
||||
say <code>T::operator-=(const U&)</code> that avoid unnecessary
|
||||
conversions from <code>U</code> to <code>T</code>. The two-argument
|
||||
template forms of the arithmetic operator create additional operator
|
||||
interfaces that use these more efficient implementations. There is, however,
|
||||
no performance gain in the 'left' forms: they still need a conversion
|
||||
from <code>U</code> to <code>T</code> and have an implementation
|
||||
equivalent to the code that would be automatically created by the compiler
|
||||
if it considered the single type binary operator to be the best match.</p>
|
||||
|
||||
<h3>Base Class <a name="chaining">Chaining</a> and Object Size</h3>
|
||||
|
||||
<p>Every operator class template, except the <a href="#ex_oprs">arithmetic
|
||||
@ -419,6 +472,12 @@ for the <a href="#chaining">base class chaining</a> technique.
|
||||
<td><code>t -= u</code>.<br>
|
||||
Return convertible to <code>T</code>.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><a name="subtractable2_left">subtractable2_left<T, U></a></code></td>
|
||||
<td><code>T operator-(const U&, const T&)</code></td>
|
||||
<td><code>T temp(u); temp -= t</code>.<br>
|
||||
Return convertible to <code>T</code>.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><a name="multipliable1">multipliable<T></a></code><br>
|
||||
<code>multipliable1<T></code></td>
|
||||
@ -448,6 +507,12 @@ for the <a href="#chaining">base class chaining</a> technique.
|
||||
<td><code>t /= u</code>.<br>
|
||||
Return convertible to <code>T</code>.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><a name="dividable2_left">dividable2_left<T, U></a></code></td>
|
||||
<td><code>T operator/(const U&, const T&)</code></td>
|
||||
<td><code>T temp(u); temp /= t</code>.<br>
|
||||
Return convertible to <code>T</code>.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><a name="modable1">modable<T></a></code><br>
|
||||
<code>modable1<T></code></td>
|
||||
@ -462,6 +527,12 @@ for the <a href="#chaining">base class chaining</a> technique.
|
||||
<td><code>t %= u</code>.<br>
|
||||
Return convertible to <code>T</code>.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><a name="modable2_left">modable2_left<T, U></a></code></td>
|
||||
<td><code>T operator%(const U&, const T&)</code></td>
|
||||
<td><code>T temp(u); temp %= t</code>.<br>
|
||||
Return convertible to <code>T</code>.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><a name="orable1">orable<T></a></code><br>
|
||||
<code>orable1<T></code></td>
|
||||
@ -588,8 +659,9 @@ for the <a href="#chaining">base class chaining</a> technique.
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p><strong><a name="ordering">Ordering Note</a></strong><br>
|
||||
The <code><a href="#less_than_comparable1">less_than_comparable<T></a></code>
|
||||
<h4><a name="ordering">Ordering</a> Note</h4>
|
||||
|
||||
<p>The <code><a href="#less_than_comparable1">less_than_comparable<T></a></code>
|
||||
and <code><a href="#partially_ordered1">partially_ordered<T></a></code>
|
||||
templates provide the same set of operations. However, the workings of
|
||||
<code><a href="#less_than_comparable1">less_than_comparable<T></a></code>
|
||||
@ -771,6 +843,109 @@ optional template parameter <code>B</code>, which is not shown, for the
|
||||
<li><code><a href="#right_shiftable2">right_shiftable<T, U></a></code></li>
|
||||
</ul></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><a name="ring_operators1">ring_operators<T></a></code><br>
|
||||
<code>ring_operators1<T></code></td>
|
||||
<td><ul>
|
||||
<li><code><a href="#additive1">additive<T></a></code></li>
|
||||
<li><code><a href="#multipliable1">multipliable<T></a></code></li>
|
||||
</ul></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><a name="ring_operators2">ring_operators<T, U></a></code><br>
|
||||
<code>ring_operators2<T, U></code></td>
|
||||
<td><ul>
|
||||
<li><code><a href="#additive2">additive<T, U></a></code></li>
|
||||
<li><code><a href="#subtractable2_left">subtractable2_left<T, U></a></code></li>
|
||||
<li><code><a href="#multipliable2">multipliable<T, U></a></code></li>
|
||||
</ul></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><a name="ordered_ring_operators1">ordered_ring_operators<T></a></code><br>
|
||||
<code>ordered_ring_operators1<T></code></td>
|
||||
<td><ul>
|
||||
<li><code><a href="#ring_operators1">ring_operators<T></a></code></li>
|
||||
<li><code><a href="#totally_ordered1">totally_ordered<T></a></code></li>
|
||||
</ul></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><a name="ordered_ring_operators2">ordered_ring_operators<T, U></a></code><br>
|
||||
<code>ordered_ring_operators2<T, U></code></td>
|
||||
<td><ul>
|
||||
<li><code><a href="#ring_operators2">ring_operators<T, U></a></code></li>
|
||||
<li><code><a href="#totally_ordered2">totally_ordered<T, U></a></code></li>
|
||||
</ul></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><a name="field_operators1">field_operators<T></a></code><br>
|
||||
<code>field_operators1<T></code></td>
|
||||
<td><ul>
|
||||
<li><code><a href="#ring_operators1">ring_operators<T></a></code></li>
|
||||
<li><code><a href="#dividable1">dividable<T></a></code></li>
|
||||
</ul></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><a name="field_operators2">field_operators<T, U></a></code><br>
|
||||
<code>field_operators2<T, U></code></td>
|
||||
<td><ul>
|
||||
<li><code><a href="#ring_operators2">ring_operators<T, U></a></code></li>
|
||||
<li><code><a href="#dividable2">dividable<T, U></a></code></li>
|
||||
<li><code><a href="#dividable2_left">dividable2_left<T, U></a></code></li>
|
||||
</ul></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><a name="ordered_field_operators1">ordered_field_operators<T></a></code><br>
|
||||
<code>ordered_field_operators1<T></code></td>
|
||||
<td><ul>
|
||||
<li><code><a href="#field_operators1">field_operators<T></a></code></li>
|
||||
<li><code><a href="#totally_ordered1">totally_ordered<T></a></code></li>
|
||||
</ul></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><a name="ordered_field_operators2">ordered_field_operators<T, U></a></code><br>
|
||||
<code>ordered_field_operators2<T, U></code></td>
|
||||
<td><ul>
|
||||
<li><code><a href="#field_operators2">field_operators<T, U></a></code></li>
|
||||
<li><code><a href="#totally_ordered2">totally_ordered<T, U></a></code></li>
|
||||
</ul></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><a name="euclidian_ring_operators1">euclidian_ring_operators<T></a></code><br>
|
||||
<code>euclidian_ring_operators1<T></code></td>
|
||||
<td><ul>
|
||||
<li><code><a href="#ring_operators1">ring_operators<T></a></code></li>
|
||||
<li><code><a href="#dividable1">dividable<T></a></code></li>
|
||||
<li><code><a href="#modable1">modable<T></a></code></li>
|
||||
</ul></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><a name="euclidian_ring_operators2">euclidian_ring_operators<T, U></a></code><br>
|
||||
<code>euclidian_ring_operators2<T, U></code></td>
|
||||
<td><ul>
|
||||
<li><code><a href="#ring_operators2">ring_operators<T, U></a></code></li>
|
||||
<li><code><a href="#dividable2">dividable<T, U></a></code></li>
|
||||
<li><code><a href="#dividable2_left">dividable2_left<T, U></a></code></li>
|
||||
<li><code><a href="#modable2">modable<T, U></a></code></li>
|
||||
<li><code><a href="#modable2_left">modable2_left<T, U></a></code></li>
|
||||
</ul></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><a name="ordered_euclidian_ring_operators1">ordered_euclidian_ring_operators<T></a></code><br>
|
||||
<code>ordered_euclidian_ring_operators1<T></code></td>
|
||||
<td><ul>
|
||||
<li><code><a href="#euclidian_ring_operators1">euclidian_ring_operators<T></a></code></li>
|
||||
<li><code><a href="#totally_ordered1">totally_ordered<T></a></code></li>
|
||||
</ul></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><a name="ordered_euclidian_ring_operators2">ordered_euclidian_ring_operators<T, U></a></code><br>
|
||||
<code>ordered_euclidian_ring_operators2<T, U></code></td>
|
||||
<td><ul>
|
||||
<li><code><a href="#euclidian_ring_operators2">euclidian_ring_operators<T, U></a></code></li>
|
||||
<li><code><a href="#totally_ordered2">totally_ordered<T, U></a></code></li>
|
||||
</ul></td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
|
||||
<h3><a name="ex_oprs">Example</a> Templates</h3>
|
||||
@ -888,19 +1063,87 @@ href="#chaining">base class chaining</a>.</p>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h3><a name="iterator">Iterator</a> Helpers</h3>
|
||||
<h3><a name="grpd_iter_oprs">Grouped Iterator Operators</a></h3>
|
||||
|
||||
<p>There are five separate iterator helper classes, each for a
|
||||
different category of iterator. Here is a summary of the core set of
|
||||
operators that the custom iterator must define, and the extra operators
|
||||
that are created by the helper classes. These classes cannot be used for <a
|
||||
href="#chaining">base class chaining</a>. For convenience, the helper
|
||||
classes also fill in all of the typedef's required of iterators by the
|
||||
C++ standard (<code>iterator_category</code>, <code>value_type</code>,
|
||||
<i>etc.</i>).</p>
|
||||
<p>There are five iterator operator class templates, each for a different
|
||||
category of iterator. The following table shows the operator groups
|
||||
for any category that a custom iterator could define. These class
|
||||
templates have an additional optional template parameter <code>B</code>,
|
||||
which is not shown, to support <a href="#chaining">base class chaining</a>.</p>
|
||||
|
||||
<table cellpadding="5" border="1" align="center">
|
||||
<caption>Iterator Helper Template Classes</caption>
|
||||
<caption>Iterator Operator Class Templates</caption>
|
||||
<tr>
|
||||
<td colspan="2"><table align="center" border="1">
|
||||
<caption><em>Key</em></caption>
|
||||
<tr>
|
||||
<td><code>T</code>: operand type</td>
|
||||
<td><code>P</code>: <code>pointer</code> type</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>D</code>: <code>difference_type</code></td>
|
||||
<td><code>R</code>: <code>reference</code> type</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>V</code>: <code>value_type</code></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</table></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Template</th>
|
||||
<th>Component Operator Templates</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><a name="input_iteratable">input_iteratable<T, P></a></code></td>
|
||||
<td><ul>
|
||||
<li><code><a href="#equality_comparable1">equality_comparable<T></a></code></li>
|
||||
<li><code><a href="#incrementable">incrementable<T></a></code></li>
|
||||
<li><code><a href="#dereferenceable">dereferenceable<T, P></a></code></li>
|
||||
</ul></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><a name="output_iteratable">output_iteratable<T></a></code></td>
|
||||
<td><ul>
|
||||
<li><code><a href="#incrementable">incrementable<T></a></code></li>
|
||||
</ul></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><a name="forward_iteratable">forward_iteratable<T, P></a></code></td>
|
||||
<td><ul>
|
||||
<li><code><a href="#input_iteratable">input_iteratable<T, P></a></code></li>
|
||||
</ul></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><a name="bidirectional_iteratable">bidirectional_iteratable<T, P></a></code></td>
|
||||
<td><ul>
|
||||
<li><code><a href="#forward_iteratable">forward_iteratable<T, P></a></code></li>
|
||||
<li><code><a href="#decrementable">decrementable<T></a></code></li>
|
||||
</ul></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code><a name="random_access_iteratable">random_access_iteratable<T, P, D, R></a></code></td>
|
||||
<td><ul>
|
||||
<li><code><a href="#bidirectional_iteratable">bidirectional_iteratable<T, P></a></code></li>
|
||||
<li><code><a href="#totally_ordered1">totally_ordered<T></a></code></li>
|
||||
<li><code><a href="#additive2">additive<T, D></a></code></li>
|
||||
<li><code><a href="#indexable">indexable<T, D, R></a></code></li>
|
||||
</ul></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h3><a name="iterator">Iterator</a> Helpers</h3>
|
||||
|
||||
<p>There are also five iterator helper class templates, each corresponding
|
||||
to a different iterator category. These classes cannot be used for <a
|
||||
href="#chaining">base class chaining</a>. The following summaries
|
||||
show that these class templates supply both the iterator operators from
|
||||
the <a href="#grpd_iter_oprs">iterator operator class templates</a> and
|
||||
the iterator typedef's required by the C++ standard (<code>iterator_category</code>,
|
||||
<code>value_type</code>, <i>etc.</i>).</p>
|
||||
|
||||
<table cellpadding="5" border="1" align="center">
|
||||
<caption>Iterator Helper Class Templates</caption>
|
||||
<tr>
|
||||
<td colspan="2"><table align="center" border="1">
|
||||
<caption><em>Key</em></caption>
|
||||
@ -926,16 +1169,14 @@ C++ standard (<code>iterator_category</code>, <code>value_type</code>,
|
||||
<td><code><a name="input_iterator_helper">input_iterator_helper<T, V, D, P, R></a></code></td>
|
||||
<td>Supports the operations and has the requirements of
|
||||
<ul>
|
||||
<li><code><a href="#equality_comparable1">equality_comparable<T></a></code></li>
|
||||
<li><code><a href="#incrementable">incrementable<T></a></code></li>
|
||||
<li><code><a href="#dereferenceable">dereferenceable<T, P></a></code></li>
|
||||
<li><code><a href="#input_iteratable">input_iteratable<T, P></a></code></li>
|
||||
</ul></td>
|
||||
</tr>
|
||||
<tr valign="baseline">
|
||||
<td><code><a name="output_iterator_helper">output_iterator_helper<T></a></code></td>
|
||||
<td>Supports the operations and has the requirements of
|
||||
<ul>
|
||||
<li><code><a href="#incrementable">incrementable<T></a></code></li>
|
||||
<li><code><a href="#output_iteratable">output_iteratable<T></a></code></li>
|
||||
</ul>
|
||||
See also [<a href="#1">1</a>], [<a href="#2">2</a>].
|
||||
</td>
|
||||
@ -944,33 +1185,21 @@ C++ standard (<code>iterator_category</code>, <code>value_type</code>,
|
||||
<td><code><a name="forward_iterator_helper">forward_iterator_helper<T, V, D, P, R></a></code></td>
|
||||
<td>Supports the operations and has the requirements of
|
||||
<ul>
|
||||
<li><code><a href="#equality_comparable1">equality_comparable<T></a></code></li>
|
||||
<li><code><a href="#incrementable">incrementable<T></a></code></li>
|
||||
<li><code><a href="#dereferenceable">dereferenceable<T, P></a></code></li>
|
||||
<li><code><a href="#forward_iteratable">forward_iteratable<T, P></a></code></li>
|
||||
</ul></td>
|
||||
</tr>
|
||||
<tr valign="baseline">
|
||||
<td><code><a name="bidirectional_iterator_helper">bidirectional_iterator_helper<T, V, D, P, R></a></code></td>
|
||||
<td>Supports the operations and has the requirements of
|
||||
<ul>
|
||||
<li><code><a href="#equality_comparable1">equality_comparable<T></a></code></li>
|
||||
<li><code><a href="#incrementable">incrementable<T></a></code></li>
|
||||
<li><code><a href="#decrementable">decrementable<T></a></code></li>
|
||||
<li><code><a href="#dereferenceable">dereferenceable<T, P></a></code></li>
|
||||
<li><code><a href="#bidirectional_iteratable">bidirectional_iteratable<T, P></a></code></li>
|
||||
</ul></td>
|
||||
</tr>
|
||||
<tr valign="baseline">
|
||||
<td><code><a name="random_access_iterator_helper">random_access_iterator_helper<T, V, D, P, R></a></code></td>
|
||||
<td>Supports the operations and has the requirements of
|
||||
<ul>
|
||||
<li><code><a href="#equality_comparable1">equality_comparable<T></a></code></li>
|
||||
<li><code><a href="#less_than_comparable1">less_than_comparable<T></a></code></li>
|
||||
<li><code><a href="#incrementable">incrementable<T></a></code></li>
|
||||
<li><code><a href="#decrementable">decrementable<T></a></code></li>
|
||||
<li><code><a href="#dereferenceable">dereferenceable<T, P></a></code></li>
|
||||
<li><code><a href="#addable2">addable<T, D></a></code></li>
|
||||
<li><code><a href="#subtractable2">subtractable<T, D></a></code></li>
|
||||
<li><code><a href="#indexable">indexable<T, D, R></a></code></li>
|
||||
<li><code><a href="#random_access_iteratable">random_access_iteratable<T, P, D, R></a></code></li>
|
||||
</ul>
|
||||
To satisfy <cite><a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">RandomAccessIterator</a></cite>,
|
||||
<code>x1 - x2</code> with return convertible to <code>D</code>
|
||||
@ -978,7 +1207,7 @@ C++ standard (<code>iterator_category</code>, <code>value_type</code>,
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h3><a name="iterator_helpers_notes">Iterator Helper Notes</a></h3>
|
||||
<h4><a name="iterator_helpers_notes">Iterator Helper Notes</a></h4>
|
||||
|
||||
<p><a name="1">[1]</a> Unlike other iterator helpers templates,
|
||||
<code>output_iterator_helper</code> takes only one template parameter - the type of
|
||||
@ -987,8 +1216,8 @@ restriction, the standard requires <code>difference_type</code> and
|
||||
<code>value_type</code> of any output iterator to be
|
||||
<code>void</code> (24.3.1 [lib.iterator.traits]), and
|
||||
<code>output_iterator_helper</code> template respects this
|
||||
requirement. Also, output iterators in the standard have void <tt>pointer</tt> and
|
||||
<tt>reference</tt> types, so the <tt>output_iterator_helper</tt> does the
|
||||
requirement. Also, output iterators in the standard have void <code>pointer</code> and
|
||||
<code>reference</code> types, so the <code>output_iterator_helper</code> does the
|
||||
same.
|
||||
|
||||
<p><a name="2">[2]</a> As self-proxying is the easiest and most common way to
|
||||
@ -1008,13 +1237,13 @@ template<class UnaryFunction>
|
||||
struct function_output_iterator
|
||||
: boost::output_iterator_helper< function_output_iterator<UnaryFunction> >
|
||||
{
|
||||
explicit function_output_iterator(UnaryFunction const& f = UnaryFunction())
|
||||
explicit function_output_iterator(UnaryFunction const& f = UnaryFunction())
|
||||
: func(f) {}
|
||||
|
||||
template<typename T>
|
||||
function_output_iterator& operator=(T const& value)
|
||||
function_output_iterator& operator=(T const& value)
|
||||
{
|
||||
this->func(value);
|
||||
this->func(value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -1093,6 +1322,10 @@ the test results with selected platforms.</p>
|
||||
partial ordering, and arithmetic conversions. Added the
|
||||
grouped operator classes. Added helper classes for
|
||||
input and output iterators.
|
||||
|
||||
<dt>Helmut Zeisel
|
||||
<dd>Contributed the 'left' operators and added some
|
||||
grouped operator classes.
|
||||
</dl>
|
||||
|
||||
<h2>Note for Users of <a name="old_lib_note">Older Versions</a></h2>
|
||||
@ -1142,7 +1375,7 @@ the library remain backward-compatible.</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<p>Revised: 25 Jun 2001</p>
|
||||
<p>Revised: 30 Oct 2001</p>
|
||||
|
||||
<p>Copyright © David Abrahams and Beman Dawes 1999-2001.
|
||||
Permission to copy, use, modify, sell and distribute this document is
|
||||
|
@ -8,6 +8,8 @@
|
||||
// See http://www.boost.org for most recent version including documentation.
|
||||
|
||||
// Revision History
|
||||
// 01 Oct 01 Added tests for "left" operators
|
||||
// and new grouped operators. (Helmut Zeisel)
|
||||
// 20 May 01 Output progress messages. Added tests for new operator
|
||||
// templates. Updated random number generator. Changed tests to
|
||||
// use Boost Test Tools library. (Daryle Walker)
|
||||
@ -184,6 +186,74 @@ namespace
|
||||
template <class T, class U>
|
||||
T true_value(Wrapped4<T,U> x) { return x.value(); }
|
||||
|
||||
// U must be convertible to T
|
||||
template <class T, class U>
|
||||
class Wrapped5
|
||||
: boost::ordered_field_operators2<Wrapped5<T, U>, U>
|
||||
, boost::ordered_field_operators1<Wrapped5<T, U> >
|
||||
{
|
||||
public:
|
||||
explicit Wrapped5( T v = T() ) : _value(v) {}
|
||||
|
||||
// Conversion from U to Wrapped5<T,U>
|
||||
Wrapped5(U u) : _value(u) {}
|
||||
|
||||
T value() const { return _value; }
|
||||
bool operator<(const Wrapped5& x) const { return _value < x._value; }
|
||||
bool operator<(U u) const { return _value < u; }
|
||||
bool operator>(U u) const { return _value > u; }
|
||||
bool operator==(const Wrapped5& u) const { return _value == u._value; }
|
||||
bool operator==(U u) const { return _value == u; }
|
||||
Wrapped5& operator/=(const Wrapped5& u) { _value /= u._value; return *this;}
|
||||
Wrapped5& operator/=(U u) { _value /= u; return *this;}
|
||||
Wrapped5& operator*=(const Wrapped5& u) { _value *= u._value; return *this;}
|
||||
Wrapped5& operator*=(U u) { _value *= u; return *this;}
|
||||
Wrapped5& operator-=(const Wrapped5& u) { _value -= u._value; return *this;}
|
||||
Wrapped5& operator-=(U u) { _value -= u; return *this;}
|
||||
Wrapped5& operator+=(const Wrapped5& u) { _value += u._value; return *this;}
|
||||
Wrapped5& operator+=(U u) { _value += u; return *this;}
|
||||
|
||||
private:
|
||||
T _value;
|
||||
};
|
||||
template <class T, class U>
|
||||
T true_value(Wrapped5<T,U> x) { return x.value(); }
|
||||
|
||||
// U must be convertible to T
|
||||
template <class T, class U>
|
||||
class Wrapped6
|
||||
: boost::ordered_euclidian_ring_operators2<Wrapped6<T, U>, U>
|
||||
, boost::ordered_euclidian_ring_operators1<Wrapped6<T, U> >
|
||||
{
|
||||
public:
|
||||
explicit Wrapped6( T v = T() ) : _value(v) {}
|
||||
|
||||
// Conversion from U to Wrapped6<T,U>
|
||||
Wrapped6(U u) : _value(u) {}
|
||||
|
||||
T value() const { return _value; }
|
||||
bool operator<(const Wrapped6& x) const { return _value < x._value; }
|
||||
bool operator<(U u) const { return _value < u; }
|
||||
bool operator>(U u) const { return _value > u; }
|
||||
bool operator==(const Wrapped6& u) const { return _value == u._value; }
|
||||
bool operator==(U u) const { return _value == u; }
|
||||
Wrapped6& operator%=(const Wrapped6& u) { _value %= u._value; return *this;}
|
||||
Wrapped6& operator%=(U u) { _value %= u; return *this;}
|
||||
Wrapped6& operator/=(const Wrapped6& u) { _value /= u._value; return *this;}
|
||||
Wrapped6& operator/=(U u) { _value /= u; return *this;}
|
||||
Wrapped6& operator*=(const Wrapped6& u) { _value *= u._value; return *this;}
|
||||
Wrapped6& operator*=(U u) { _value *= u; return *this;}
|
||||
Wrapped6& operator-=(const Wrapped6& u) { _value -= u._value; return *this;}
|
||||
Wrapped6& operator-=(U u) { _value -= u; return *this;}
|
||||
Wrapped6& operator+=(const Wrapped6& u) { _value += u._value; return *this;}
|
||||
Wrapped6& operator+=(U u) { _value += u; return *this;}
|
||||
|
||||
private:
|
||||
T _value;
|
||||
};
|
||||
template <class T, class U>
|
||||
T true_value(Wrapped6<T,U> x) { return x.value(); }
|
||||
|
||||
// MyInt uses only the single template-argument form of all_operators<>
|
||||
typedef Wrapped1<int> MyInt;
|
||||
|
||||
@ -193,6 +263,10 @@ namespace
|
||||
|
||||
typedef Wrapped4<short, short> MyShort;
|
||||
|
||||
typedef Wrapped5<double, int> MyDoubleInt;
|
||||
|
||||
typedef Wrapped6<long, int> MyLongInt;
|
||||
|
||||
template <class X1, class Y1, class X2, class Y2>
|
||||
void sanity_check(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||
{
|
||||
@ -267,6 +341,13 @@ namespace
|
||||
BOOST_TEST( (x1 - y1).value() == (x2 - y2) );
|
||||
}
|
||||
|
||||
template <class X1, class Y1, class X2, class Y2>
|
||||
void test_subtractable_left(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||
{
|
||||
sanity_check( x1, y1, x2, y2 );
|
||||
BOOST_TEST( (y1 - x1).value() == (y2 - x2) );
|
||||
}
|
||||
|
||||
template <class X1, class Y1, class X2, class Y2>
|
||||
void test_dividable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||
{
|
||||
@ -275,6 +356,14 @@ namespace
|
||||
BOOST_TEST( (x1 / y1).value() == (x2 / y2) );
|
||||
}
|
||||
|
||||
template <class X1, class Y1, class X2, class Y2>
|
||||
void test_dividable_left(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||
{
|
||||
sanity_check( x1, y1, x2, y2 );
|
||||
if ( x2 != 0 )
|
||||
BOOST_TEST( (y1 / x1).value() == (y2 / x2) );
|
||||
}
|
||||
|
||||
template <class X1, class Y1, class X2, class Y2>
|
||||
void test_modable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||
{
|
||||
@ -283,6 +372,14 @@ namespace
|
||||
BOOST_TEST( (x1 % y1).value() == (x2 % y2) );
|
||||
}
|
||||
|
||||
template <class X1, class Y1, class X2, class Y2>
|
||||
void test_modable_left(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||
{
|
||||
sanity_check( x1, y1, x2, y2 );
|
||||
if ( x2 != 0 )
|
||||
BOOST_TEST( (y1 % x1).value() == (y2 % x2) );
|
||||
}
|
||||
|
||||
template <class X1, class Y1, class X2, class Y2>
|
||||
void test_xorable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||
{
|
||||
@ -374,6 +471,14 @@ namespace
|
||||
test_decrementable( x1, x2 );
|
||||
}
|
||||
|
||||
template <class X1, class Y1, class X2, class Y2>
|
||||
void test_left(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||
{
|
||||
test_subtractable_left( x1, y1, x2, y2 );
|
||||
test_dividable_left( x1, y1, x2, y2 );
|
||||
test_modable_left( x1, y1, x2, y2 );
|
||||
}
|
||||
|
||||
template <class Big, class Small>
|
||||
struct tester
|
||||
{
|
||||
@ -388,6 +493,18 @@ namespace
|
||||
}
|
||||
};
|
||||
|
||||
template <class Big, class Small>
|
||||
struct tester_left
|
||||
{
|
||||
void operator()(boost::minstd_rand& randomizer) const
|
||||
{
|
||||
Big b1 = Big( randomizer() );
|
||||
Small s = Small( randomizer() );
|
||||
|
||||
test_left( Wrapped6<Big, Small>(b1), s, b1, s );
|
||||
}
|
||||
};
|
||||
|
||||
// added as a regression test. We had a bug which this uncovered.
|
||||
struct Point
|
||||
: boost::addable<Point
|
||||
@ -427,6 +544,13 @@ template Wrapped2<unsigned int, unsigned char>;
|
||||
template Wrapped2<unsigned long, unsigned int>;
|
||||
template Wrapped2<unsigned long, unsigned char>;
|
||||
template Wrapped2<unsigned long, unsigned long>;
|
||||
|
||||
template Wrapped6<long, int>;
|
||||
template Wrapped6<long, signed char>;
|
||||
template Wrapped6<int, signed char>;
|
||||
template Wrapped6<unsigned long, unsigned int>;
|
||||
template Wrapped6<unsigned long, unsigned char>;
|
||||
template Wrapped6<unsigned int, unsigned char>;
|
||||
#endif
|
||||
|
||||
#define PRIVATE_EXPR_TEST(e, t) BOOST_TEST( ((e), (t)) )
|
||||
@ -445,7 +569,7 @@ test_main( int , char * [] )
|
||||
|
||||
cout << "Created point, and operated on it." << endl;
|
||||
|
||||
for (int n = 0; n < 10000; ++n)
|
||||
for (int n = 0; n < 1000; ++n) // was 10,000 but took too long (Beman)
|
||||
{
|
||||
boost::minstd_rand r;
|
||||
tester<long, int>()(r);
|
||||
@ -459,6 +583,14 @@ test_main( int , char * [] )
|
||||
tester<unsigned long, unsigned long>()(r);
|
||||
tester<unsigned int, unsigned int>()(r);
|
||||
tester<unsigned int, unsigned char>()(r);
|
||||
|
||||
tester_left<long, int>()(r);
|
||||
tester_left<long, signed char>()(r);
|
||||
tester_left<int, signed char>()(r);
|
||||
|
||||
tester_left<unsigned long, unsigned int>()(r);
|
||||
tester_left<unsigned long, unsigned char>()(r);
|
||||
tester_left<unsigned int, unsigned char>()(r);
|
||||
}
|
||||
|
||||
cout << "Did random tester loop." << endl;
|
||||
@ -653,5 +785,106 @@ test_main( int , char * [] )
|
||||
|
||||
cout << "Performed tests on MyShort objects.\n";
|
||||
|
||||
MyDoubleInt di1(1);
|
||||
MyDoubleInt di2(2.);
|
||||
MyDoubleInt half(0.5);
|
||||
MyDoubleInt di;
|
||||
MyDoubleInt tmp;
|
||||
|
||||
BOOST_TEST( di1.value() == 1 );
|
||||
BOOST_TEST( di2.value() == 2 );
|
||||
BOOST_TEST( di2.value() == 2 );
|
||||
BOOST_TEST( di.value() == 0 );
|
||||
|
||||
cout << "Created MyDoubleInt objects.\n";
|
||||
|
||||
PRIVATE_EXPR_TEST( (di = di2), (di.value() == 2) );
|
||||
|
||||
BOOST_TEST( di2 == di );
|
||||
BOOST_TEST( 2 == di );
|
||||
BOOST_TEST( di == 2 );
|
||||
BOOST_TEST( di1 < di2 );
|
||||
BOOST_TEST( 1 < di2 );
|
||||
BOOST_TEST( di1 <= di2 );
|
||||
BOOST_TEST( 1 <= di2 );
|
||||
BOOST_TEST( di2 > di1 );
|
||||
BOOST_TEST( di2 > 1 );
|
||||
BOOST_TEST( di2 >= di1 );
|
||||
BOOST_TEST( di2 >= 1 );
|
||||
BOOST_TEST( di1 / di2 == half );
|
||||
BOOST_TEST( di1 / 2 == half );
|
||||
BOOST_TEST( 1 / di2 == half );
|
||||
PRIVATE_EXPR_TEST( (tmp=di1), ((tmp/=2) == half) );
|
||||
PRIVATE_EXPR_TEST( (tmp=di1), ((tmp/=di2) == half) );
|
||||
BOOST_TEST( di1 * di2 == di2 );
|
||||
BOOST_TEST( di1 * 2 == di2 );
|
||||
BOOST_TEST( 1 * di2 == di2 );
|
||||
PRIVATE_EXPR_TEST( (tmp=di1), ((tmp*=2) == di2) );
|
||||
PRIVATE_EXPR_TEST( (tmp=di1), ((tmp*=di2) == di2) );
|
||||
BOOST_TEST( di2 - di1 == di1 );
|
||||
BOOST_TEST( di2 - 1 == di1 );
|
||||
BOOST_TEST( 2 - di1 == di1 );
|
||||
PRIVATE_EXPR_TEST( (tmp=di2), ((tmp-=1) == di1) );
|
||||
PRIVATE_EXPR_TEST( (tmp=di2), ((tmp-=di1) == di1) );
|
||||
BOOST_TEST( di1 + di1 == di2 );
|
||||
BOOST_TEST( di1 + 1 == di2 );
|
||||
BOOST_TEST( 1 + di1 == di2 );
|
||||
PRIVATE_EXPR_TEST( (tmp=di1), ((tmp+=1) == di2) );
|
||||
PRIVATE_EXPR_TEST( (tmp=di1), ((tmp+=di1) == di2) );
|
||||
|
||||
cout << "Performed tests on MyDoubleInt objects.\n";
|
||||
|
||||
MyLongInt li1(1);
|
||||
MyLongInt li2(2);
|
||||
MyLongInt li;
|
||||
MyLongInt tmp2;
|
||||
|
||||
BOOST_TEST( li1.value() == 1 );
|
||||
BOOST_TEST( li2.value() == 2 );
|
||||
BOOST_TEST( li.value() == 0 );
|
||||
|
||||
cout << "Created MyLongInt objects.\n";
|
||||
|
||||
PRIVATE_EXPR_TEST( (li = li2), (li.value() == 2) );
|
||||
|
||||
BOOST_TEST( li2 == li );
|
||||
BOOST_TEST( 2 == li );
|
||||
BOOST_TEST( li == 2 );
|
||||
BOOST_TEST( li1 < li2 );
|
||||
BOOST_TEST( 1 < li2 );
|
||||
BOOST_TEST( li1 <= li2 );
|
||||
BOOST_TEST( 1 <= li2 );
|
||||
BOOST_TEST( li2 > li1 );
|
||||
BOOST_TEST( li2 > 1 );
|
||||
BOOST_TEST( li2 >= li1 );
|
||||
BOOST_TEST( li2 >= 1 );
|
||||
BOOST_TEST( li1 % li2 == li1 );
|
||||
BOOST_TEST( li1 % 2 == li1 );
|
||||
BOOST_TEST( 1 % li2 == li1 );
|
||||
PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2%=2) == li1) );
|
||||
PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2%=li2) == li1) );
|
||||
BOOST_TEST( li1 / li2 == 0 );
|
||||
BOOST_TEST( li1 / 2 == 0 );
|
||||
BOOST_TEST( 1 / li2 == 0 );
|
||||
PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2/=2) == 0) );
|
||||
PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2/=li2) == 0) );
|
||||
BOOST_TEST( li1 * li2 == li2 );
|
||||
BOOST_TEST( li1 * 2 == li2 );
|
||||
BOOST_TEST( 1 * li2 == li2 );
|
||||
PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2*=2) == li2) );
|
||||
PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2*=li2) == li2) );
|
||||
BOOST_TEST( li2 - li1 == li1 );
|
||||
BOOST_TEST( li2 - 1 == li1 );
|
||||
BOOST_TEST( 2 - li1 == li1 );
|
||||
PRIVATE_EXPR_TEST( (tmp2=li2), ((tmp2-=1) == li1) );
|
||||
PRIVATE_EXPR_TEST( (tmp2=li2), ((tmp2-=li1) == li1) );
|
||||
BOOST_TEST( li1 + li1 == li2 );
|
||||
BOOST_TEST( li1 + 1 == li2 );
|
||||
BOOST_TEST( 1 + li1 == li2 );
|
||||
PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2+=1) == li2) );
|
||||
PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2+=li1) == li2) );
|
||||
|
||||
cout << "Performed tests on MyLongInt objects.\n";
|
||||
|
||||
return boost::exit_success;
|
||||
}
|
||||
|
177
permutation_iterator.htm
Normal file
177
permutation_iterator.htm
Normal file
@ -0,0 +1,177 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>Permutation Iterator Adaptor Documentation</title>
|
||||
</head>
|
||||
|
||||
<body bgcolor="#FFFFFF" text="#000000">
|
||||
|
||||
<h1>Permutation Iterator Adaptor</h1>
|
||||
<p>Defined in header <a href="../../boost/permutation_iterator.hpp">boost/permutation_iterator.hpp</a></p>
|
||||
<p>The permutation iterator adaptor provides an iterator to a permutation of a given range.
|
||||
(<a href="http://www.cut-the-knot.com/do_you_know/permutation.html">see definition of permutation</a>).
|
||||
The adaptor takes two arguments
|
||||
<ul>
|
||||
<li>an iterator to the range V on which the <a href="http://www.cut-the-knot.com/do_you_know/permutation.html">permutation</a> will be applied</li>
|
||||
<li>the reindexing scheme that defines how the elements of V will be permuted.</li>
|
||||
</ul>
|
||||
|
||||
<p>Note that the permutation iterator is not limited to strict permutations of the given range V.
|
||||
The distance between begin and end of the reindexing iterators is allowed to be smaller compared to the
|
||||
size of the range V, in which case the permutation iterator only provides a permutation of a subrange of V.
|
||||
The indexes neither need to be unique. In this same context, it must be noted that the past the end permutation iterator is
|
||||
completely defined by means of the past-the-end iterator to the indices</p>
|
||||
|
||||
<h2>Synopsis</h2>
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
namespace boost {
|
||||
template <class IndexIterator>
|
||||
class permutation_iterator_policies;
|
||||
|
||||
template <class ElementIterator, class IndexIterator>
|
||||
class permutation_iterator_generator;
|
||||
|
||||
template <class ElementIterator, class IndexIterator>
|
||||
typename permutation_iterator_generator<ElementIterator, IndexIterator>::type
|
||||
make_permutation_iterator(ElementIterator& base, IndexIterator& indexing);
|
||||
}
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
|
||||
<h2>The Permutation Iterator Generator Class Template</h2>
|
||||
|
||||
<p>The <code>permutation_iterator_generator</code> is a helper class whose purpose
|
||||
is to construct a permutation iterator <strong>type</strong>. This class has
|
||||
two template arguments, the first being the iterator type over the range V, the
|
||||
second being the type of the iterator over the indices.
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
template <class ElementIterator, class IndexIterator>
|
||||
class permutation_iterator_generator
|
||||
{
|
||||
public:
|
||||
typedef <a href="iterator_adaptors.htm#iterator_adaptor">iterator_adaptor</a><...> type; // the resulting permutation iterator type
|
||||
}
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
|
||||
<h3>Template Parameters</h3>
|
||||
|
||||
<table border>
|
||||
<tr>
|
||||
<th>Parameter</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><tt>ElementIterator</tt></td>
|
||||
<td>The iterator over the elements to be permuted. This type must be a model
|
||||
of <a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">RandomAccessIterator</a></td>
|
||||
</td>
|
||||
|
||||
<tr>
|
||||
<td><tt>IndexIterator</tt></td>
|
||||
<td>The iterator over the new indexing scheme. This type must at least be a model
|
||||
of <a href="http://www.sgi.com/tech/stl/ForwardIterator.html">ForwardIterator</a>.
|
||||
The <code>IndexIterator::value_type</code> must be convertible to the
|
||||
<code>ElementIterator::difference_type</code>.</td>
|
||||
</table>
|
||||
|
||||
<h3>Concept Model</h3>
|
||||
The permutation iterator is always a model of the same concept as the IndexIterator.
|
||||
|
||||
<h3>Members</h3>
|
||||
The permutation iterator implements the member functions
|
||||
and operators required for the
|
||||
<a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random Access Iterator</a>
|
||||
concept. However, the permutation iterator can only meet the complexity guarantees
|
||||
of the same concept as the IndexIterator. Thus for instance, although the permutation
|
||||
iterator provides <code>operator+=(distance)</code>, this operation will take linear time
|
||||
in case the IndexIterator is a model of ForwardIterator instead of amortized constant time.
|
||||
|
||||
<br>
|
||||
|
||||
<h2><a name="make_generator_iterator">The Permutation Iterator Object Generator</a></h2>
|
||||
|
||||
The <code>make_permutation_iterator()</code> function provides a
|
||||
convenient way to create permutation iterator objects. The function
|
||||
saves the user the trouble of explicitly writing out the iterator
|
||||
types.
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
template <class ElementIterator, class IndexIterator >
|
||||
typename permutation_iterator_generator<ElementIterator, IndexIterator>::type
|
||||
make_permutation_iterator(ElementIterator& base, IndexIterator& indices);
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<h2>Example</h2>
|
||||
<blockquote>
|
||||
<pre>
|
||||
using namespace boost;
|
||||
int i = 0;
|
||||
|
||||
typedef std::vector< int > element_range_type;
|
||||
typedef std::list< int > index_type;
|
||||
|
||||
static const int element_range_size = 10;
|
||||
static const int index_size = 4;
|
||||
|
||||
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);
|
||||
|
||||
index_type indices( index_size );
|
||||
for(index_type::iterator i_it = indices.begin() ; i_it != indices.end() ; ++i_it ) *i_it = element_range_size - index_size + std::distance(indices.begin(), i_it);
|
||||
std::reverse( indices.begin(), indices.end() );
|
||||
|
||||
typedef permutation_iterator_generator< element_range_type::iterator, index_type::iterator >::type permutation_type;
|
||||
permutation_type begin = make_permutation_iterator( elements.begin(), indices.begin() );
|
||||
permutation_type it = begin;
|
||||
permutation_type end = make_permutation_iterator( elements.begin(), indices.end() );
|
||||
|
||||
std::cout << "The original range is : ";
|
||||
std::copy( elements.begin(), elements.end(), std::ostream_iterator< int >( std::cout, " " ) );
|
||||
std::cout << "\n";
|
||||
|
||||
std::cout << "The reindexing scheme is : ";
|
||||
std::copy( indices.begin(), indices.end(), std::ostream_iterator< int >( std::cout, " " ) );
|
||||
std::cout << "\n";
|
||||
|
||||
std::cout << "The permutated range is : ";
|
||||
std::copy( begin, end, std::ostream_iterator< int >( std::cout, " " ) );
|
||||
std::cout << "\n";
|
||||
|
||||
std::cout << "Elements at even indices in the permutation : ";
|
||||
it = begin;
|
||||
for(i = 0; i < index_size / 2 ; ++i, it+=2 ) std::cout << *it << " ";
|
||||
std::cout << "\n";
|
||||
|
||||
std::cout << "Permutation backwards : ";
|
||||
it = begin + (index_size);
|
||||
assert( it != begin );
|
||||
for( ; it-- != begin ; ) std::cout << *it << " ";
|
||||
std::cout << "\n";
|
||||
|
||||
std::cout << "Iterate backward with stride 2 : ";
|
||||
it = begin + (index_size - 1);
|
||||
for(i = 0 ; i < index_size / 2 ; ++i, it-=2 ) std::cout << *it << " ";
|
||||
std::cout << "\n";
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<br><br><br><hr>
|
||||
Thanks: The permutation iterator is only a small addition to the superb iterator adaptors
|
||||
library of David Abrahams and Jeremy Siek.
|
||||
<br><br>
|
||||
|
||||
Copyright 2001 Toon Knapen.
|
||||
|
||||
</body>
|
||||
</html>
|
115
ref_ct_test.cpp
Normal file
115
ref_ct_test.cpp
Normal file
@ -0,0 +1,115 @@
|
||||
// compile-time test for "boost/ref.hpp" header content
|
||||
// see 'ref_test.cpp' for run-time part
|
||||
|
||||
#include <boost/ref.hpp>
|
||||
#include <boost/type_traits/same_traits.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
|
||||
namespace {
|
||||
|
||||
template< typename T, typename U >
|
||||
void ref_test(boost::reference_wrapper<U>)
|
||||
{
|
||||
typedef typename boost::reference_wrapper<U>::type type;
|
||||
BOOST_STATIC_ASSERT((boost::is_same<U,type>::value));
|
||||
BOOST_STATIC_ASSERT((boost::is_same<T,type>::value));
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
void assignable_test(T x)
|
||||
{
|
||||
x = x;
|
||||
}
|
||||
|
||||
template< bool R, typename T >
|
||||
void is_reference_wrapper_test(T)
|
||||
{
|
||||
BOOST_STATIC_ASSERT(boost::is_reference_wrapper<T>::value == R);
|
||||
}
|
||||
|
||||
template< typename R, typename Ref >
|
||||
void cxx_reference_test(Ref)
|
||||
{
|
||||
BOOST_STATIC_ASSERT((boost::is_same<R,Ref>::value));
|
||||
}
|
||||
|
||||
template< typename R, typename Ref >
|
||||
void unwrap_reference_test(Ref)
|
||||
{
|
||||
typedef typename boost::unwrap_reference<Ref>::type type;
|
||||
BOOST_STATIC_ASSERT((boost::is_same<R,type>::value));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int main()
|
||||
{
|
||||
int i = 0;
|
||||
int& ri = i;
|
||||
|
||||
int const ci = 0;
|
||||
int const& rci = ci;
|
||||
|
||||
// 'ref/cref' functions test
|
||||
ref_test<int>(boost::ref(i));
|
||||
ref_test<int>(boost::ref(ri));
|
||||
ref_test<int const>(boost::ref(ci));
|
||||
ref_test<int const>(boost::ref(rci));
|
||||
|
||||
ref_test<int const>(boost::cref(i));
|
||||
ref_test<int const>(boost::cref(ri));
|
||||
ref_test<int const>(boost::cref(ci));
|
||||
ref_test<int const>(boost::cref(rci));
|
||||
|
||||
// test 'assignable' requirement
|
||||
assignable_test(boost::ref(i));
|
||||
assignable_test(boost::ref(ri));
|
||||
assignable_test(boost::cref(i));
|
||||
assignable_test(boost::cref(ci));
|
||||
assignable_test(boost::cref(rci));
|
||||
|
||||
// 'is_reference_wrapper' test
|
||||
is_reference_wrapper_test<true>(boost::ref(i));
|
||||
is_reference_wrapper_test<true>(boost::ref(ri));
|
||||
is_reference_wrapper_test<true>(boost::cref(i));
|
||||
is_reference_wrapper_test<true>(boost::cref(ci));
|
||||
is_reference_wrapper_test<true>(boost::cref(rci));
|
||||
|
||||
is_reference_wrapper_test<false>(i);
|
||||
is_reference_wrapper_test<false, int&>(ri);
|
||||
is_reference_wrapper_test<false>(ci);
|
||||
is_reference_wrapper_test<false, int const&>(rci);
|
||||
|
||||
// ordinary references/function template arguments deduction test
|
||||
cxx_reference_test<int>(i);
|
||||
cxx_reference_test<int>(ri);
|
||||
cxx_reference_test<int>(ci);
|
||||
cxx_reference_test<int>(rci);
|
||||
|
||||
cxx_reference_test<int&, int&>(i);
|
||||
cxx_reference_test<int&, int&>(ri);
|
||||
cxx_reference_test<int const&, int const&>(i);
|
||||
cxx_reference_test<int const&, int const&>(ri);
|
||||
cxx_reference_test<int const&, int const&>(ci);
|
||||
cxx_reference_test<int const&, int const&>(rci);
|
||||
|
||||
// 'unwrap_reference' test
|
||||
unwrap_reference_test<int>(boost::ref(i));
|
||||
unwrap_reference_test<int>(boost::ref(ri));
|
||||
unwrap_reference_test<int const>(boost::cref(i));
|
||||
unwrap_reference_test<int const>(boost::cref(ci));
|
||||
unwrap_reference_test<int const>(boost::cref(rci));
|
||||
|
||||
unwrap_reference_test<int>(i);
|
||||
unwrap_reference_test<int>(ri);
|
||||
unwrap_reference_test<int>(ci);
|
||||
unwrap_reference_test<int>(rci);
|
||||
unwrap_reference_test<int&, int&>(i);
|
||||
unwrap_reference_test<int&, int&>(ri);
|
||||
unwrap_reference_test<int const&, int const&>(i);
|
||||
unwrap_reference_test<int const&, int const&>(ri);
|
||||
unwrap_reference_test<int const&, int const&>(ci);
|
||||
unwrap_reference_test<int const&, int const&>(rci);
|
||||
|
||||
return 0;
|
||||
}
|
74
ref_test.cpp
Normal file
74
ref_test.cpp
Normal file
@ -0,0 +1,74 @@
|
||||
|
||||
// run-time test for "boost/ref.hpp" header content
|
||||
// see 'ref_ct_test.cpp' for compile-time part
|
||||
|
||||
#if defined(_MSC_VER) && !defined(__ICL)
|
||||
# pragma warning(disable: 4786) // identifier truncated in debug info
|
||||
# pragma warning(disable: 4710) // function not inlined
|
||||
# pragma warning(disable: 4711) // function selected for automatic inline expansion
|
||||
# pragma warning(disable: 4514) // unreferenced inline removed
|
||||
#endif
|
||||
|
||||
#include <boost/ref.hpp>
|
||||
|
||||
#if defined(BOOST_MSVC) && (BOOST_MSVC < 1300)
|
||||
# pragma warning(push, 3)
|
||||
#endif
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#if defined(BOOST_MSVC) && (BOOST_MSVC < 1300)
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
|
||||
#define BOOST_INCLUDE_MAIN
|
||||
#include <boost/test/test_tools.hpp>
|
||||
|
||||
namespace {
|
||||
using namespace boost;
|
||||
|
||||
template <class T>
|
||||
struct ref_wrapper
|
||||
{
|
||||
// Used to verify implicit conversion
|
||||
static T* get_pointer(T& x)
|
||||
{
|
||||
return &x;
|
||||
}
|
||||
|
||||
static T const* get_const_pointer(T const& x)
|
||||
{
|
||||
return &x;
|
||||
}
|
||||
|
||||
template <class Arg>
|
||||
static T* passthru(Arg x)
|
||||
{
|
||||
return get_pointer(x);
|
||||
}
|
||||
|
||||
template <class Arg>
|
||||
static T const* cref_passthru(Arg x)
|
||||
{
|
||||
return get_const_pointer(x);
|
||||
}
|
||||
|
||||
static void test(T x)
|
||||
{
|
||||
BOOST_TEST(passthru(ref(x)) == &x);
|
||||
BOOST_TEST(&ref(x).get() == &x);
|
||||
|
||||
BOOST_TEST(cref_passthru(cref(x)) == &x);
|
||||
BOOST_TEST(&cref(x).get() == &x);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace unnamed
|
||||
|
||||
int test_main(int, char * [])
|
||||
{
|
||||
ref_wrapper<int>::test(1);
|
||||
ref_wrapper<int const>::test(1);
|
||||
return 0;
|
||||
}
|
@ -10,23 +10,32 @@
|
||||
|
||||
int main(int, char*[])
|
||||
{
|
||||
char letters[] = "hello world!";
|
||||
const int N = sizeof(letters)/sizeof(char) - 1;
|
||||
char letters_[] = "hello world!";
|
||||
const int N = sizeof(letters_)/sizeof(char) - 1;
|
||||
#ifdef BOOST_NO_STD_ITERATOR_TRAITS
|
||||
// Assume there won't be proper iterator traits for pointers. This
|
||||
// is just a wrapper for char* which has the right traits.
|
||||
typedef boost::iterator_adaptor<char*, boost::default_iterator_policies, char> base_iterator;
|
||||
#else
|
||||
typedef char* base_iterator;
|
||||
#endif
|
||||
base_iterator letters(letters_);
|
||||
|
||||
std::cout << "original sequence of letters:\t"
|
||||
<< letters << std::endl;
|
||||
<< letters_ << std::endl;
|
||||
|
||||
std::sort(letters, letters + N);
|
||||
|
||||
// Use reverse_iterator_generator to print a sequence
|
||||
// of letters in reverse order.
|
||||
|
||||
boost::reverse_iterator_generator<char*>::type
|
||||
boost::reverse_iterator_generator<base_iterator>::type
|
||||
reverse_letters_first(letters + N),
|
||||
reverse_letters_last(letters);
|
||||
|
||||
std::cout << "letters in descending order:\t";
|
||||
std::copy(reverse_letters_first, reverse_letters_last,
|
||||
std::ostream_iterator<char>(std::cout));
|
||||
std::ostream_iterator<char>(std::cout));
|
||||
std::cout << std::endl;
|
||||
|
||||
// Use make_reverse_iterator() to print the sequence
|
||||
@ -34,8 +43,8 @@ int main(int, char*[])
|
||||
|
||||
std::cout << "letters in ascending order:\t";
|
||||
std::copy(boost::make_reverse_iterator(reverse_letters_last),
|
||||
boost::make_reverse_iterator(reverse_letters_first),
|
||||
std::ostream_iterator<char>(std::cout));
|
||||
boost::make_reverse_iterator(reverse_letters_first),
|
||||
std::ostream_iterator<char>(std::cout));
|
||||
std::cout << std::endl;
|
||||
|
||||
return 0;
|
||||
|
332
shared_container_iterator.html
Normal file
332
shared_container_iterator.html
Normal file
@ -0,0 +1,332 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
|
||||
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
|
||||
<meta name="ProgId" content="FrontPage.Editor.Document">
|
||||
<title>Shared Container Iterator Documentation</title>
|
||||
</head>
|
||||
|
||||
<body bgcolor="#FFFFFF" text="#000000">
|
||||
|
||||
<img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)"
|
||||
align="center" width="277" height="86">
|
||||
|
||||
<h1>Shared Container Iterator</h1>
|
||||
|
||||
Defined in header
|
||||
<a href="../../boost/shared_container_iterator.hpp">boost/shared_container_iterator.hpp</a>
|
||||
|
||||
<p>
|
||||
The purpose of the shared container iterator is to attach the lifetime
|
||||
of a container to the lifetime of its iterators. In other words,
|
||||
the container will be deleted after the last iterator is destroyed.
|
||||
The shared container iterator is typically used to implement functions
|
||||
that return iterators over a
|
||||
range of objects that will only be needed for the lifetime of
|
||||
the iterators. By returning a pair of shared iterators from a
|
||||
function, the callee can ensure that the underlying container's
|
||||
lifetime will be properly managed.
|
||||
<p>
|
||||
The shared container iterator augments an iterator into a shared
|
||||
container with a reference counted pointer to the container.
|
||||
Assuming no other references exist to the container, it will be
|
||||
destroyed when the last shared container iterator is destroyed.
|
||||
In all other ways, the shared container iterator
|
||||
behaves the same as its base iterator.
|
||||
|
||||
|
||||
<h2>Synopsis</h2>
|
||||
|
||||
<pre>
|
||||
namespace boost {
|
||||
template <typename <a href="http://www.sgi.com/tech/stl/Container.html">Container</a>>
|
||||
class shared_container_iterator_generator;
|
||||
|
||||
template <typename <a href="http://www.sgi.com/tech/stl/Container.html">Container</a>>
|
||||
typename shared_container_iterator_generator<Container>::type
|
||||
make_shared_container_iterator(typename Container::iterator base,
|
||||
boost::shared_ptr<Container> const& container);
|
||||
|
||||
std::pair<
|
||||
typename shared_container_iterator_generator<Container>::type,
|
||||
typename shared_container_iterator_generator<Container>::type
|
||||
>
|
||||
make_shared_container_range(boost::shared_ptr<Container> const& container);
|
||||
|
||||
}
|
||||
</pre>
|
||||
|
||||
<hr>
|
||||
|
||||
<h2><a name="generator">The Shared Container Iterator Type Generator</a></h2>
|
||||
|
||||
The class <tt>shared_container_iterator_generator</tt> is a helper
|
||||
class to construct a shared container iterator type. The template
|
||||
parameter for this class is a type that models the
|
||||
<a href="http://www.sgi.com/tech/stl/Container.html">Container</a>
|
||||
concept.
|
||||
|
||||
<pre>
|
||||
template <typename Container>
|
||||
class shared_container_iterator_generator
|
||||
{
|
||||
public:
|
||||
typedef <a href="./iterator_adaptors.htm#iterator_adaptor">iterator_adaptor</a><...> type;
|
||||
};
|
||||
</pre>
|
||||
|
||||
<h3>Example</h3>
|
||||
|
||||
<p>
|
||||
The following example illustrates how to use the
|
||||
<tt>shared_counter_iterator_generator</tt> to create an iterator that
|
||||
regulates the lifetime of a reference counted <tt>std::vector</tt>.
|
||||
Though the original <tt>shared_ptr</tt> to the vector ceases to exist, the
|
||||
<tt>shared_counter_iterator</tt>s extend the lifetime of the container.
|
||||
<p>
|
||||
<a href="./shared_iterator_example1.cpp">shared_iterator_example1.cpp</a>:
|
||||
<PRE>
|
||||
<font color="#008040">#include "shared_container_iterator.hpp"</font>
|
||||
<font color="#008040">#include "boost/shared_ptr.hpp"</font>
|
||||
<font color="#008040">#include <algorithm></font>
|
||||
<font color="#008040">#include <iostream></font>
|
||||
<font color="#008040">#include <vector></font>
|
||||
|
||||
<B>typedef</B> boost::shared_container_iterator_generator< std::vector<<B>int</B>> >::type iterator;
|
||||
|
||||
|
||||
<B>void</B> set_range(iterator& i, iterator& end) {
|
||||
|
||||
boost::shared_ptr< std::vector<<B>int</B>> > ints(<B>new</B> std::vector<<B>int</B>>());
|
||||
|
||||
ints->push_back(<font color="#0000A0">0</font>);
|
||||
ints->push_back(<font color="#0000A0">1</font>);
|
||||
ints->push_back(<font color="#0000A0">2</font>);
|
||||
ints->push_back(<font color="#0000A0">3</font>);
|
||||
ints->push_back(<font color="#0000A0">4</font>);
|
||||
ints->push_back(<font color="#0000A0">5</font>);
|
||||
|
||||
i = iterator(ints->begin(),ints);
|
||||
end = iterator(ints->end(),ints);
|
||||
}
|
||||
|
||||
|
||||
<B>int</B> main() {
|
||||
|
||||
iterator i,end;
|
||||
|
||||
set_range(i,end);
|
||||
|
||||
std::copy(i,end,std::ostream_iterator<<B>int</B>>(std::cout,<font color="#0000FF">","</font>));
|
||||
std::cout.put(<font color="#0000FF">'\n'</font>);
|
||||
|
||||
<B>return</B> <font color="#0000A0">0</font>;
|
||||
}
|
||||
</PRE>
|
||||
|
||||
The output from this part is:
|
||||
<pre>
|
||||
0,1,2,3,4,5,
|
||||
</pre>
|
||||
|
||||
<h3>Template Parameters</h3>
|
||||
|
||||
<Table border>
|
||||
<TR>
|
||||
<TH>Parameter</TH><TH>Description</TH>
|
||||
</TR>
|
||||
|
||||
<TR>
|
||||
<TD><a
|
||||
href="http://www.sgi.com/tech/stl/Container.html"><tt>Container</tt></a></TD>
|
||||
<TD>The type of the container that we wish to iterate over. It must be
|
||||
a model of the
|
||||
<a href="http://www.sgi.com/tech/stl/Container.html"><tt>Container</tt></a>
|
||||
concept.
|
||||
</TD>
|
||||
</TR>
|
||||
</Table>
|
||||
|
||||
<h3>Model of</h3>
|
||||
|
||||
The shared container iterator adaptor (the type
|
||||
<tt>shared_container_iterator_generator<...>::type</tt>) models the
|
||||
same iterator concept as the base iterator
|
||||
(<tt>Container::iterator</tt>) up to
|
||||
<a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random
|
||||
Access Iterator</a>.
|
||||
|
||||
<h3>Members</h3>
|
||||
|
||||
The shared container iterator type implements the member functions and
|
||||
operators required of the <a
|
||||
href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random Access Iterator</a>
|
||||
concept, though only operations defined for the base iterator will be valid.
|
||||
In addition it has the following constructor:
|
||||
|
||||
<pre>
|
||||
shared_container_iterator_generator::type(Container::iterator const& it,
|
||||
boost::shared_ptr<Container> const& container)
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
<hr>
|
||||
<p>
|
||||
|
||||
|
||||
<h2><a name="make_iterator">The Shared Container Iterator Object Generator</a></h2>
|
||||
|
||||
<pre>
|
||||
template <typename Container>
|
||||
typename shared_container_iterator_generator<AdaptableUnaryFunction,BaseIterator>::type
|
||||
make_shared_container_iterator(Container::iterator base,
|
||||
boost::shared_ptr<Container> const& container)
|
||||
</pre>
|
||||
|
||||
This function provides an alternative to using the shared container
|
||||
iterator type generator to create the iterator type before
|
||||
construction. Using the object generator, a shared container iterator
|
||||
can be created and passed to a function without explicitly specifying
|
||||
its type.
|
||||
|
||||
<h3>Example</h3>
|
||||
|
||||
This example, similar to the previous, uses
|
||||
<tt>make_shared_container_iterator()</tt> to create the iterators.
|
||||
|
||||
<p>
|
||||
<a href="./shared_iterator_example2.cpp">shared_iterator_example2.cpp</a>:
|
||||
|
||||
<PRE>
|
||||
<font color="#008040">#include "shared_container_iterator.hpp"</font>
|
||||
<font color="#008040">#include "boost/shared_ptr.hpp"</font>
|
||||
<font color="#008040">#include <algorithm></font>
|
||||
<font color="#008040">#include <iterator></font>
|
||||
<font color="#008040">#include <iostream></font>
|
||||
<font color="#008040">#include <vector></font>
|
||||
|
||||
|
||||
<B>template</B> <<B>typename</B> Iterator>
|
||||
<B>void</B> print_range_nl (Iterator begin, Iterator end) {
|
||||
<B>typedef</B> <B>typename</B> std::iterator_traits<Iterator>::value_type val;
|
||||
std::copy(begin,end,std::ostream_iterator<val>(std::cout,<font color="#0000FF">","</font>));
|
||||
std::cout.put(<font color="#0000FF">'\n'</font>);
|
||||
}
|
||||
|
||||
|
||||
<B>int</B> main() {
|
||||
|
||||
<B>typedef</B> boost::shared_ptr< std::vector<<B>int</B>> > ints_t;
|
||||
{
|
||||
ints_t ints(<B>new</B> std::vector<<B>int</B>>());
|
||||
|
||||
ints->push_back(<font color="#0000A0">0</font>);
|
||||
ints->push_back(<font color="#0000A0">1</font>);
|
||||
ints->push_back(<font color="#0000A0">2</font>);
|
||||
ints->push_back(<font color="#0000A0">3</font>);
|
||||
ints->push_back(<font color="#0000A0">4</font>);
|
||||
ints->push_back(<font color="#0000A0">5</font>);
|
||||
|
||||
print_range_nl(boost::make_shared_container_iterator(ints->begin(),ints),
|
||||
boost::make_shared_container_iterator(ints->end(),ints));
|
||||
}
|
||||
|
||||
|
||||
|
||||
<B>return</B> <font color="#0000A0">0</font>;
|
||||
}
|
||||
</PRE>
|
||||
|
||||
Observe that the <tt>shared_container_iterator</tt> type is never
|
||||
explicitly named. The output from this example is the same as the previous.
|
||||
|
||||
<h2><a name="make_range">The Shared Container Iterator Range Generator</a></h2>
|
||||
|
||||
<pre>
|
||||
template <typename Container>
|
||||
std::pair<
|
||||
typename shared_container_iterator_generator<Container>::type,
|
||||
typename shared_container_iterator_generator<Container>::type
|
||||
>
|
||||
make_shared_container_range(boost::shared_ptr<Container> const& container);
|
||||
</pre>
|
||||
|
||||
Class <tt>shared_container_iterator</tt> is meant primarily to return
|
||||
via iterators a range of values that we can guarantee will be alive as
|
||||
long as the iterators are. This is a convenience
|
||||
function to do just that. This function is equivalent to
|
||||
|
||||
<pre>
|
||||
std::make_pair(make_shared_container_iterator(container->begin(),container),
|
||||
make_shared_container_iterator(container->end(),container));
|
||||
</pre>
|
||||
|
||||
<h3>Example</h3>
|
||||
|
||||
In the following example, a range of values is returned as a pair of
|
||||
<tt>shared_container_iterator</tt>s.
|
||||
|
||||
|
||||
<p>
|
||||
<a href="./shared_iterator_example3.cpp">shared_iterator_example3.cpp</a>:
|
||||
|
||||
<PRE>
|
||||
<font color="#008040">#include "shared_container_iterator.hpp"</font>
|
||||
<font color="#008040">#include "boost/shared_ptr.hpp"</font>
|
||||
<font color="#008040">#include "boost/tuple/tuple.hpp" // for boost::tie</font>
|
||||
<font color="#008040">#include <algorithm> // for std::copy</font>
|
||||
<font color="#008040">#include <iostream> </font>
|
||||
<font color="#008040">#include <vector></font>
|
||||
|
||||
|
||||
<B>typedef</B> boost::shared_container_iterator_generator< std::vector<<B>int</B>> >::type
|
||||
function_iterator;
|
||||
|
||||
std::pair<function_iterator,function_iterator>
|
||||
return_range() {
|
||||
boost::shared_ptr< std::vector<<B>int</B>> > range(<B>new</B> std::vector<<B>int</B>>());
|
||||
range->push_back(<font color="#0000A0">0</font>);
|
||||
range->push_back(<font color="#0000A0">1</font>);
|
||||
range->push_back(<font color="#0000A0">2</font>);
|
||||
range->push_back(<font color="#0000A0">3</font>);
|
||||
range->push_back(<font color="#0000A0">4</font>);
|
||||
range->push_back(<font color="#0000A0">5</font>);
|
||||
<B>return</B> boost::make_shared_container_range(range);
|
||||
}
|
||||
|
||||
|
||||
<B>int</B> main() {
|
||||
|
||||
|
||||
function_iterator i,end;
|
||||
|
||||
boost::tie(i,end) = return_range();
|
||||
|
||||
std::copy(i,end,std::ostream_iterator<<B>int</B>>(std::cout,<font color="#0000FF">","</font>));
|
||||
std::cout.put(<font color="#0000FF">'\n'</font>);
|
||||
|
||||
<B>return</B> <font color="#0000A0">0</font>;
|
||||
}
|
||||
</PRE>
|
||||
|
||||
Though the <tt>range</tt> object only lives for the duration of the
|
||||
<tt>return_range</tt> call, the reference counted
|
||||
<tt>std::vector</tt> will live until <tt>i</tt> and <tt>end</tt>
|
||||
are both destroyed. The output from this example is the same as
|
||||
the previous two.
|
||||
|
||||
|
||||
<hr>
|
||||
<!-- hhmts start -->
|
||||
Last modified: Wed Sep 4 15:52:17 EST 2002
|
||||
<!-- hhmts end -->
|
||||
<p><EFBFBD> Copyright Ronald Garcia 2002. Permission to copy, use,
|
||||
modify, sell and distribute this document is granted provided this copyright
|
||||
notice appears in all copies. This document is provided "as is"
|
||||
without express or implied warranty, and with no claim as to its suitability for
|
||||
any purpose.</p>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
42
shared_iterator_example1.cpp
Normal file
42
shared_iterator_example1.cpp
Normal file
@ -0,0 +1,42 @@
|
||||
// (C) Copyright Ronald Garcia 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.
|
||||
|
||||
#include "boost/shared_container_iterator.hpp"
|
||||
#include "boost/shared_ptr.hpp"
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
typedef boost::shared_container_iterator_generator< std::vector<int> >::type
|
||||
iterator;
|
||||
|
||||
|
||||
void set_range(iterator& i, iterator& end) {
|
||||
|
||||
boost::shared_ptr< std::vector<int> > ints(new std::vector<int>());
|
||||
|
||||
ints->push_back(0);
|
||||
ints->push_back(1);
|
||||
ints->push_back(2);
|
||||
ints->push_back(3);
|
||||
ints->push_back(4);
|
||||
ints->push_back(5);
|
||||
|
||||
i = iterator(ints->begin(),ints);
|
||||
end = iterator(ints->end(),ints);
|
||||
}
|
||||
|
||||
|
||||
int main() {
|
||||
|
||||
iterator i,end;
|
||||
|
||||
set_range(i,end);
|
||||
|
||||
std::copy(i,end,std::ostream_iterator<int>(std::cout,","));
|
||||
std::cout.put('\n');
|
||||
|
||||
return 0;
|
||||
}
|
42
shared_iterator_example2.cpp
Normal file
42
shared_iterator_example2.cpp
Normal file
@ -0,0 +1,42 @@
|
||||
// (C) Copyright Ronald Garcia 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.
|
||||
|
||||
#include "boost/shared_container_iterator.hpp"
|
||||
#include "boost/shared_ptr.hpp"
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
|
||||
template <typename Iterator>
|
||||
void print_range_nl (Iterator begin, Iterator end) {
|
||||
typedef typename std::iterator_traits<Iterator>::value_type val;
|
||||
std::copy(begin,end,std::ostream_iterator<val>(std::cout,","));
|
||||
std::cout.put('\n');
|
||||
}
|
||||
|
||||
|
||||
int main() {
|
||||
|
||||
typedef boost::shared_ptr< std::vector<int> > ints_t;
|
||||
{
|
||||
ints_t ints(new std::vector<int>());
|
||||
|
||||
ints->push_back(0);
|
||||
ints->push_back(1);
|
||||
ints->push_back(2);
|
||||
ints->push_back(3);
|
||||
ints->push_back(4);
|
||||
ints->push_back(5);
|
||||
|
||||
print_range_nl(boost::make_shared_container_iterator(ints->begin(),ints),
|
||||
boost::make_shared_container_iterator(ints->end(),ints));
|
||||
}
|
||||
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
41
shared_iterator_example3.cpp
Normal file
41
shared_iterator_example3.cpp
Normal file
@ -0,0 +1,41 @@
|
||||
// (C) Copyright Ronald Garcia 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.
|
||||
|
||||
#include "boost/shared_container_iterator.hpp"
|
||||
#include "boost/shared_ptr.hpp"
|
||||
#include "boost/tuple/tuple.hpp" // for boost::tie
|
||||
#include <algorithm> // for std::copy
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
|
||||
typedef boost::shared_container_iterator_generator< std::vector<int> >::type
|
||||
function_iterator;
|
||||
|
||||
std::pair<function_iterator,function_iterator>
|
||||
return_range() {
|
||||
boost::shared_ptr< std::vector<int> > range(new std::vector<int>());
|
||||
range->push_back(0);
|
||||
range->push_back(1);
|
||||
range->push_back(2);
|
||||
range->push_back(3);
|
||||
range->push_back(4);
|
||||
range->push_back(5);
|
||||
return boost::make_shared_container_range(range);
|
||||
}
|
||||
|
||||
|
||||
int main() {
|
||||
|
||||
|
||||
function_iterator i,end;
|
||||
|
||||
boost::tie(i,end) = return_range();
|
||||
|
||||
std::copy(i,end,std::ostream_iterator<int>(std::cout,","));
|
||||
std::cout.put('\n');
|
||||
|
||||
return 0;
|
||||
}
|
@ -14,11 +14,12 @@
|
||||
//
|
||||
// 3 successfully inserted.
|
||||
// 9 was already in the set.
|
||||
// There were 2 occurances of 4.
|
||||
// There were 2 occurrences of 4.
|
||||
|
||||
#include <set>
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <iterator> // std::distance
|
||||
// Note: tie() use to live in boost/utility.hpp, but
|
||||
// not it is part of the more general Boost Tuple Library.
|
||||
#include <boost/tuple/tuple.hpp>
|
||||
@ -41,9 +42,9 @@ main(int, char*[])
|
||||
for (int k = 0; k < 2; ++k) {
|
||||
boost::tie(i,inserted) = s.insert(new_vals[k]);
|
||||
if (!inserted)
|
||||
std::cout << *i << " was already in the set." << std::endl;
|
||||
std::cout << *i << " was already in the set." << std::endl;
|
||||
else
|
||||
std::cout << *i << " successfully inserted." << std::endl;
|
||||
std::cout << *i << " successfully inserted." << std::endl;
|
||||
}
|
||||
}
|
||||
{
|
||||
@ -55,7 +56,7 @@ main(int, char*[])
|
||||
|
||||
boost::tie(i,end) = std::equal_range(vals, vals + 6, 4);
|
||||
std::cout << "There were " << std::distance(i,end)
|
||||
<< " occurances of " << *i << "." << std::endl;
|
||||
<< " occurrences of " << *i << "." << std::endl;
|
||||
// Footnote: of course one would normally just use std::count()
|
||||
// to get this information, but that would spoil the example :)
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ Defined in header
|
||||
|
||||
<p>
|
||||
The transform iterator adaptor augments an iterator by applying some
|
||||
function object to the result of dereferencing the iterator. Another
|
||||
function object to the result of dereferencing the iterator. In other
|
||||
words, the <tt>operator*</tt> of the transform iterator first
|
||||
dereferences the base iterator, passes the result of this to the
|
||||
function object, and then returns the result. The following
|
||||
|
@ -18,15 +18,15 @@ namespace boost {
|
||||
template <class Operation>
|
||||
class binder1st
|
||||
: public std::unary_function<typename Operation::second_argument_type,
|
||||
typename Operation::result_type> {
|
||||
typename Operation::result_type> {
|
||||
protected:
|
||||
Operation op;
|
||||
typename Operation::first_argument_type value;
|
||||
public:
|
||||
binder1st() { } // this had to be added!
|
||||
binder1st(const Operation& x,
|
||||
const typename Operation::first_argument_type& y)
|
||||
: op(x), value(y) {}
|
||||
const typename Operation::first_argument_type& y)
|
||||
: op(x), value(y) {}
|
||||
typename Operation::result_type
|
||||
operator()(const typename Operation::second_argument_type& x) const {
|
||||
return op(value, x);
|
||||
@ -66,8 +66,8 @@ main(int, char*[])
|
||||
std::cout << "adding 4 to each element in the array:" << std::endl;
|
||||
|
||||
std::copy(boost::make_transform_iterator(x, boost::bind1st(std::plus<int>(), 4)),
|
||||
boost::make_transform_iterator(x + N, boost::bind1st(std::plus<int>(), 4)),
|
||||
std::ostream_iterator<int>(std::cout, " "));
|
||||
boost::make_transform_iterator(x + N, boost::bind1st(std::plus<int>(), 4)),
|
||||
std::ostream_iterator<int>(std::cout, " "));
|
||||
std::cout << std::endl;
|
||||
|
||||
return 0;
|
||||
|
43
utility.htm
43
utility.htm
@ -22,6 +22,7 @@
|
||||
checked_array_delete()</a></li>
|
||||
<li>Function templates <a href="#functions next">next() and prior()</a></li>
|
||||
<li>Class <a href="#Class noncopyable">noncopyable</a></li>
|
||||
<li>Function template <a href="#addressof">addressof()</a></li>
|
||||
<li>Function template <a href="tie.html">tie()</a> and supporting class tied.</li>
|
||||
</ul>
|
||||
<h2> Function templates <a name="checked_delete">checked_delete</a>() and
|
||||
@ -133,6 +134,48 @@ emphasize that it is to be used only as a base class. Dave Abrahams notes
|
||||
concern about the effect on compiler optimization of adding (even trivial inline)
|
||||
destructor declarations. He says "Probably this concern is misplaced, because
|
||||
noncopyable will be used mostly for classes which own resources and thus have non-trivial destruction semantics."</p>
|
||||
<h2><a name="addressof">Function template addressof()</a></h2>
|
||||
<p>Function <strong>addressof()</strong> returns the address of an object.</p>
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
template <typename T> inline T* addressof(T& v);
|
||||
template <typename T> inline const T* addressof(const T& v);
|
||||
template <typename T> inline volatile T* addressof(volatile T& v);
|
||||
template <typename T> inline const volatile T* addressof(const volatile T& v);
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
|
||||
<p>C++ allows programmers to replace the unary
|
||||
<strong>operator&()</strong> class member used to get the address of
|
||||
an object. Getting the real address of an object requires ugly
|
||||
casting tricks to avoid invoking the overloaded
|
||||
<strong>operator&()</strong>. Function <strong>addressof()</strong>
|
||||
provides a wrapper around the necessary code to make it easy to get an
|
||||
object's real address.
|
||||
</p>
|
||||
|
||||
<p>The program <a href="addressof_test.cpp">addressof_test.cpp</a> can be
|
||||
used to verify that <b>addressof()</b> works as expected.</p>
|
||||
|
||||
<p>Contributed by Brad King based on ideas from discussion with Doug Gregor.</p>
|
||||
<h3>Example</h3>
|
||||
<blockquote>
|
||||
<pre>#include <boost/utility.hpp>
|
||||
|
||||
struct useless_type {};
|
||||
class nonaddressable {
|
||||
useless_type operator&() const;
|
||||
};
|
||||
|
||||
void f() {
|
||||
nonaddressable x;
|
||||
nonaddressable* xp = boost::addressof(x);
|
||||
// nonaddressable* xpe = &x; /* error */
|
||||
}</pre>
|
||||
</blockquote>
|
||||
|
||||
<h2>Class templates for the Base-from-Member Idiom</h2>
|
||||
<p>See <a href="base_from_member.html">separate documentation</a>.</p>
|
||||
<h2>Function template tie()</h2>
|
||||
|
219
value_init.htm
Normal file
219
value_init.htm
Normal file
@ -0,0 +1,219 @@
|
||||
<html>
|
||||
<head>
|
||||
|
||||
<meta http-equiv="Content-Type"
|
||||
content="text/html; charset=iso-8859-1">
|
||||
<title>value_initialized</title>
|
||||
|
||||
</head>
|
||||
<body vlink="#800080" link="#0000ff" text="#000000" bgcolor="#ffffff">
|
||||
|
||||
<h2><img src="../../c++boost.gif" width="276" height="86">
|
||||
Header <<a href="../../boost/utility/value_init.hpp">boost/utility/value_init.hpp</a>>
|
||||
</h2>
|
||||
|
||||
<h2>Contents</h2>
|
||||
|
||||
<dl>
|
||||
<dt><a href="#intro">Rationale</a></dt>
|
||||
<dt><a href="#rationale">Introduction</a></dt>
|
||||
</dl>
|
||||
|
||||
<ul>
|
||||
<li><a href="#valueinit">value-initialization</a></li>
|
||||
<li><a href="#valueinitsyn">value-initialization syntax</a></li>
|
||||
|
||||
</ul>
|
||||
|
||||
<dl class="page-index">
|
||||
<dt><a href="#types">Types</a></dt>
|
||||
</dl>
|
||||
|
||||
<ul>
|
||||
<li><a href="#val_init"><code>value_initialized<></code></a></li>
|
||||
|
||||
</ul>
|
||||
<a href="#acknowledgements">Acknowledgements</a><br>
|
||||
<br>
|
||||
|
||||
<hr>
|
||||
<h2><a name="rationale"></a>Rationale</h2>
|
||||
|
||||
<p>Constructing and initializing objects in a generic way is difficult in
|
||||
C++. The problem is that there are several different rules that apply
|
||||
for initialization. Depending on the type, the value of a newly constructed
|
||||
object can be zero-initialized (logically 0), default-constructed (using
|
||||
the default constructor), or indeterminate. When writing generic code,
|
||||
this problem must be addressed. <code>value_initialized</code> provides
|
||||
a solution with consistent syntax for value initialization of scalar,
|
||||
union and class types. <br>
|
||||
</p>
|
||||
|
||||
<h2><a name="into"></a>Introduction</h2>
|
||||
|
||||
<p>The C++ standard [<a href="#references">1</a>] contains the definitions
|
||||
of <code>zero-initialization</code> and <code>default-initialization</code>.
|
||||
Informally, zero-initialization means that the object is given the initial
|
||||
value 0 (converted to the type) and default-initialization means that
|
||||
POD [<a href="#references">2</a>] types are zero-initialized, while class
|
||||
types are initialized with their corresponding default constructors. A
|
||||
<i>declaration</i> can contain an <i>initializer</i>, which specifies the
|
||||
object's initial value. The initializer can be just '()', which states that
|
||||
the object shall be default-initialized (but see below). However, if a <i>declaration</i>
|
||||
has no <i>initializer</i> and it is of a non-<code>const</code>, non-<code>static</code>
|
||||
POD type, the initial value is indeterminate:<cite>(see §8.5 for the
|
||||
accurate definitions).</cite></p>
|
||||
|
||||
<pre>int x ; // no initializer. x value is indeterminate.<br>std::string s ; // no initializer, s is default-constructed.<br><br>int y = int() ; <br>// y is initialized using copy-initialization<br>// but the temporary uses an empty set of parentheses as the initializer,<br>// so it is default-constructed.<br>// A default constructed POD type is zero-initialized,<br>// therefore, y == 0.<br><br>void foo ( std::string ) ;<br>foo ( std::string() ) ; <br>// the temporary string is default constructed <br>// as indicated by the initializer () </pre>
|
||||
|
||||
<h3><a name="valueinit">value-initialization</a></h3>
|
||||
|
||||
<p>The first <a
|
||||
href="http://anubis.dkuug.dk/JTC1/SC22/WG21/docs/cwg_defects.html">Technical
|
||||
Corrigendum for the C++ Standard</a> (TC1), whose draft was released to
|
||||
the public in November 2001, introduced <a
|
||||
href="http://anubis.dkuug.dk/JTC1/SC22/WG21/docs/cwg_defects.html#178">Core
|
||||
Issue 178</a> (among many other issues, of course).</p>
|
||||
|
||||
<p> That issue introduced the new concept of <code>value-initialization</code>
|
||||
(it also fixed the wording for zero-initialization). Informally, value-initialization
|
||||
is similar to default-initialization with the exception that in some cases
|
||||
non-static data members and base class sub-objects are also value-initialized.
|
||||
The difference is that an object that is value-initialized won't have
|
||||
(or at least is less likely to have) indeterminate values for data members
|
||||
and base class sub-objects; unlike the case of an object default constructed.
|
||||
(see Core Issue 178 for a normative description).</p>
|
||||
|
||||
<p>In order to specify value-initialization of an object we need to use the
|
||||
empty-set initializer: (). </p>
|
||||
|
||||
<p><i>(but recall that the current C++ Standard states that '()' invokes default-initialization,
|
||||
not value-initialization)</i></p>
|
||||
|
||||
<p>As before, a declaration with no intializer specifies default-initialization,
|
||||
and a declaration with a non-empty initializer specifies copy (=xxx) or
|
||||
direct (xxx) initialization. </p>
|
||||
|
||||
<pre>template<class T> void eat(T);<br>int x ; // indeterminate initial value.<br>std::string s; // default-initialized.<br>eat ( int() ) ; // value-initialized<br>eat ( std::string() ) ; // value-initialied</pre>
|
||||
|
||||
<h4><a name="valueinitsyn">value-initialization</a> syntax</h4>
|
||||
|
||||
<p>Value initialization is specified using (). However, the empty set of
|
||||
parentheses is not permitted by the syntax of initializers because it is
|
||||
parsed as the declaration of a function taking no arguments: </p>
|
||||
|
||||
<pre>int x() ; // declares function int(*)()<br>int y ( int() ) ; // decalares function int(*)( int(*)() )</pre>
|
||||
|
||||
<p>Thus, the empty () must be put in some other initialization context.</p>
|
||||
|
||||
<p>One alternative is to use copy-initialization syntax:</p>
|
||||
|
||||
<pre>int x = int() ;</pre>
|
||||
|
||||
<p>This works perfectly fine for POD types. But for non-POD class types,
|
||||
copy-initialization searches for a suitable constructor, which could be,
|
||||
for instance, the copy-constructor (it also searches for a suitable conversion
|
||||
sequence but this doesn't apply in this context). For an arbitrary unknown
|
||||
type, using this syntax may not have the value-initialization effect intended
|
||||
because we don't know if a copy from a default constructed object is exactly
|
||||
the same as a default constructed object, and the compiler is allowed (in
|
||||
some cases), but never required to, optimize the copy away.</p>
|
||||
|
||||
<p>One possible generic solution is to use value-initialization of a non static
|
||||
data member:</p>
|
||||
|
||||
<pre>template<class T> <br>struct W <br>{<br> // value-initialization of 'data' here.<br> W() : data() {}<br> T data ;<br>} ;<br>W<int> w ;<br>// w.data is value-initialized for any type. </pre>
|
||||
|
||||
<p><code>This is the solution supplied by the value_initialized<> template
|
||||
class.</code></p>
|
||||
|
||||
<h2><a name="types"></a>Types</h2>
|
||||
|
||||
<h2><a name="val_init"><code>template class value_initialized<T></code></a></h2>
|
||||
|
||||
<pre>namespace boost {<br><br>template<class T><br>class value_initialized<br>{<br> public :<br> value_initialized() : x() {}<br> operator T&() const { return x ; }<br> T& data() const { return x ; }<br><br> private :<br> <i>impll-defined</i> x ;<br>} ;<br><br>template<class T><br>T const& get ( value_initialized<T> const& x )<br>{<br> return x.data() ;<br>}<br><br>template<class T><br>T& get ( value_initialized<T>& x )<br>{<br> return x.data() ;<br>}<br><br>} // namespace boost<br></pre>
|
||||
|
||||
<p>An object of this template class is a <code>T</code>-wrapper convertible
|
||||
to <code>'T&'</code> whose wrapped object (data member of type <code>T</code>)
|
||||
is <a href="#valueinit">value-initialized</a> upon default-initialization
|
||||
of this wrapper class: </p>
|
||||
|
||||
<pre>int zero = 0 ;<br>value_initialized<int> x ;<br>assert ( x == zero ) ;<br><br>std::string def ;<br>value_initialized< std::string > y ;<br>assert ( y == def ) ;<br></pre>
|
||||
|
||||
<p>The purpose of this wrapper is to provide a consistent syntax for value
|
||||
initialization of scalar, union and class types (POD and non-POD) since
|
||||
the correct syntax for value initialization varies (see <a
|
||||
href="#valueinitsyn">value-initialization syntax</a>)</p>
|
||||
|
||||
<p>The wrapped object can be accessed either through the conversion operator
|
||||
<code>T&</code>, the member function <code>data()</code>, or the
|
||||
non-member function <code>get()</code>: </p>
|
||||
|
||||
<pre>void watch(int);<br>value_initialized<int> x;<br><br>watch(x) ; // operator T& used.<br>watch(x.data());<br>watch( get(x) ) // function get() used</pre>
|
||||
|
||||
<p>Both <code>const</code> and non-<code>const</code> objects can be wrapped.
|
||||
Mutable objects can be modified directly from within the wrapper but constant
|
||||
objects cannot:</p>
|
||||
|
||||
<pre>value_initialized<int> x ; <br>static_cast<int&>(x) = 1 ; // OK<br>get(x) = 1 ; // OK<br><br>value_initialized<int const> y ; <br>static_cast<int&>(y) = 1 ; // ERROR: cannot cast to int&<br>static_cast<int const&>(y) = 1 ; // ERROR: cannot modify a const value<br>get(y) = 1 ; // ERROR: cannot modify a const value</pre>
|
||||
|
||||
<h3>Warning:</h3>
|
||||
|
||||
<p>Both the conversion operator and the <code>data()</code> member function
|
||||
are <code>const</code> in order to allow access to the wrapped object
|
||||
from a constant wrapper:</p>
|
||||
|
||||
<pre>void foo(int);<br>value_initialized<int> const x ;<br>foo(x);<br></pre>
|
||||
|
||||
<p>But notice that this conversion operator is to <code>T&</code> although
|
||||
it is itself <code>const</code>. As a consequence, if <code>T</code> is
|
||||
a non-<code>const</code> type, you can modify the wrapped object even from
|
||||
within a constant wrapper:</p>
|
||||
|
||||
<pre>value_initialized<int> const x_c ;<br>int& xr = x_c ; // OK, conversion to int& available even though x_c is itself const.<br>xr = 2 ; </pre>
|
||||
|
||||
<p>The reason for this obscure behavior is that some commonly used compilers
|
||||
just don't accept the following valid code:</p>
|
||||
|
||||
<pre>struct X<br>{<br> operator int&() ;<br> operator int const&() const ; <br>};<br>X x ;<br>(x == 1 ) ; // ERROR HERE!</pre>
|
||||
|
||||
<p>These compilers complain about ambiguity between the conversion operators.
|
||||
This complaint is incorrect, but the only workaround that I know of is
|
||||
to provide only one of them, which leads to the obscure behavior just explained.<br>
|
||||
</p>
|
||||
|
||||
<h3>Recommended practice: The non-member get() idiom</h3>
|
||||
|
||||
<p>The obscure behavior of being able to modify a non-<code>const</code>
|
||||
wrapped object from within a constant wrapper can be avoided if access to
|
||||
the wrapped object is always performed with the <code>get()</code> idiom:</p>
|
||||
|
||||
<pre>value_initialized<int> x ;<br>get(x) = 1 ; // OK<br><br>value_initialized<int const> cx ;<br>get(x) = 1 ; // ERROR: Cannot modify a const object<br><br>value_initialized<int> const x_c ;<br>get(x_c) = 1 ; // ERROR: Cannot modify a const object<br><br>value_initialized<int const> const cx_c ;<br>get(cx_c) = 1 ; // ERROR: Cannot modify a const object<br></pre>
|
||||
|
||||
<h3><a name="references">References</a></h3>
|
||||
[1] The C++ Standard, ISO/IEC 14882:98 <br>
|
||||
[2] Plain Old Data
|
||||
<h3><a name="acknowledgements"></a>Acknowledgements</h3>
|
||||
value_initialized was developed by Fernando Cacciola, with help and
|
||||
suggestions from David Abrahams and Darin Adler.<br>
|
||||
Special thanks to Bj<42>rn Karlsson who carefully edited and completed this documentation.
|
||||
<pre> </pre>
|
||||
|
||||
<hr>
|
||||
<p>Revised 19 September 2002</p>
|
||||
|
||||
<p>© Copyright boost.org 2002. Permission to copy, use, modify, sell
|
||||
and distribute this document is granted provided this copyright notice appears
|
||||
in all copies. This document is provided "as is" without express or implied
|
||||
warranty, and with no claim as to its suitability for any purpose.</p>
|
||||
|
||||
<p>Developed by <a href="mailto:fernando_cacciola@hotmail.com">Fernando Cacciola</a>,
|
||||
the latest version of this file can be found at <a
|
||||
href="http://www.boost.org">www.boost.org</a>, and the boost discussion list
|
||||
at <a href="http://www.yahoogroups.com/list/boost">www.yahoogroups.com/list/boost</a>.
|
||||
</p>
|
||||
<br>
|
||||
<br>
|
||||
|
||||
</body>
|
||||
</html>
|
119
value_init_test.cpp
Normal file
119
value_init_test.cpp
Normal file
@ -0,0 +1,119 @@
|
||||
// (C) 2002, Fernando Luis Cacciola Carballal.
|
||||
//
|
||||
// This material is provided "as is", with absolutely no warranty expressed
|
||||
// or implied. Any use is at your own risk.
|
||||
//
|
||||
// Permission to use or copy this software for any purpose is hereby granted
|
||||
// without fee, provided the above notices are retained on all copies.
|
||||
// Permission to modify the code and to distribute modified code is granted,
|
||||
// provided the above notices are retained, and a notice that the code was
|
||||
// modified is included with the above copyright notice.
|
||||
//
|
||||
// Test program for "boost/utility/value_init.hpp"
|
||||
//
|
||||
// Initial: 21 Agu 2002
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#include "boost/utility/value_init.hpp"
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#define BOOST_INCLUDE_MAIN
|
||||
#include "boost/test/test_tools.hpp"
|
||||
|
||||
//
|
||||
// Sample POD type
|
||||
//
|
||||
struct POD
|
||||
{
|
||||
POD () : c(0), i(0), f(0) {}
|
||||
|
||||
POD ( char c_, int i_, float f_ ) : c(c_), i(i_), f(f_) {}
|
||||
|
||||
friend std::ostream& operator << ( std::ostream& os, POD const& pod )
|
||||
{ return os << '(' << pod.c << ',' << pod.i << ',' << pod.f << ')' ; }
|
||||
|
||||
friend bool operator == ( POD const& lhs, POD const& rhs )
|
||||
{ return lhs.f == rhs.f && lhs.c == rhs.c && lhs.i == rhs.i ; }
|
||||
|
||||
float f;
|
||||
char c;
|
||||
int i;
|
||||
} ;
|
||||
|
||||
//
|
||||
// Sample non POD type
|
||||
//
|
||||
struct NonPODBase
|
||||
{
|
||||
virtual ~NonPODBase() {}
|
||||
} ;
|
||||
struct NonPOD : NonPODBase
|
||||
{
|
||||
NonPOD () : id() {}
|
||||
NonPOD ( std::string const& id_) : id(id_) {}
|
||||
|
||||
friend std::ostream& operator << ( std::ostream& os, NonPOD const& npod )
|
||||
{ return os << '(' << npod.id << ')' ; }
|
||||
|
||||
friend bool operator == ( NonPOD const& lhs, NonPOD const& rhs )
|
||||
{ return lhs.id == rhs.id ; }
|
||||
|
||||
std::string id ;
|
||||
} ;
|
||||
|
||||
template<class T>
|
||||
void test ( T const& y, T const& z )
|
||||
{
|
||||
boost::value_initialized<T> x ;
|
||||
BOOST_TEST ( y == x ) ;
|
||||
BOOST_TEST ( y == get(x) ) ;
|
||||
static_cast<T&>(x) = z ;
|
||||
get(x) = z ;
|
||||
BOOST_TEST ( x == z ) ;
|
||||
|
||||
boost::value_initialized<T> const x_c ;
|
||||
BOOST_TEST ( y == x_c ) ;
|
||||
BOOST_TEST ( y == get(x_c) ) ;
|
||||
static_cast<T&>(x_c) = z ;
|
||||
BOOST_TEST ( x_c == z ) ;
|
||||
#ifdef PRODUCE_ERROR_1
|
||||
get(x_c) = z ; // this should produce an ERROR
|
||||
#endif
|
||||
|
||||
boost::value_initialized<T const> cx ;
|
||||
BOOST_TEST ( y == cx ) ;
|
||||
BOOST_TEST ( y == get(cx) ) ;
|
||||
#ifdef PRODUCE_ERROR_2
|
||||
get(cx) = z ; // this should produce an ERROR
|
||||
#endif
|
||||
|
||||
boost::value_initialized<T const> const cx_c ;
|
||||
BOOST_TEST ( y == cx_c ) ;
|
||||
BOOST_TEST ( y == get(cx_c) ) ;
|
||||
#ifdef PRODUCE_ERROR_3
|
||||
get(cx_c) = z ; // this should produce an ERROR
|
||||
#endif
|
||||
}
|
||||
|
||||
int test_main(int, char **)
|
||||
{
|
||||
test( 0,1234 ) ;
|
||||
test( 0.0,12.34 ) ;
|
||||
test( POD(0,0,0.0), POD('a',1234,56.78) ) ;
|
||||
test( NonPOD( std::string() ), NonPOD( std::string("something") ) ) ;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
unsigned int expected_failures = 0;
|
||||
|
||||
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user