mirror of
https://github.com/boostorg/utility.git
synced 2025-10-05 21:40:59 +02:00
Compare commits
1 Commits
boost-1.29
...
svn-branch
Author | SHA1 | Date | |
---|---|---|---|
|
cfb38f7097 |
648
Collection.html
648
Collection.html
@@ -1,648 +0,0 @@
|
|||||||
<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>
|
|
@@ -408,7 +408,7 @@ template struct call_traits_test<int[2], true>;
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(BOOST_MSVC) && _MSC_VER <= 1300
|
#ifdef BOOST_MSVC
|
||||||
unsigned int expected_failures = 14;
|
unsigned int expected_failures = 14;
|
||||||
#elif defined(__SUNPRO_CC)
|
#elif defined(__SUNPRO_CC)
|
||||||
#if(__SUNPRO_CC <= 0x520)
|
#if(__SUNPRO_CC <= 0x520)
|
||||||
|
@@ -52,7 +52,7 @@ private:
|
|||||||
T* t_;
|
T* t_;
|
||||||
};
|
};
|
||||||
|
|
||||||
# if defined(__BORLANDC__) && (__BORLANDC__ <= 0x570)
|
# if defined(__BORLANDC__) && (__BORLANDC__ <= 0x560)
|
||||||
# define BOOST_REF_CONST
|
# define BOOST_REF_CONST
|
||||||
# else
|
# else
|
||||||
# define BOOST_REF_CONST const
|
# define BOOST_REF_CONST const
|
||||||
|
@@ -1,82 +0,0 @@
|
|||||||
// (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
|
|
||||||
|
|
@@ -128,8 +128,6 @@
|
|||||||
<a href="generator_iterator.htm">Generator Iterator Adaptor</a>
|
<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>
|
<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>
|
<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>
|
</ul>
|
||||||
|
|
||||||
<p><b><a href="../../people/dave_abrahams.htm">Dave
|
<p><b><a href="../../people/dave_abrahams.htm">Dave
|
||||||
@@ -158,9 +156,6 @@
|
|||||||
adaptor.<br>
|
adaptor.<br>
|
||||||
Toon Knapen contributed the <a href="permutation_iterator.htm">permutation
|
Toon Knapen contributed the <a href="permutation_iterator.htm">permutation
|
||||||
iterator</a> adaptor.<br>
|
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>
|
<h2><a name="iterator_adaptor">Class template</a>
|
||||||
<tt>iterator_adaptor</tt></h2>
|
<tt>iterator_adaptor</tt></h2>
|
||||||
|
@@ -569,7 +569,7 @@ test_main( int , char * [] )
|
|||||||
|
|
||||||
cout << "Created point, and operated on it." << endl;
|
cout << "Created point, and operated on it." << endl;
|
||||||
|
|
||||||
for (int n = 0; n < 1000; ++n) // was 10,000 but took too long (Beman)
|
for (int n = 0; n < 10000; ++n)
|
||||||
{
|
{
|
||||||
boost::minstd_rand r;
|
boost::minstd_rand r;
|
||||||
tester<long, int>()(r);
|
tester<long, int>()(r);
|
||||||
|
@@ -1,332 +0,0 @@
|
|||||||
<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>
|
|
@@ -1,42 +0,0 @@
|
|||||||
// (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;
|
|
||||||
}
|
|
@@ -1,42 +0,0 @@
|
|||||||
// (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;
|
|
||||||
}
|
|
@@ -1,41 +0,0 @@
|
|||||||
// (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;
|
|
||||||
}
|
|
@@ -19,7 +19,7 @@ Defined in header
|
|||||||
|
|
||||||
<p>
|
<p>
|
||||||
The transform iterator adaptor augments an iterator by applying some
|
The transform iterator adaptor augments an iterator by applying some
|
||||||
function object to the result of dereferencing the iterator. In other
|
function object to the result of dereferencing the iterator. Another
|
||||||
words, the <tt>operator*</tt> of the transform iterator first
|
words, the <tt>operator*</tt> of the transform iterator first
|
||||||
dereferences the base iterator, passes the result of this to the
|
dereferences the base iterator, passes the result of this to the
|
||||||
function object, and then returns the result. The following
|
function object, and then returns the result. The following
|
||||||
|
219
value_init.htm
219
value_init.htm
@@ -1,219 +0,0 @@
|
|||||||
<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>
|
|
@@ -1,119 +0,0 @@
|
|||||||
// (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