mirror of
https://github.com/boostorg/utility.git
synced 2025-05-09 15:04:00 +00:00
Transcribe documentation to quickbook
This commit is contained in:
parent
05e0d1688d
commit
703a4bf752
118
Assignable.html
118
Assignable.html
@ -1,109 +1,19 @@
|
|||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
|
||||||
|
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta http-equiv="Content-Language" content="en-us">
|
<title>Boost.Utility</title>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
|
<meta http-equiv="refresh" content="0; URL=./doc/html/index.html">
|
||||||
|
|
||||||
<title>Assignable</title>
|
|
||||||
</head>
|
</head>
|
||||||
|
<body>
|
||||||
<body bgcolor="#FFFFFF" link="#0000EE" text="#000000" vlink="#551A8B" alink=
|
Automatic redirection failed, please go to
|
||||||
"#FF0000">
|
<a href="./doc/html/index.html">./doc/html/index.html</a>
|
||||||
<img src="../../boost.png" alt="C++ Boost" width="277" height=
|
<hr>
|
||||||
"86"><br clear="none">
|
<tt>
|
||||||
|
Boost.Utility<br>
|
||||||
<h1>Assignable</h1>
|
<br>
|
||||||
|
Distributed under the Boost Software License, Version 1.0.
|
||||||
<h3>Description</h3>
|
(See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
<a href=http://www.boost.org/LICENSE_1_0.txt>http://www.boost.org/LICENSE_1_0.txt</a>) <br>
|
||||||
<p>A type is Assignable if it is possible to assign one object of the type
|
<br>
|
||||||
to another object of that type.</p>
|
</tt>
|
||||||
|
|
||||||
<h3>Notation</h3>
|
|
||||||
|
|
||||||
<table summary="">
|
|
||||||
<tr>
|
|
||||||
<td valign="top"><tt>T</tt></td>
|
|
||||||
|
|
||||||
<td valign="top">is type that is a model of Assignable</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td valign="top"><tt>t</tt></td>
|
|
||||||
|
|
||||||
<td valign="top">is an object of type <tt>T</tt></td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td valign="top"><tt>u</tt></td>
|
|
||||||
|
|
||||||
<td valign="top">is an object of type <tt>T</tt> or possibly <tt>const
|
|
||||||
T</tt></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<h3>Definitions</h3>
|
|
||||||
|
|
||||||
<h3>Valid expressions</h3>
|
|
||||||
|
|
||||||
<table border summary="">
|
|
||||||
<tr>
|
|
||||||
<th>Name</th>
|
|
||||||
|
|
||||||
<th>Expression</th>
|
|
||||||
|
|
||||||
<th>Return type</th>
|
|
||||||
|
|
||||||
<th>Semantics</th>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td valign="top">Assignment</td>
|
|
||||||
|
|
||||||
<td valign="top"><tt>t = u</tt></td>
|
|
||||||
|
|
||||||
<td valign="top"><tt>T&</tt></td>
|
|
||||||
|
|
||||||
<td valign="top"><tt>t</tt> is equivalent to <tt>u</tt></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<h3>Models</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><tt>int</tt></li>
|
|
||||||
|
|
||||||
<li><tt>std::pair</tt></li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h3>See also</h3>
|
|
||||||
|
|
||||||
<p><a href=
|
|
||||||
"http://www.sgi.com/tech/stl/DefaultConstructible.html">DefaultConstructible</a>
|
|
||||||
and <a href="./CopyConstructible.html">CopyConstructible</a><br></p>
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
<p><a href="http://validator.w3.org/check?uri=referer"><img border="0" src=
|
|
||||||
"../../doc/images/valid-html401.png" alt="Valid HTML 4.01 Transitional"
|
|
||||||
height="31" width="88"></a></p>
|
|
||||||
|
|
||||||
<p>Revised
|
|
||||||
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan -->05 December, 2006<!--webbot bot="Timestamp" endspan i-checksum="38516" --></p>
|
|
||||||
|
|
||||||
<table summary="">
|
|
||||||
<tr valign="top">
|
|
||||||
<td nowrap><i>Copyright © 2000</i></td>
|
|
||||||
|
|
||||||
<td><i><a href="http://www.lsc.nd.edu/~jsiek">Jeremy Siek</a>, Univ.of
|
|
||||||
Notre Dame (<a href=
|
|
||||||
"mailto:jsiek@lsc.nd.edu">jsiek@lsc.nd.edu</a>)</i></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<p><i>Distributed under the Boost Software License, Version 1.0. (See
|
|
||||||
accompanying file <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or
|
|
||||||
copy at <a href=
|
|
||||||
"http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>)</i></p>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
543
Collection.html
543
Collection.html
@ -1,534 +1,19 @@
|
|||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
|
||||||
|
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta http-equiv="Content-Language" content="en-us">
|
<title>Boost.Utility</title>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
|
<meta http-equiv="refresh" content="0; URL=./doc/html/index.html">
|
||||||
|
|
||||||
<title>Collection</title>
|
|
||||||
</head>
|
</head>
|
||||||
|
<body>
|
||||||
<body bgcolor="#FFFFFF" link="#0000EE" text="#000000" vlink="#551A8B" alink=
|
Automatic redirection failed, please go to
|
||||||
"#FF0000">
|
<a href="./doc/html/index.html">./doc/html/index.html</a>
|
||||||
<h1><img src="../../boost.png" alt="boost logo" width="277" align="middle"
|
<hr>
|
||||||
height="86"><br>
|
<tt>
|
||||||
Collection</h1>
|
Boost.Utility<br>
|
||||||
|
<br>
|
||||||
<h3>Description</h3>
|
Distributed under the Boost Software License, Version 1.0.
|
||||||
|
(See accompanying file LICENSE_1_0.txt or copy at
|
||||||
<p>A Collection is a <i>concept</i> similar to the STL <a href=
|
<a href=http://www.boost.org/LICENSE_1_0.txt>http://www.boost.org/LICENSE_1_0.txt</a>) <br>
|
||||||
"http://www.sgi.com/tech/stl/Container.html">Container</a> concept. A
|
<br>
|
||||||
Collection provides iterators for accessing a range of elements and
|
</tt>
|
||||||
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:</p>
|
|
||||||
|
|
||||||
<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>
|
|
||||||
|
|
||||||
<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>
|
|
||||||
|
|
||||||
<li>The associated reference type of a Collection does not have to be a
|
|
||||||
real C++ reference.</li>
|
|
||||||
</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.
|
|
||||||
|
|
||||||
<h3>Associated types</h3>
|
|
||||||
|
|
||||||
<table border summary="">
|
|
||||||
<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="#n1">[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 summary="">
|
|
||||||
<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>
|
|
||||||
|
|
||||||
<p>The following expressions must be valid.</p>
|
|
||||||
|
|
||||||
<table border summary="">
|
|
||||||
<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 summary="">
|
|
||||||
<tr>
|
|
||||||
<th>Name</th>
|
|
||||||
|
|
||||||
<th>Expression</th>
|
|
||||||
|
|
||||||
<th>Semantics</th>
|
|
||||||
|
|
||||||
<th>Postcondition</th>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<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</tt></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>
|
|
||||||
|
|
||||||
<p><tt>begin()</tt> and <tt>end()</tt> are amortized constant time.</p>
|
|
||||||
|
|
||||||
<p><tt>size()</tt> is at most linear in the Collection's size.
|
|
||||||
<tt>empty()</tt> is amortized constant time.</p>
|
|
||||||
|
|
||||||
<p><tt>swap()</tt> is at most linear in the size of the two
|
|
||||||
collections.</p>
|
|
||||||
|
|
||||||
<h3>Invariants</h3>
|
|
||||||
|
|
||||||
<table border summary="">
|
|
||||||
<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>
|
|
||||||
|
|
||||||
<li><tt>array_ptr</tt></li>
|
|
||||||
|
|
||||||
<li><tt>vector<bool></tt></li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h3>Collection Refinements</h3>
|
|
||||||
|
|
||||||
<p>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.</p>
|
|
||||||
|
|
||||||
<h4>ForwardCollection</h4>
|
|
||||||
|
|
||||||
<p>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 summary="">
|
|
||||||
<tr>
|
|
||||||
<th>Name</th>
|
|
||||||
|
|
||||||
<th>Expression</th>
|
|
||||||
|
|
||||||
<th>Return type</th>
|
|
||||||
|
|
||||||
<th>Semantics</th>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td valign="top">Front</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.begin())</tt>.</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<h4>ReversibleCollection</h4>
|
|
||||||
|
|
||||||
<p>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 summary="">
|
|
||||||
<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>
|
|
||||||
|
|
||||||
<p>The elements are arranged in a strict linear order. No extra methods are
|
|
||||||
required.</p>
|
|
||||||
|
|
||||||
<h4>RandomAccessCollection</h4>
|
|
||||||
|
|
||||||
<p>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 summary="">
|
|
||||||
<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="n1" id="n1">[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).</p>
|
|
||||||
|
|
||||||
<h3>See also</h3>
|
|
||||||
|
|
||||||
<p><a href=
|
|
||||||
"http://www.sgi.com/tech/stl/Container.html">Container</a><br></p>
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
<p><a href="http://validator.w3.org/check?uri=referer"><img border="0" src=
|
|
||||||
"../../doc/images/valid-html401.png" alt="Valid HTML 4.01 Transitional"
|
|
||||||
height="31" width="88"></a></p>
|
|
||||||
|
|
||||||
<p>Revised
|
|
||||||
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan -->05
|
|
||||||
December, 2006<!--webbot bot="Timestamp" endspan i-checksum="38516" --></p>
|
|
||||||
|
|
||||||
<table summary="">
|
|
||||||
<tr valign="top">
|
|
||||||
<td nowrap><i>Copyright © 2000</i></td>
|
|
||||||
|
|
||||||
<td><i><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>)</i></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<p><i>Distributed under the Boost Software License, Version 1.0. (See
|
|
||||||
accompanying file <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or
|
|
||||||
copy at <a href=
|
|
||||||
"http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>)</i></p>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -1,185 +1,19 @@
|
|||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
|
||||||
|
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta http-equiv="Content-Language" content="en-us">
|
<title>Boost.Utility</title>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
|
<meta http-equiv="refresh" content="0; URL=./doc/html/index.html">
|
||||||
|
|
||||||
<title>Copy Constructible</title>
|
|
||||||
</head>
|
</head>
|
||||||
|
<body>
|
||||||
<body bgcolor="#FFFFFF" link="#0000EE" text="#000000" vlink="#551A8B" alink=
|
Automatic redirection failed, please go to
|
||||||
"#FF0000">
|
<a href="./doc/html/index.html">./doc/html/index.html</a>
|
||||||
<img src="../../boost.png" alt="C++ Boost" width="277" height=
|
<hr>
|
||||||
"86"><br clear="none">
|
<tt>
|
||||||
|
Boost.Utility<br>
|
||||||
<h1>Copy Constructible</h1>
|
<br>
|
||||||
|
Distributed under the Boost Software License, Version 1.0.
|
||||||
<h3>Description</h3>
|
(See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
<a href=http://www.boost.org/LICENSE_1_0.txt>http://www.boost.org/LICENSE_1_0.txt</a>) <br>
|
||||||
<p>A type is Copy Constructible if it is possible to copy objects of that
|
<br>
|
||||||
type.</p>
|
</tt>
|
||||||
|
|
||||||
<h3>Notation</h3>
|
|
||||||
|
|
||||||
<table summary="">
|
|
||||||
<tr>
|
|
||||||
<td valign="top"><tt>T</tt></td>
|
|
||||||
|
|
||||||
<td valign="top">is type that is a model of Copy Constructible</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td valign="top"><tt>t</tt></td>
|
|
||||||
|
|
||||||
<td valign="top">is an object of type <tt>T</tt></td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td valign="top"><tt>u</tt></td>
|
|
||||||
|
|
||||||
<td valign="top">is an object of type <tt>const T</tt></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<h3>Definitions</h3>
|
|
||||||
|
|
||||||
<h3>Valid expressions</h3>
|
|
||||||
|
|
||||||
<table border summary="">
|
|
||||||
<tr>
|
|
||||||
<th>Name</th>
|
|
||||||
|
|
||||||
<th>Expression</th>
|
|
||||||
|
|
||||||
<th>Return type</th>
|
|
||||||
|
|
||||||
<th>Semantics</th>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td valign="top">Copy constructor</td>
|
|
||||||
|
|
||||||
<td valign="top"><tt>T(t)</tt></td>
|
|
||||||
|
|
||||||
<td valign="top"><tt>T</tt></td>
|
|
||||||
|
|
||||||
<td valign="top"><tt>t</tt> is equivalent to <tt>T(t)</tt></td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td valign="top">Copy constructor</td>
|
|
||||||
|
|
||||||
<td valign="top">
|
|
||||||
<pre>
|
|
||||||
T(u)
|
|
||||||
</pre>
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td valign="top"><tt>T</tt></td>
|
|
||||||
|
|
||||||
<td valign="top"><tt>u</tt> is equivalent to <tt>T(u)</tt></td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td valign="top">Destructor</td>
|
|
||||||
|
|
||||||
<td valign="top">
|
|
||||||
<pre>
|
|
||||||
t.~T()
|
|
||||||
</pre>
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td valign="top"><tt>T</tt></td>
|
|
||||||
|
|
||||||
<td valign="top"> </td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td valign="top">Address Operator</td>
|
|
||||||
|
|
||||||
<td valign="top">
|
|
||||||
<pre>
|
|
||||||
&t
|
|
||||||
</pre>
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td valign="top"><tt>T*</tt></td>
|
|
||||||
|
|
||||||
<td valign="top">denotes the address of <tt>t</tt></td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td valign="top">Address Operator</td>
|
|
||||||
|
|
||||||
<td valign="top">
|
|
||||||
<pre>
|
|
||||||
&u
|
|
||||||
</pre>
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td valign="top"><tt>T*</tt></td>
|
|
||||||
|
|
||||||
<td valign="top">denotes the address of <tt>u</tt></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<h3>Models</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><tt>int</tt></li>
|
|
||||||
|
|
||||||
<li><tt>std::pair</tt></li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h3>Concept Checking Class</h3>
|
|
||||||
<pre>
|
|
||||||
template <class T>
|
|
||||||
struct CopyConstructibleConcept
|
|
||||||
{
|
|
||||||
void constraints() {
|
|
||||||
T a(b); // require copy constructor
|
|
||||||
T* ptr = &a; // require address of operator
|
|
||||||
const_constraints(a);
|
|
||||||
ignore_unused_variable_warning(ptr);
|
|
||||||
}
|
|
||||||
void const_constraints(const T& a) {
|
|
||||||
T c(a); // require const copy constructor
|
|
||||||
const T* ptr = &a; // require const address of operator
|
|
||||||
ignore_unused_variable_warning(c);
|
|
||||||
ignore_unused_variable_warning(ptr);
|
|
||||||
}
|
|
||||||
T b;
|
|
||||||
};
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<h3>See also</h3>
|
|
||||||
|
|
||||||
<p><a href="http://www.sgi.com/tech/stl/DefaultConstructible.html">Default
|
|
||||||
Constructible</a> and <a href="./Assignable.html">Assignable</a><br></p>
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
<p><a href="http://validator.w3.org/check?uri=referer"><img border="0" src=
|
|
||||||
"../../doc/images/valid-html401.png" alt="Valid HTML 4.01 Transitional"
|
|
||||||
height="31" width="88"></a></p>
|
|
||||||
|
|
||||||
<p>Revised
|
|
||||||
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan -->05
|
|
||||||
December, 2006<!--webbot bot="Timestamp" endspan i-checksum="38516" --></p>
|
|
||||||
|
|
||||||
<table summary="">
|
|
||||||
<tr valign="top">
|
|
||||||
<td nowrap><i>Copyright © 2000</i></td>
|
|
||||||
|
|
||||||
<td><i><a href="http://www.lsc.nd.edu/~jsiek">Jeremy Siek</a>, Univ.of
|
|
||||||
Notre Dame (<a href=
|
|
||||||
"mailto:jsiek@lsc.nd.edu">jsiek@lsc.nd.edu</a>)</i></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<p><i>Distributed under the Boost Software License, Version 1.0. (See
|
|
||||||
accompanying file <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or
|
|
||||||
copy at <a href=
|
|
||||||
"http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>)</i></p>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -1,210 +1,19 @@
|
|||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
|
||||||
|
|
||||||
<html>
|
<html>
|
||||||
<!--
|
|
||||||
== Copyright (c) 1996-1999
|
|
||||||
== Silicon Graphics Computer Systems, Inc.
|
|
||||||
==
|
|
||||||
== 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.
|
|
||||||
==
|
|
||||||
== Copyright (c) 1994
|
|
||||||
== Hewlett-Packard Company
|
|
||||||
==
|
|
||||||
== 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. Hewlett-Packard Company makes no
|
|
||||||
== representations about the suitability of this software for any
|
|
||||||
== purpose. It is provided "as is" without express or implied warranty.
|
|
||||||
==
|
|
||||||
-->
|
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta http-equiv="Content-Language" content="en-us">
|
<title>Boost.Utility</title>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
|
<meta http-equiv="refresh" content="0; URL=./doc/html/index.html">
|
||||||
|
|
||||||
<title>LessThanComparable</title>
|
|
||||||
</head>
|
</head>
|
||||||
|
<body>
|
||||||
<body bgcolor="#FFFFFF" link="#0000EE" text="#000000" vlink="#551A8B" alink=
|
Automatic redirection failed, please go to
|
||||||
"#FF0000">
|
<a href="./doc/html/index.html">./doc/html/index.html</a>
|
||||||
<img src="../../boost.png" alt="C++ Boost" width="277" height=
|
<hr>
|
||||||
"86"><br clear="none">
|
<tt>
|
||||||
|
Boost.Utility<br>
|
||||||
<h1>LessThanComparable</h1>
|
<br>
|
||||||
|
Distributed under the Boost Software License, Version 1.0.
|
||||||
<h3>Description</h3>
|
(See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
<a href=http://www.boost.org/LICENSE_1_0.txt>http://www.boost.org/LICENSE_1_0.txt</a>) <br>
|
||||||
<p>A type is LessThanComparable if it is ordered: it must be possible to
|
<br>
|
||||||
compare two objects of that type using <tt>operator<</tt>, and
|
</tt>
|
||||||
<tt>operator<</tt> must be a strict weak ordering relation.</p>
|
|
||||||
|
|
||||||
<h3>Refinement of</h3>
|
|
||||||
|
|
||||||
<h3>Associated types</h3>
|
|
||||||
|
|
||||||
<h3>Notation</h3>
|
|
||||||
|
|
||||||
<table summary="">
|
|
||||||
<tr>
|
|
||||||
<td valign="top"><tt>X</tt></td>
|
|
||||||
|
|
||||||
<td valign="top">A type that is a model of LessThanComparable</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td valign="top"><tt>x</tt>, <tt>y</tt>, <tt>z</tt></td>
|
|
||||||
|
|
||||||
<td valign="top">Object of type <tt>X</tt></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<h3>Definitions</h3>
|
|
||||||
|
|
||||||
<p>Consider the relation <tt>!(x < y) && !(y < x)</tt>. If
|
|
||||||
this relation is transitive (that is, if <tt>!(x < y) && !(y
|
|
||||||
< x) && !(y < z) && !(z < y)</tt> implies <tt>!(x
|
|
||||||
< z) && !(z < x)</tt>), then it satisfies the mathematical
|
|
||||||
definition of an equivalence relation. In this case, <tt>operator<</tt>
|
|
||||||
is a <i>strict weak ordering</i>.</p>
|
|
||||||
|
|
||||||
<p>If <tt>operator<</tt> is a strict weak ordering, and if each
|
|
||||||
equivalence class has only a single element, then <tt>operator<</tt> is
|
|
||||||
a <i>total ordering</i>.</p>
|
|
||||||
|
|
||||||
<h3>Valid expressions</h3>
|
|
||||||
|
|
||||||
<table border summary="">
|
|
||||||
<tr>
|
|
||||||
<th>Name</th>
|
|
||||||
|
|
||||||
<th>Expression</th>
|
|
||||||
|
|
||||||
<th>Type requirements</th>
|
|
||||||
|
|
||||||
<th>Return type</th>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td valign="top">Less</td>
|
|
||||||
|
|
||||||
<td valign="top"><tt>x < y</tt></td>
|
|
||||||
|
|
||||||
<td valign="top"> </td>
|
|
||||||
|
|
||||||
<td valign="top">Convertible to <tt>bool</tt></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<h3>Expression semantics</h3>
|
|
||||||
|
|
||||||
<table border summary="">
|
|
||||||
<tr>
|
|
||||||
<th>Name</th>
|
|
||||||
|
|
||||||
<th>Expression</th>
|
|
||||||
|
|
||||||
<th>Precondition</th>
|
|
||||||
|
|
||||||
<th>Semantics</th>
|
|
||||||
|
|
||||||
<th>Postcondition</th>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td valign="top">Less</td>
|
|
||||||
|
|
||||||
<td valign="top"><tt>x < y</tt></td>
|
|
||||||
|
|
||||||
<td valign="top"><tt>x</tt> and <tt>y</tt> are in the domain of
|
|
||||||
<tt><</tt></td>
|
|
||||||
|
|
||||||
<td valign="top"> </td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<h3>Complexity guarantees</h3>
|
|
||||||
|
|
||||||
<h3>Invariants</h3>
|
|
||||||
|
|
||||||
<table border summary="">
|
|
||||||
<tr>
|
|
||||||
<td valign="top">Irreflexivity</td>
|
|
||||||
|
|
||||||
<td valign="top"><tt>x < x</tt> must be false.</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td valign="top">Antisymmetry</td>
|
|
||||||
|
|
||||||
<td valign="top"><tt>x < y</tt> implies !(y < x) <a href=
|
|
||||||
"#n2">[2]</a></td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td valign="top">Transitivity</td>
|
|
||||||
|
|
||||||
<td valign="top"><tt>x < y</tt> and <tt>y < z</tt> implies <tt>x
|
|
||||||
< z</tt> <a href="#n3">[3]</a></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<h3>Models</h3>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>int</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h3>Notes</h3>
|
|
||||||
|
|
||||||
<p><a name="n1" id="n1">[1]</a> Only <tt>operator<</tt> is fundamental;
|
|
||||||
the other inequality operators are essentially syntactic sugar.</p>
|
|
||||||
|
|
||||||
<p><a name="n2" id="n2">[2]</a> Antisymmetry is a theorem, not an axiom: it
|
|
||||||
follows from irreflexivity and transitivity.</p>
|
|
||||||
|
|
||||||
<p><a name="n3" id="n3">[3]</a> Because of irreflexivity and transitivity,
|
|
||||||
<tt>operator<</tt> always satisfies the definition of a <i>partial
|
|
||||||
ordering</i>. The definition of a <i>strict weak ordering</i> is stricter,
|
|
||||||
and the definition of a <i>total ordering</i> is stricter still.</p>
|
|
||||||
|
|
||||||
<h3>See also</h3>
|
|
||||||
|
|
||||||
<p><a href=
|
|
||||||
"http://www.sgi.com/tech/stl/EqualityComparable.html">EqualityComparable</a>,
|
|
||||||
<a href=
|
|
||||||
"http://www.sgi.com/tech/stl/StrictWeakOrdering.html">StrictWeakOrdering</a><br>
|
|
||||||
</p>
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
<p><a href="http://validator.w3.org/check?uri=referer"><img border="0" src=
|
|
||||||
"../../doc/images/valid-html401.png" alt="Valid HTML 4.01 Transitional"
|
|
||||||
height="31" width="88"></a></p>
|
|
||||||
|
|
||||||
<p>Revised
|
|
||||||
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan -->05
|
|
||||||
December, 2006<!--webbot bot="Timestamp" endspan i-checksum="38516" --></p>
|
|
||||||
|
|
||||||
<table summary="">
|
|
||||||
<tr valign="top">
|
|
||||||
<td nowrap><i>Copyright © 2000</i></td>
|
|
||||||
|
|
||||||
<td><i><a href="http://www.lsc.nd.edu/~jsiek">Jeremy Siek</a>, Univ.of
|
|
||||||
Notre Dame (<a href=
|
|
||||||
"mailto:jsiek@lsc.nd.edu">jsiek@lsc.nd.edu</a>)</i></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<p><i>Distributed under the Boost Software License, Version 1.0. (See
|
|
||||||
accompanying file <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or
|
|
||||||
copy at <a href=
|
|
||||||
"http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>)</i></p>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -1,95 +1,19 @@
|
|||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
|
||||||
|
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta http-equiv="Content-Language" content="en-us">
|
<title>Boost.Utility</title>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
|
<meta http-equiv="refresh" content="0; URL=./doc/html/index.html">
|
||||||
|
|
||||||
<title>MultiPassInputIterator</title>
|
|
||||||
</head>
|
</head>
|
||||||
|
<body>
|
||||||
<body bgcolor="#FFFFFF" link="#0000EE" text="#000000" vlink="#551A8B" alink=
|
Automatic redirection failed, please go to
|
||||||
"#FF0000">
|
<a href="./doc/html/index.html">./doc/html/index.html</a>
|
||||||
<img src="../../boost.png" alt="C++ Boost" width="277" height=
|
<hr>
|
||||||
"86"><br clear="none">
|
<tt>
|
||||||
|
Boost.Utility<br>
|
||||||
<h2><a name="concept:MultiPassInputIterator" id=
|
<br>
|
||||||
"concept:MultiPassInputIterator"></a> Multi-Pass Input Iterator</h2>
|
Distributed under the Boost Software License, Version 1.0.
|
||||||
|
(See accompanying file LICENSE_1_0.txt or copy at
|
||||||
<p>This concept is a refinement of <a href=
|
<a href=http://www.boost.org/LICENSE_1_0.txt>http://www.boost.org/LICENSE_1_0.txt</a>) <br>
|
||||||
"http://www.sgi.com/tech/stl/InputIterator.html">Input Iterator</a>, adding
|
<br>
|
||||||
the requirements that the iterator can be used to make multiple passes
|
</tt>
|
||||||
through a range, and that if <tt>it1 == it2</tt> and <tt>it1</tt> is
|
|
||||||
dereferenceable then <tt>++it1 == ++it2</tt>. The Multi-Pass Input Iterator
|
|
||||||
is very similar to the <a href=
|
|
||||||
"http://www.sgi.com/tech/stl/ForwardIterator.html">Forward Iterator</a>.
|
|
||||||
The only difference is that a <a href=
|
|
||||||
"http://www.sgi.com/tech/stl/ForwardIterator.html">Forward Iterator</a>
|
|
||||||
requires the <tt>reference</tt> type to be <tt>value_type&</tt>,
|
|
||||||
whereas MultiPassInputIterator is like <a href=
|
|
||||||
"http://www.sgi.com/tech/stl/InputIterator.html">Input Iterator</a> in that
|
|
||||||
the <tt>reference</tt> type merely has to be convertible to
|
|
||||||
<tt>value_type</tt>.</p>
|
|
||||||
|
|
||||||
<h3>Design Notes</h3>
|
|
||||||
|
|
||||||
<p>comments by Valentin Bonnard:</p>
|
|
||||||
|
|
||||||
<p>I think that introducing Multi-Pass Input Iterator isn't the right
|
|
||||||
solution. Do you also want to define Multi-Pass Bidirectionnal Iterator and
|
|
||||||
Multi-Pass Random Access Iterator ? I don't, definitly. It only confuses
|
|
||||||
the issue. The problem lies into the existing hierarchy of iterators, which
|
|
||||||
mixes movabillity, modifiabillity and lvalue-ness, and these are clearly
|
|
||||||
independant.</p>
|
|
||||||
|
|
||||||
<p>The terms Forward, Bidirectionnal and Random Access are about
|
|
||||||
movabillity and shouldn't be used to mean anything else. In a completly
|
|
||||||
orthogonal way, iterators can be immutable, mutable, or neither. Lvalueness
|
|
||||||
of iterators is also orthogonal with immutabillity. With these clean
|
|
||||||
concepts, your Multi-Pass Input Iterator is just called a Forward
|
|
||||||
Iterator.</p>
|
|
||||||
|
|
||||||
<p>Other translations are:<br>
|
|
||||||
std::Forward Iterator -> ForwardIterator & Lvalue Iterator<br>
|
|
||||||
std::Bidirectionnal Iterator -> Bidirectionnal Iterator & Lvalue
|
|
||||||
Iterator<br>
|
|
||||||
std::Random Access Iterator -> Random Access Iterator & Lvalue
|
|
||||||
Iterator<br></p>
|
|
||||||
|
|
||||||
<p>Note that in practice the only operation not allowed on my Forward
|
|
||||||
Iterator which is allowed on std::Forward Iterator is <tt>&*it</tt>. I
|
|
||||||
think that <tt>&*</tt> is rarely needed in generic code.</p>
|
|
||||||
|
|
||||||
<p>reply by Jeremy Siek:</p>
|
|
||||||
|
|
||||||
<p>The above analysis by Valentin is right on. Of course, there is the
|
|
||||||
problem with backward compatibility. The current STL implementations are
|
|
||||||
based on the old definition of Forward Iterator. The right course of action
|
|
||||||
is to get Forward Iterator, etc. changed in the C++ standard. Once that is
|
|
||||||
done we can drop Multi-Pass Input Iterator.<br></p>
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
<p><a href="http://validator.w3.org/check?uri=referer"><img border="0" src=
|
|
||||||
"../../doc/images/valid-html401.png" alt="Valid HTML 4.01 Transitional"
|
|
||||||
height="31" width="88"></a></p>
|
|
||||||
|
|
||||||
<p>Revised
|
|
||||||
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan -->05
|
|
||||||
December, 2006<!--webbot bot="Timestamp" endspan i-checksum="38516" --></p>
|
|
||||||
|
|
||||||
<table summary="">
|
|
||||||
<tr valign="top">
|
|
||||||
<td nowrap><i>Copyright © 2000</i></td>
|
|
||||||
|
|
||||||
<td><i><a href="http://www.lsc.nd.edu/~jsiek">Jeremy Siek</a>, Univ.of
|
|
||||||
Notre Dame (<a href=
|
|
||||||
"mailto:jsiek@lsc.nd.edu">jsiek@lsc.nd.edu</a>)</i></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<p><i>Distributed under the Boost Software License, Version 1.0. (See
|
|
||||||
accompanying file <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or
|
|
||||||
copy at <a href=
|
|
||||||
"http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>)</i></p>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -1,159 +1,19 @@
|
|||||||
<HTML>
|
<html>
|
||||||
<Head>
|
<head>
|
||||||
<Title>OptionalPointee Concept</Title>
|
<title>Boost.Utility</title>
|
||||||
</HEAD>
|
<meta http-equiv="refresh" content="0; URL=./doc/html/index.html">
|
||||||
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"
|
</head>
|
||||||
ALINK="#ff0000">
|
<body>
|
||||||
<IMG SRC="../../boost.png"
|
Automatic redirection failed, please go to
|
||||||
ALT="C++ Boost" width="277" height="86">
|
<a href="./doc/html/index.html">./doc/html/index.html</a>
|
||||||
<!--end header-->
|
<hr>
|
||||||
<BR Clear>
|
<tt>
|
||||||
<H1>Concept: OptionalPointee</H1>
|
Boost.Utility<br>
|
||||||
|
<br>
|
||||||
<h3>Description</h3>
|
Distributed under the Boost Software License, Version 1.0.
|
||||||
A type is a model of <i>OptionalPointee</i> if it points to (or refers to) a value
|
(See accompanying file LICENSE_1_0.txt or copy at
|
||||||
that may not exist. That is, if it has a <b>pointee</b> which might be <b>valid</b>
|
<a href=http://www.boost.org/LICENSE_1_0.txt>http://www.boost.org/LICENSE_1_0.txt</a>) <br>
|
||||||
(existent) or <b>invalid</b> (inexistent); and it is possible to test whether the
|
<br>
|
||||||
pointee is valid or not.
|
</tt>
|
||||||
This model does <u>not</u> imply pointer semantics: i.e., it does not imply shallow copy nor
|
</body>
|
||||||
aliasing.
|
</html>
|
||||||
<h3>Notation</h3>
|
|
||||||
<Table>
|
|
||||||
<TR>
|
|
||||||
<TD VAlign=top> <tt>T</tt> </TD>
|
|
||||||
<TD VAlign=top> is a type that is a model of OptionalPointee</TD>
|
|
||||||
</TR>
|
|
||||||
<TR>
|
|
||||||
<TD VAlign=top> <tt>t</tt> </TD>
|
|
||||||
<TD VAlign=top> is an object of type <tt>T</tt> or possibly <tt>const T</tt></TD>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<h3>Definitions</h3>
|
|
||||||
<h3>Valid expressions</h3>
|
|
||||||
<Table border>
|
|
||||||
<TR>
|
|
||||||
<TH> Name </TH>
|
|
||||||
<TH> Expression </TH>
|
|
||||||
<TH> Return type </TH>
|
|
||||||
<TH> Semantics </TH>
|
|
||||||
</TR>
|
|
||||||
<TR>
|
|
||||||
<TD VAlign=top>Value Access</TD>
|
|
||||||
<TD VAlign=top> <tt>*t</tt></TD>
|
|
||||||
<TD VAlign=top> <tt>T&</tt></TD>
|
|
||||||
<TD VAlign=top>If the pointee is valid returns a reference to
|
|
||||||
the pointee.<br>
|
|
||||||
If the pointee is invalid the result is <i>undefined</i>.</TD>
|
|
||||||
<TD VAlign=top> </TD>
|
|
||||||
</TR>
|
|
||||||
<TR>
|
|
||||||
<TD VAlign=top>Value Access</TD>
|
|
||||||
<TD VAlign=top> <tt>t-><i>xyz</i></tt></TD>
|
|
||||||
<TD VAlign=top> <tt>T*</tt></TD>
|
|
||||||
<TD VAlign=top>If the pointee is valid returns a builtin pointer to the pointee.<br>
|
|
||||||
If the pointee is invalid the result is <i>undefined</i> (It might not even return NULL).<br>
|
|
||||||
</TD>
|
|
||||||
<TD VAlign=top> </TD>
|
|
||||||
</TR>
|
|
||||||
<TR>
|
|
||||||
<TD VAlign=top>Validity Test</TD>
|
|
||||||
<TD VAlign=top> <tt>bool(t)</tt></TD>
|
|
||||||
<TD VAlign=top> bool </TD>
|
|
||||||
<TD VAlign=top>If the pointee is valid returns true.<br>
|
|
||||||
If the pointee is invalid returns false.</TD>
|
|
||||||
<TD VAlign=top></TD>
|
|
||||||
</TR>
|
|
||||||
<TR>
|
|
||||||
<TD VAlign=top>Invalidity Test</TD>
|
|
||||||
<TD VAlign=top> <tt>!t</tt></TD>
|
|
||||||
<TD VAlign=top> bool </TD>
|
|
||||||
<TD VAlign=top>If the pointee is valid returns false.<br>
|
|
||||||
If the pointee is invalid returns true.</TD>
|
|
||||||
<TD VAlign=top></TD>
|
|
||||||
</TR>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
|
|
||||||
<h3>Models</h3>
|
|
||||||
|
|
||||||
<UL>
|
|
||||||
<LI><tt>pointers, both builtin and smart.</tt>
|
|
||||||
<LI><tt>boost::optional<></tt>
|
|
||||||
</UL>
|
|
||||||
|
|
||||||
<HR>
|
|
||||||
<h3>OptionalPointee and relational operations</h3>
|
|
||||||
<p>This concept does not define any particular semantic for relational operations, therefore,
|
|
||||||
a type which models this concept might have either shallow or deep relational semantics.<br>
|
|
||||||
For instance, pointers, which are models of OptionalPointee, have shallow relational operators:
|
|
||||||
comparisons of pointers do not involve comparisons of pointees.
|
|
||||||
This makes sense for pointers because they have shallow copy semantics.<br>
|
|
||||||
But boost::optional<T>, on the other hand, which is also a model of OptionalPointee, has
|
|
||||||
deep-copy and deep-relational semantics.<br>
|
|
||||||
If generic code is written for this concept, it is important not to use relational
|
|
||||||
operators directly because the semantics might be different depending on the actual type.<br>
|
|
||||||
Still, the concept itsef can be used to define <i>deep</i> relational tests that can
|
|
||||||
be used in generic code with any type which models OptionalPointee:</p>
|
|
||||||
<a name="equal"></a>
|
|
||||||
<p><u>Equivalence relation:</u></p>
|
|
||||||
<pre>template<class OptionalPointee>
|
|
||||||
inline
|
|
||||||
bool equal_pointees ( OptionalPointee const& x, OptionalPointee const& y )
|
|
||||||
{
|
|
||||||
return (!x) != (!y) ? false : ( !x ? true : (*x) == (*y) ) ;
|
|
||||||
}
|
|
||||||
template<class OptionalPointee>
|
|
||||||
struct equal_pointees_t : std::binary_function<OptionalPointee,OptionalPointee,bool>
|
|
||||||
{
|
|
||||||
bool operator() ( OptionalPointee const& x, OptionalPointee const& y ) const
|
|
||||||
{ return equal_pointees(x,y) ; }
|
|
||||||
} ;
|
|
||||||
</pre>
|
|
||||||
<p>The preceding generic function and function object have the following semantics:<br>
|
|
||||||
If both <b>x</b> and <b>y</b> have valid pointees, it compares values via <code>(*x == *y)</code>.<br>
|
|
||||||
If only one has a valid pointee, returns <code>false</code>.<br>
|
|
||||||
If both have invalid pointees, returns <code>true</code>.</p>
|
|
||||||
<a name="less"></a>
|
|
||||||
<p><u>Less-than relation:</u></p>
|
|
||||||
<pre>template<class OptionalPointee>
|
|
||||||
inline
|
|
||||||
bool less_pointees ( OptionalPointee const& x, OptionalPointee const& y )
|
|
||||||
{
|
|
||||||
return !y ? false : ( !x ? true : (*x) < (*y) ) ;
|
|
||||||
}
|
|
||||||
template<class OptionalPointee>
|
|
||||||
struct less_pointees_t : std::binary_function<OptionalPointee,OptionalPointee,bool>
|
|
||||||
{
|
|
||||||
bool operator() ( OptionalPointee const& x, OptionalPointee const& y ) const
|
|
||||||
{ return less_pointees(x,y) ; }
|
|
||||||
} ;
|
|
||||||
</pre>
|
|
||||||
<p>The preceding generic function and function object have the following semantics:<br>
|
|
||||||
If <b>y</b> has an invalid pointee, returns <code>false</code>.<br>
|
|
||||||
Else, if <b>x</b> has an invalid pointee, returns <code>true</code>.<br>
|
|
||||||
Else, ( <b>x</b> and <b>y</b> have valid pointees), compares values via <code>(*x <
|
|
||||||
*y).</code></p>
|
|
||||||
<p><br>
|
|
||||||
All these functions and function
|
|
||||||
objects are is implemented in <a href="../../boost/utility/compare_pointees.hpp">compare_pointees.hpp</a></p>
|
|
||||||
<p>Notice that OptionalPointee does not imply aliasing (and optional<> for instance does not alias);
|
|
||||||
so direct usage of relational operators with the implied aliasing of shallow semantics
|
|
||||||
-as with pointers- should not be used with generic code written for this concept.</p>
|
|
||||||
|
|
||||||
<h3>Acknowledgements</h3>
|
|
||||||
<p>Based on the original concept developed by Augustus Saunders.
|
|
||||||
|
|
||||||
<br>
|
|
||||||
</p>
|
|
||||||
<HR>
|
|
||||||
<TABLE>
|
|
||||||
<TR valign=top>
|
|
||||||
<TD nowrap>Copyright © 2003</TD><TD>
|
|
||||||
<A HREF="mailto:fernando_cacciola@hotmail.com">Fernando Cacciola</A>
|
|
||||||
</TD></TR></TABLE>
|
|
||||||
|
|
||||||
<p>Distributed under the Boost Software License, Version 1.0. See
|
|
||||||
<a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a></p>
|
|
||||||
|
|
||||||
</BODY>
|
|
||||||
</HTML>
|
|
||||||
|
762
call_traits.htm
762
call_traits.htm
@ -1,755 +1,19 @@
|
|||||||
<html>
|
<html>
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta http-equiv="Content-Type"
|
<title>Boost.Utility</title>
|
||||||
content="text/html; charset=iso-8859-1">
|
<meta http-equiv="refresh" content="0; URL=./doc/html/index.html">
|
||||||
<meta name="Template"
|
|
||||||
content="C:\PROGRAM FILES\MICROSOFT OFFICE\OFFICE\html.dot">
|
|
||||||
<meta name="GENERATOR" content="Microsoft FrontPage Express 2.0">
|
|
||||||
<title>Call Traits</title>
|
|
||||||
</head>
|
</head>
|
||||||
|
<body>
|
||||||
<body bgcolor="#FFFFFF" text="#000000" link="#0000FF"
|
Automatic redirection failed, please go to
|
||||||
vlink="#800080">
|
<a href="./doc/html/utility/utilities/call_traits.html">./doc/html/utility/utilities/call_traits.html</a>
|
||||||
|
|
||||||
<h1><img src="../../boost.png" width="276" height="86">Header
|
|
||||||
<<a href="../../boost/detail/call_traits.hpp">boost/call_traits.hpp</a>></h1>
|
|
||||||
|
|
||||||
<p>All of the contents of <boost/call_traits.hpp> are
|
|
||||||
defined inside namespace boost.</p>
|
|
||||||
|
|
||||||
<p>The template class call_traits<T> encapsulates the
|
|
||||||
"best" method to pass a parameter of some type T to or
|
|
||||||
from a function, and consists of a collection of typedefs defined
|
|
||||||
as in the table below. The purpose of call_traits is to ensure
|
|
||||||
that problems like "<a href="#refs">references to references</a>"
|
|
||||||
never occur, and that parameters are passed in the most efficient
|
|
||||||
manner possible (see <a href="#examples">examples</a>). In each
|
|
||||||
case if your existing practice is to use the type defined on the
|
|
||||||
left, then replace it with the call_traits defined type on the
|
|
||||||
right. </p>
|
|
||||||
|
|
||||||
<p>Note that for compilers that do not support either partial
|
|
||||||
specialization or member templates, no benefit will occur from
|
|
||||||
using call_traits: the call_traits defined types will always be
|
|
||||||
the same as the existing practice in this case. In addition if
|
|
||||||
only member templates and not partial template specialisation is
|
|
||||||
support by the compiler (for example Visual C++ 6) then
|
|
||||||
call_traits can not be used with array types (although it can be
|
|
||||||
used to solve the reference to reference problem).</p>
|
|
||||||
|
|
||||||
<table border="0" cellpadding="7" cellspacing="1" width="797">
|
|
||||||
<tr>
|
|
||||||
<td valign="top" width="17%" bgcolor="#008080"><p
|
|
||||||
align="center">Existing practice</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="35%" bgcolor="#008080"><p
|
|
||||||
align="center">call_traits equivalent</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="32%" bgcolor="#008080"><p
|
|
||||||
align="center">Description</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="16%" bgcolor="#008080"><p
|
|
||||||
align="center">Notes</p>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td valign="top" width="17%"><p align="center">T<br>
|
|
||||||
(return by value)</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="35%"><p align="center"><code>call_traits<T>::value_type</code></p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="32%">Defines a type that
|
|
||||||
represents the "value" of type T. Use this for
|
|
||||||
functions that return by value, or possibly for stored
|
|
||||||
values of type T.</td>
|
|
||||||
<td valign="top" width="16%"><p align="center">2</p>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td valign="top" width="17%"><p align="center">T&<br>
|
|
||||||
(return value)</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="35%"><p align="center"><code>call_traits<T>::reference</code></p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="32%">Defines a type that
|
|
||||||
represents a reference to type T. Use for functions that
|
|
||||||
would normally return a T&.</td>
|
|
||||||
<td valign="top" width="16%"><p align="center">1</p>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td valign="top" width="17%"><p align="center">const
|
|
||||||
T&<br>
|
|
||||||
(return value)</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="35%"><p align="center"><code>call_traits<T>::const_reference</code></p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="32%">Defines a type that
|
|
||||||
represents a constant reference to type T. Use for
|
|
||||||
functions that would normally return a const T&.</td>
|
|
||||||
<td valign="top" width="16%"><p align="center">1</p>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td valign="top" width="17%"><p align="center">const
|
|
||||||
T&<br>
|
|
||||||
(function parameter)</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="35%"><p align="center"><code>call_traits<T>::param_type</code></p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="32%">Defines a type that
|
|
||||||
represents the "best" way to pass a parameter
|
|
||||||
of type T to a function.</td>
|
|
||||||
<td valign="top" width="16%"><p align="center">1,3</p>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<p>Notes:</p>
|
|
||||||
|
|
||||||
<ol>
|
|
||||||
<li>If T is already reference type, then call_traits is
|
|
||||||
defined such that <a href="#refs">references to
|
|
||||||
references</a> do not occur (requires partial
|
|
||||||
specialization).</li>
|
|
||||||
<li>If T is an array type, then call_traits defines <code>value_type</code>
|
|
||||||
as a "constant pointer to type" rather than an
|
|
||||||
"array of type" (requires partial
|
|
||||||
specialization). Note that if you are using value_type as
|
|
||||||
a stored value then this will result in storing a "constant
|
|
||||||
pointer to an array" rather than the array itself.
|
|
||||||
This may or may not be a good thing depending upon what
|
|
||||||
you actually need (in other words take care!).</li>
|
|
||||||
<li>If T is a small built in type or a pointer, then <code>param_type</code>
|
|
||||||
is defined as <code>T const</code>, instead of <code>T
|
|
||||||
const&</code>. This can improve the ability of the
|
|
||||||
compiler to optimize loops in the body of the function if
|
|
||||||
they depend upon the passed parameter, the semantics of
|
|
||||||
the passed parameter is otherwise unchanged (requires
|
|
||||||
partial specialization).</li>
|
|
||||||
</ol>
|
|
||||||
|
|
||||||
<p> </p>
|
|
||||||
|
|
||||||
<h3>Copy constructibility</h3>
|
|
||||||
|
|
||||||
<p>The following table defines which call_traits types can always
|
|
||||||
be copy-constructed from which other types, those entries marked
|
|
||||||
with a '?' are true only if and only if T is copy constructible:</p>
|
|
||||||
|
|
||||||
<table border="0" cellpadding="7" cellspacing="1" width="766">
|
|
||||||
<tr>
|
|
||||||
<td valign="top" width="17%"> </td>
|
|
||||||
<td valign="top" colspan="5" width="85%"
|
|
||||||
bgcolor="#008080"><p align="center">To:</p>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td valign="top" width="17%" bgcolor="#008080">From:</td>
|
|
||||||
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
|
||||||
align="center">T</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
|
||||||
align="center">value_type</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
|
||||||
align="center">reference</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
|
||||||
align="center">const_reference</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
|
||||||
align="center">param_type</p>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td valign="top" width="17%" bgcolor="#C0C0C0">T</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">?</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">?</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">Y</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">Y</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">Y</p>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td valign="top" width="17%" bgcolor="#C0C0C0">value_type</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">?</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">?</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">N</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">N</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">Y</p>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td valign="top" width="17%" bgcolor="#C0C0C0">reference</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">?</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">?</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">Y</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">Y</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">Y</p>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td valign="top" width="17%" bgcolor="#C0C0C0">const_reference</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">?</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">N</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">N</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">Y</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">Y</p>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td valign="top" width="17%" bgcolor="#C0C0C0">param_type</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">?</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">?</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">N</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">N</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">Y</p>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<p> </p>
|
|
||||||
|
|
||||||
<p>If T is an assignable type the following assignments are
|
|
||||||
possible:</p>
|
|
||||||
|
|
||||||
<table border="0" cellpadding="7" cellspacing="1" width="766">
|
|
||||||
<tr>
|
|
||||||
<td valign="top" width="17%"> </td>
|
|
||||||
<td valign="top" colspan="5" width="85%"
|
|
||||||
bgcolor="#008080"><p align="center">To:</p>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td valign="top" width="17%" bgcolor="#008080">From:</td>
|
|
||||||
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
|
||||||
align="center">T</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
|
||||||
align="center">value_type</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
|
||||||
align="center">reference</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
|
||||||
align="center">const_reference</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
|
||||||
align="center">param_type</p>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td valign="top" width="17%" bgcolor="#C0C0C0">T</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">Y</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">Y</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">-</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">-</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">-</p>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td valign="top" width="17%" bgcolor="#C0C0C0">value_type</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">Y</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">Y</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">-</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">-</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">-</p>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td valign="top" width="17%" bgcolor="#C0C0C0">reference</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">Y</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">Y</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">-</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">-</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">-</p>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td valign="top" width="17%" bgcolor="#C0C0C0">const_reference</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">Y</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">Y</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">-</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">-</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">-</p>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td valign="top" width="17%" bgcolor="#C0C0C0">param_type</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">Y</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">Y</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">-</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">-</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">-</p>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<p> </p>
|
|
||||||
|
|
||||||
<h3><a name="examples"></a>Examples</h3>
|
|
||||||
|
|
||||||
<p>The following table shows the effect that call_traits has on
|
|
||||||
various types, the table assumes that the compiler supports
|
|
||||||
partial specialization: if it doesn't then all types behave in
|
|
||||||
the same way as the entry for "myclass", and
|
|
||||||
call_traits can not be used with reference or array types.</p>
|
|
||||||
|
|
||||||
<table border="0" cellpadding="7" cellspacing="1" width="766">
|
|
||||||
<tr>
|
|
||||||
<td valign="top" width="17%"> </td>
|
|
||||||
<td valign="top" colspan="5" width="85%"
|
|
||||||
bgcolor="#008080"><p align="center">Call_traits type:</p>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td valign="top" width="17%" bgcolor="#008080"><p
|
|
||||||
align="center">Original type T</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
|
||||||
align="center">value_type</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
|
||||||
align="center">reference</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
|
||||||
align="center">const_reference</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
|
||||||
align="center">param_type</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
|
||||||
align="center">Applies to:</p>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
|
||||||
align="center">myclass</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">myclass</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">myclass&</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">const
|
|
||||||
myclass&</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">myclass
|
|
||||||
const&</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">All user
|
|
||||||
defined types.</p>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
|
||||||
align="center">int</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">int</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">int&</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">const
|
|
||||||
int&</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">int const</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">All small
|
|
||||||
built-in types.</p>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
|
||||||
align="center">int*</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">int*</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">int*&</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">int*const&</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">int* const</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">All
|
|
||||||
pointer types.</p>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
|
||||||
align="center">int&</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">int&</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">int&</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">const
|
|
||||||
int&</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">int&</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">All
|
|
||||||
reference types.</p>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
|
||||||
align="center">const int&</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">const
|
|
||||||
int&</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">const
|
|
||||||
int&</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">const
|
|
||||||
int&</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">const
|
|
||||||
int&</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">All
|
|
||||||
constant-references.</p>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
|
||||||
align="center">int[3]</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">const int*</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">int(&)[3]</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">const int(&)[3]</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">const int*
|
|
||||||
const</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">All array
|
|
||||||
types.</p>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
|
||||||
align="center">const int[3]</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">const int*</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">const int(&)[3]</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">const int(&)[3]</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">const int*
|
|
||||||
const</p>
|
|
||||||
</td>
|
|
||||||
<td valign="top" width="17%"><p align="center">All
|
|
||||||
constant-array types.</p>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<p> </p>
|
|
||||||
|
|
||||||
<h4>Example 1:</h4>
|
|
||||||
|
|
||||||
<p>The following class is a trivial class that stores some type T
|
|
||||||
by value (see the <a href="test/call_traits_test.cpp">call_traits_test.cpp</a>
|
|
||||||
file), the aim is to illustrate how each of the available
|
|
||||||
call_traits typedefs may be used:</p>
|
|
||||||
|
|
||||||
<pre>template <class T>
|
|
||||||
struct contained
|
|
||||||
{
|
|
||||||
// define our typedefs first, arrays are stored by value
|
|
||||||
// so value_type is not the same as result_type:
|
|
||||||
typedef typename boost::call_traits<T>::param_type param_type;
|
|
||||||
typedef typename boost::call_traits<T>::reference reference;
|
|
||||||
typedef typename boost::call_traits<T>::const_reference const_reference;
|
|
||||||
typedef T value_type;
|
|
||||||
typedef typename boost::call_traits<T>::value_type result_type;
|
|
||||||
|
|
||||||
// stored value:
|
|
||||||
value_type v_;
|
|
||||||
|
|
||||||
// constructors:
|
|
||||||
contained() {}
|
|
||||||
contained(param_type p) : v_(p){}
|
|
||||||
// return byval:
|
|
||||||
result_type value() { return v_; }
|
|
||||||
// return by_ref:
|
|
||||||
reference get() { return v_; }
|
|
||||||
const_reference const_get()const { return v_; }
|
|
||||||
// pass value:
|
|
||||||
void call(param_type p){}
|
|
||||||
|
|
||||||
};</pre>
|
|
||||||
|
|
||||||
<h4><a name="refs"></a>Example 2 (the reference to reference
|
|
||||||
problem):</h4>
|
|
||||||
|
|
||||||
<p>Consider the definition of std::binder1st:</p>
|
|
||||||
|
|
||||||
<pre>template <class Operation>
|
|
||||||
class binder1st :
|
|
||||||
public unary_function<typename Operation::second_argument_type, typename Operation::result_type>
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
Operation op;
|
|
||||||
typename Operation::first_argument_type value;
|
|
||||||
public:
|
|
||||||
binder1st(const Operation& x, const typename Operation::first_argument_type& y);
|
|
||||||
typename Operation::result_type operator()(const typename Operation::second_argument_type& x) const;
|
|
||||||
}; </pre>
|
|
||||||
|
|
||||||
<p>Now consider what happens in the relatively common case that
|
|
||||||
the functor takes its second argument as a reference, that
|
|
||||||
implies that <code>Operation::second_argument_type</code> is a
|
|
||||||
reference type, <code>operator()</code> will now end up taking a
|
|
||||||
reference to a reference as an argument, and that is not
|
|
||||||
currently legal. The solution here is to modify <code>operator()</code>
|
|
||||||
to use call_traits:</p>
|
|
||||||
|
|
||||||
<pre>typename Operation::result_type operator()(typename call_traits<typename Operation::second_argument_type>::param_type x) const;</pre>
|
|
||||||
|
|
||||||
<p>Now in the case that <code>Operation::second_argument_type</code>
|
|
||||||
is a reference type, the argument is passed as a reference, and
|
|
||||||
the no "reference to reference" occurs.</p>
|
|
||||||
|
|
||||||
<h4><a name="ex3"></a>Example 3 (the make_pair problem):</h4>
|
|
||||||
|
|
||||||
<p>If we pass the name of an array as one (or both) arguments to <code>std::make_pair</code>,
|
|
||||||
then template argument deduction deduces the passed parameter as
|
|
||||||
"const reference to array of T", this also applies to
|
|
||||||
string literals (which are really array literals). Consequently
|
|
||||||
instead of returning a pair of pointers, it tries to return a
|
|
||||||
pair of arrays, and since an array type is not copy-constructible
|
|
||||||
the code fails to compile. One solution is to explicitly cast the
|
|
||||||
arguments to make_pair to pointers, but call_traits provides a
|
|
||||||
better (i.e. automatic) solution (and one that works safely even
|
|
||||||
in generic code where the cast might do the wrong thing):</p>
|
|
||||||
|
|
||||||
<pre>template <class T1, class T2>
|
|
||||||
std::pair<
|
|
||||||
typename boost::call_traits<T1>::value_type,
|
|
||||||
typename boost::call_traits<T2>::value_type>
|
|
||||||
make_pair(const T1& t1, const T2& t2)
|
|
||||||
{
|
|
||||||
return std::pair<
|
|
||||||
typename boost::call_traits<T1>::value_type,
|
|
||||||
typename boost::call_traits<T2>::value_type>(t1, t2);
|
|
||||||
}</pre>
|
|
||||||
|
|
||||||
<p>Here, the deduced argument types will be automatically
|
|
||||||
degraded to pointers if the deduced types are arrays, similar
|
|
||||||
situations occur in the standard binders and adapters: in
|
|
||||||
principle in any function that "wraps" a temporary
|
|
||||||
whose type is deduced. Note that the function arguments to
|
|
||||||
make_pair are not expressed in terms of call_traits: doing so
|
|
||||||
would prevent template argument deduction from functioning.</p>
|
|
||||||
|
|
||||||
<h4><a name="ex4"></a>Example 4 (optimising fill):</h4>
|
|
||||||
|
|
||||||
<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="../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
|
|
||||||
used, but with the passed parameter "optimized" using
|
|
||||||
call_traits:</p>
|
|
||||||
|
|
||||||
<pre>namespace detail{
|
|
||||||
|
|
||||||
template <bool opt>
|
|
||||||
struct filler
|
|
||||||
{
|
|
||||||
template <typename I, typename T>
|
|
||||||
static void do_fill(I first, I last, typename boost::call_traits<T>::param_type val)
|
|
||||||
{
|
|
||||||
while(first != last)
|
|
||||||
{
|
|
||||||
*first = val;
|
|
||||||
++first;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <>
|
|
||||||
struct filler<true>
|
|
||||||
{
|
|
||||||
template <typename I, typename T>
|
|
||||||
static void do_fill(I first, I last, T val)
|
|
||||||
{
|
|
||||||
memset(first, val, last-first);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class I, class T>
|
|
||||||
inline void fill(I first, I last, const T& val)
|
|
||||||
{
|
|
||||||
enum{ can_opt = boost::is_pointer<I>::value
|
|
||||||
&& boost::is_arithmetic<T>::value
|
|
||||||
&& (sizeof(T) == 1) };
|
|
||||||
typedef detail::filler<can_opt> filler_t;
|
|
||||||
filler_t::template do_fill<I,T>(first, last, val);
|
|
||||||
}</pre>
|
|
||||||
|
|
||||||
<p>Footnote: the reason that this is "optimal" for
|
|
||||||
small built-in types is that with the value passed as "T
|
|
||||||
const" instead of "const T&" the compiler is
|
|
||||||
able to tell both that the value is constant and that it is free
|
|
||||||
of aliases. With this information the compiler is able to cache
|
|
||||||
the passed value in a register, unroll the loop, or use
|
|
||||||
explicitly parallel instructions: if any of these are supported.
|
|
||||||
Exactly how much mileage you will get from this depends upon your
|
|
||||||
compiler - we could really use some accurate benchmarking
|
|
||||||
software as part of boost for cases like this.</p>
|
|
||||||
|
|
||||||
<p>Note that the function arguments to fill are not expressed in
|
|
||||||
terms of call_traits: doing so would prevent template argument
|
|
||||||
deduction from functioning. Instead fill acts as a "thin
|
|
||||||
wrapper" that is there to perform template argument
|
|
||||||
deduction, the compiler will optimise away the call to fill all
|
|
||||||
together, replacing it with the call to filler<>::do_fill,
|
|
||||||
which does use call_traits.</p>
|
|
||||||
|
|
||||||
<h3>Rationale</h3>
|
|
||||||
|
|
||||||
<p>The following notes are intended to briefly describe the
|
|
||||||
rational behind choices made in call_traits.</p>
|
|
||||||
|
|
||||||
<p>All user-defined types follow "existing practice"
|
|
||||||
and need no comment.</p>
|
|
||||||
|
|
||||||
<p>Small built-in types (what the standard calls fundamental
|
|
||||||
types [3.9.1]) differ from existing practice only in the <i>param_type</i>
|
|
||||||
typedef. In this case passing "T const" is compatible
|
|
||||||
with existing practice, but may improve performance in some cases
|
|
||||||
(see <a href="#ex4">Example 4</a>), in any case this should never
|
|
||||||
be any worse than existing practice.</p>
|
|
||||||
|
|
||||||
<p>Pointers follow the same rational as small built-in types.</p>
|
|
||||||
|
|
||||||
<p>For reference types the rational follows <a href="#refs">Example
|
|
||||||
2</a> - references to references are not allowed, so the
|
|
||||||
call_traits members must be defined such that these problems do
|
|
||||||
not occur. There is a proposal to modify the language such that
|
|
||||||
"a reference to a reference is a reference" (issue #106,
|
|
||||||
submitted by Bjarne Stroustrup), call_traits<T>::value_type
|
|
||||||
and call_traits<T>::param_type both provide the same effect
|
|
||||||
as that proposal, without the need for a language change (in
|
|
||||||
other words it's a workaround).</p>
|
|
||||||
|
|
||||||
<p>For array types, a function that takes an array as an argument
|
|
||||||
will degrade the array type to a pointer type: this means that
|
|
||||||
the type of the actual parameter is different from its declared
|
|
||||||
type, something that can cause endless problems in template code
|
|
||||||
that relies on the declared type of a parameter. For example:</p>
|
|
||||||
|
|
||||||
<pre>template <class T>
|
|
||||||
struct A
|
|
||||||
{
|
|
||||||
void foo(T t);
|
|
||||||
};</pre>
|
|
||||||
|
|
||||||
<p><font face="Times New Roman">In this case if we instantiate
|
|
||||||
A<int[2]> then the declared type of the parameter passed to
|
|
||||||
member function foo is int[2], but it's actual type is const int*,
|
|
||||||
if we try to use the type T within the function body, then there
|
|
||||||
is a strong likelyhood that our code will not compile:</font></p>
|
|
||||||
|
|
||||||
<pre>template <class T>
|
|
||||||
void A<T>::foo(T t)
|
|
||||||
{
|
|
||||||
T dup(t); // doesn't compile for case that T is an array.
|
|
||||||
}</pre>
|
|
||||||
|
|
||||||
<p>By using call_traits the degradation from array to pointer is
|
|
||||||
explicit, and the type of the parameter is the same as it's
|
|
||||||
declared type:</p>
|
|
||||||
|
|
||||||
<pre>template <class T>
|
|
||||||
struct A
|
|
||||||
{
|
|
||||||
void foo(typename call_traits<T>::value_type t);
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
void A<T>::foo(typename call_traits<T>::value_type t)
|
|
||||||
{
|
|
||||||
typename call_traits<T>::value_type dup(t); // OK even if T is an array type.
|
|
||||||
}</pre>
|
|
||||||
|
|
||||||
<p>For value_type (return by value), again only a pointer may be
|
|
||||||
returned, not a copy of the whole array, and again call_traits
|
|
||||||
makes the degradation explicit. The value_type member is useful
|
|
||||||
whenever an array must be explicitly degraded to a pointer - <a
|
|
||||||
href="#ex3">Example 3</a> provides the test case (Footnote: the
|
|
||||||
array specialisation for call_traits is the least well understood
|
|
||||||
of all the call_traits specialisations, if the given semantics
|
|
||||||
cause specific problems for you, or don't solve a particular
|
|
||||||
array-related problem, then I would be interested to hear about
|
|
||||||
it. Most people though will probably never need to use this
|
|
||||||
specialisation).</p>
|
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
|
<tt>
|
||||||
<p>Revised 01 September 2000</p>
|
Boost.Utility<br>
|
||||||
|
<br>
|
||||||
<p>
|
Distributed under the Boost Software License, Version 1.0.
|
||||||
Copyright 2000 Steve Cleary, Beman Dawes, Howard
|
(See accompanying file LICENSE_1_0.txt or copy at
|
||||||
Hinnant and John Maddock. <br/>
|
<a href=http://www.boost.org/LICENSE_1_0.txt>http://www.boost.org/LICENSE_1_0.txt</a>) <br>
|
||||||
Use, modification and distribution are subject to the
|
<br>
|
||||||
Boost Software License, Version 1.0.
|
</tt>
|
||||||
(See accompanying file LICENSE_1_0.txt
|
|
||||||
or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
|
|
||||||
http://www.boost.org/LICENSE_1_0.txt
|
|
||||||
</a>).
|
|
||||||
</p>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
@ -1,15 +1,19 @@
|
|||||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta http-equiv=refresh content="0; URL=../core/doc/html/core/checked_delete.html">
|
<title>Boost.Utility</title>
|
||||||
<title>Automatic redirection</title>
|
<meta http-equiv="refresh" content="0; URL=./doc/html/index.html">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
Automatic redirection failed, please go to
|
Automatic redirection failed, please go to
|
||||||
<a href="../core/doc/html/core/checked_delete.html">checked_delete.html</a>. <hr>
|
<a href="../core/doc/html/core/checked_delete.html">../core/doc/html/core/checked_delete.html</a>
|
||||||
<p>© Copyright Beman Dawes, 2001</p>
|
<hr>
|
||||||
<p>Distributed under the Boost Software License, Version 1.0. (See accompanying
|
<tt>
|
||||||
file <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or copy
|
Boost.Utility<br>
|
||||||
at <a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a>)</p>
|
<br>
|
||||||
|
Distributed under the Boost Software License, Version 1.0.
|
||||||
|
(See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
<a href=http://www.boost.org/LICENSE_1_0.txt>http://www.boost.org/LICENSE_1_0.txt</a>) <br>
|
||||||
|
<br>
|
||||||
|
</tt>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -1,16 +1,19 @@
|
|||||||
|
|
||||||
<!--
|
|
||||||
Copyright 2014 Daniel James.
|
|
||||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
||||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
||||||
-->
|
|
||||||
|
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta http-equiv="refresh" content="0; URL=doc/html/compressed_pair.html">
|
<title>Boost.Utility</title>
|
||||||
|
<meta http-equiv="refresh" content="0; URL=./doc/html/index.html">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
Automatic redirection failed, please go to
|
Automatic redirection failed, please go to
|
||||||
<a href="doc/html/compressed_pair.html">doc/html/compressed_pair.html</a>
|
<a href="./doc/html/utility/utilities/compressed_pair.html">./doc/html/utility/utilities/compressed_pair.html</a>
|
||||||
|
<hr>
|
||||||
|
<tt>
|
||||||
|
Boost.Utility<br>
|
||||||
|
<br>
|
||||||
|
Distributed under the Boost Software License, Version 1.0.
|
||||||
|
(See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
<a href=http://www.boost.org/LICENSE_1_0.txt>http://www.boost.org/LICENSE_1_0.txt</a>) <br>
|
||||||
|
<br>
|
||||||
|
</tt>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
74
doc/BOOST_BINARY.qbk
Normal file
74
doc/BOOST_BINARY.qbk
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
[/
|
||||||
|
/ Copyright (c) 2012 Marshall Clow
|
||||||
|
/ Copyright (c) 2021, Alan Freitas
|
||||||
|
/ Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
/]
|
||||||
|
|
||||||
|
[/===============]
|
||||||
|
[#sec:BOOST_BINARY]
|
||||||
|
[section Binary Integer Literals]
|
||||||
|
[/===============]
|
||||||
|
|
||||||
|
[heading Introduction]
|
||||||
|
|
||||||
|
The macro `BOOST_BINARY` is used for the representation of binary
|
||||||
|
literals. It takes as an argument a binary number arranged as an
|
||||||
|
arbitrary amount of 1s and 0s in groupings of length 1 to 8, with
|
||||||
|
groups separated by spaces. The macro serves as a replacement for
|
||||||
|
[@https://en.cppreference.com/w/cpp/language/integer_literal binary integer literals],
|
||||||
|
adopted in C++14.
|
||||||
|
|
||||||
|
The type of the literal yielded is determined by the same rules as
|
||||||
|
those of [@https://en.cppreference.com/w/cpp/language/integer_literal hex and octal literals].
|
||||||
|
By implementation, this macro expands directly to an octal literal during preprocessing, so
|
||||||
|
there is no overhead at runtime and the result is usable in any place that an octal literal
|
||||||
|
would be.
|
||||||
|
|
||||||
|
In order to directly support binary literals with suffixes,
|
||||||
|
additional macros of the form `BOOST_BINARY_XXX` are also
|
||||||
|
provided, where `XXX` is a standard integer suffix in all capital
|
||||||
|
letters.
|
||||||
|
|
||||||
|
In addition, LL and ULL suffixes may be used for representing
|
||||||
|
`long long` and `unsigned long long` types in compilers which provide
|
||||||
|
them as an extension.
|
||||||
|
|
||||||
|
The `BOOST_BINARY` family of macros resides in the header
|
||||||
|
[@../../../include/boost/utility/binary.hpp <boost/utility/binary.hpp>].
|
||||||
|
|
||||||
|
[heading Example]
|
||||||
|
|
||||||
|
```
|
||||||
|
void foo( int );
|
||||||
|
|
||||||
|
void foo( unsigned long );
|
||||||
|
|
||||||
|
void bar()
|
||||||
|
{
|
||||||
|
int value1 = BOOST_BINARY( 100 111000 01 1 110 );
|
||||||
|
|
||||||
|
unsigned long value2 = BOOST_BINARY_UL( 100 001 ); // unsigned long
|
||||||
|
|
||||||
|
long long value3 = BOOST_BINARY_LL( 11 000 ); // long long if supported
|
||||||
|
|
||||||
|
__assert__( BOOST_BINARY( 10010 )
|
||||||
|
& BOOST_BINARY( 11000 )
|
||||||
|
== BOOST_BINARY( 10000 )
|
||||||
|
);
|
||||||
|
|
||||||
|
foo( BOOST_BINARY( 1010 ) ); // calls the first foo
|
||||||
|
|
||||||
|
foo( BOOST_BINARY_LU( 1010 ) ); // calls the second foo
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
[heading Acknowledgments]
|
||||||
|
|
||||||
|
Contributed by Matt Calabrese.
|
||||||
|
|
||||||
|
[endsect]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
|||||||
[/
|
[/
|
||||||
Copyright 2001, 2003, 2004, 2012 Daryle Walker.
|
Copyright 2001, 2003, 2004, 2012 Daryle Walker.
|
||||||
|
Copyright (c) 2021, Alan Freitas
|
||||||
|
|
||||||
Distributed under the Boost Software License, Version 1.0.
|
Distributed under the Boost Software License, Version 1.0.
|
||||||
|
|
||||||
@ -7,48 +8,43 @@
|
|||||||
or copy at http://boost.org/LICENSE_1_0.txt
|
or copy at http://boost.org/LICENSE_1_0.txt
|
||||||
]
|
]
|
||||||
|
|
||||||
[article Base_From_Member
|
[section:base_from_member Base from Member]
|
||||||
[quickbook 1.5]
|
[block'''<?dbhtml stop-chunking?>''']
|
||||||
[authors [Walker, Daryle]]
|
|
||||||
[copyright 2001, 2003, 2004, 2012 Daryle Walker]
|
|
||||||
[license
|
|
||||||
Distributed under the Boost Software License, Version 1.0.
|
|
||||||
(See accompanying file LICENSE_1_0.txt or copy at
|
|
||||||
[@http://www.boost.org/LICENSE_1_0.txt])
|
|
||||||
]
|
|
||||||
]
|
|
||||||
|
|
||||||
[section Rationale]
|
[heading Introduction]
|
||||||
|
|
||||||
|
The class templates __base_from_member__ support the base-from-member idiom.
|
||||||
When developing a class, sometimes a base class needs to be initialized
|
When developing a class, sometimes a base class needs to be initialized
|
||||||
with a member of the current class. As a na\u00EFve example:
|
with a member of the current class. As a na\u00EFve example:
|
||||||
|
|
||||||
#include <streambuf> /* for std::streambuf */
|
```
|
||||||
#include <ostream> /* for std::ostream */
|
#include <streambuf> /* for std::streambuf */
|
||||||
|
#include <ostream> /* for std::ostream */
|
||||||
|
|
||||||
class fdoutbuf
|
class fdoutbuf
|
||||||
: public std::streambuf
|
: public __std_streambuf__
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit fdoutbuf( int fd );
|
explicit fdoutbuf( int fd );
|
||||||
//...
|
//...
|
||||||
};
|
};
|
||||||
|
|
||||||
class fdostream
|
class fdostream
|
||||||
: public std::ostream
|
: public __std_ostream__
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
fdoutbuf buf;
|
fdoutbuf buf;
|
||||||
public:
|
public:
|
||||||
explicit fdostream( int fd )
|
explicit fdostream( int fd )
|
||||||
: buf( fd ), std::ostream( &buf ) {}
|
: buf( fd ), __std_ostream__( &buf ) {}
|
||||||
//...
|
//...
|
||||||
};
|
};
|
||||||
|
```
|
||||||
|
|
||||||
This is undefined because C++'s initialization order mandates that the base
|
This is undefined because C++'s initialization order mandates that the base
|
||||||
class is initialized before the member it uses. [@http://www.moocat.org R.
|
class is initialized before the member it uses. [@http://www.moocat.org R.
|
||||||
Samuel Klatchko] developed a way around this by using the initialization
|
Samuel Klatchko] developed a way around this by using the initialization
|
||||||
order in his favor. Base classes are intialized in order of declaration, so
|
order in his favor. Base classes are initialized in order of declaration, so
|
||||||
moving the desired member to another base class, that is initialized before
|
moving the desired member to another base class, that is initialized before
|
||||||
the desired base class, can ensure proper initialization.
|
the desired base class, can ensure proper initialization.
|
||||||
|
|
||||||
@ -58,7 +54,7 @@ A custom base class can be made for this idiom:
|
|||||||
#include <ostream> /* for std::ostream */
|
#include <ostream> /* for std::ostream */
|
||||||
|
|
||||||
class fdoutbuf
|
class fdoutbuf
|
||||||
: public std::streambuf
|
: public __std_streambuf__
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit fdoutbuf( int fd );
|
explicit fdoutbuf( int fd );
|
||||||
@ -75,10 +71,10 @@ A custom base class can be made for this idiom:
|
|||||||
|
|
||||||
class fdostream
|
class fdostream
|
||||||
: private fdostream_pbase
|
: private fdostream_pbase
|
||||||
, public std::ostream
|
, public __std_ostream__
|
||||||
{
|
{
|
||||||
typedef fdostream_pbase pbase_type;
|
typedef fdostream_pbase pbase_type;
|
||||||
typedef std::ostream base_type;
|
typedef __std_ostream__ base_type;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit fdostream( int fd )
|
explicit fdostream( int fd )
|
||||||
@ -104,9 +100,8 @@ parameter, an integer, that exists solely to provide type differentiation.
|
|||||||
This parameter has a default value so a single use of a particular member
|
This parameter has a default value so a single use of a particular member
|
||||||
type does not need to concern itself with the integer.
|
type does not need to concern itself with the integer.
|
||||||
|
|
||||||
[endsect]
|
|
||||||
|
|
||||||
[section Synopsis]
|
[heading Synopsis]
|
||||||
|
|
||||||
#include <type_traits> /* exposition only */
|
#include <type_traits> /* exposition only */
|
||||||
|
|
||||||
@ -115,41 +110,41 @@ type does not need to concern itself with the integer.
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
template < typename MemberType, int UniqueID = 0 >
|
template < typename MemberType, int UniqueID = 0 >
|
||||||
class boost::base_from_member
|
class __boost_base_from_member__
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
MemberType member;
|
MemberType member;
|
||||||
|
|
||||||
#if ``['C++11 is in use]``
|
#if ``['C++11 is in use]``
|
||||||
template< typename ...T >
|
template< typename ...T >
|
||||||
explicit constexpr base_from_member( T&& ...x )
|
explicit constexpr __base_from_member__( T&& ...x )
|
||||||
noexcept( std::is_nothrow_constructible<MemberType, T...>::value );
|
noexcept( __std_is_nothrow_constructible__<MemberType, T...>::value );
|
||||||
#else
|
#else
|
||||||
base_from_member();
|
__base_from_member__();
|
||||||
|
|
||||||
template< typename T1 >
|
template< typename T1 >
|
||||||
explicit base_from_member( T1 x1 );
|
explicit __base_from_member__( T1 x1 );
|
||||||
|
|
||||||
template< typename T1, typename T2 >
|
template< typename T1, typename T2 >
|
||||||
base_from_member( T1 x1, T2 x2 );
|
__base_from_member__( T1 x1, T2 x2 );
|
||||||
|
|
||||||
//...
|
//...
|
||||||
|
|
||||||
template< typename T1, typename T2, typename T3, typename T4,
|
template< typename T1, typename T2, typename T3, typename T4,
|
||||||
typename T5, typename T6, typename T7, typename T8, typename T9,
|
typename T5, typename T6, typename T7, typename T8, typename T9,
|
||||||
typename T10 >
|
typename T10 >
|
||||||
base_from_member( T1 x1, T2 x2, T3 x3, T4 x4, T5 x5, T6 x6, T7 x7,
|
__base_from_member__( T1 x1, T2 x2, T3 x3, T4 x4, T5 x5, T6 x6, T7 x7,
|
||||||
T8 x8, T9 x9, T10 x10 );
|
T8 x8, T9 x9, T10 x10 );
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
template < typename MemberType, int UniqueID >
|
template < typename MemberType, int UniqueID >
|
||||||
class base_from_member<MemberType&, UniqueID>
|
class __base_from_member__<MemberType&, UniqueID>
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
MemberType& member;
|
MemberType& member;
|
||||||
|
|
||||||
explicit constexpr base_from_member( MemberType& x )
|
explicit constexpr __base_from_member__( MemberType& x )
|
||||||
noexcept;
|
noexcept;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -158,21 +153,21 @@ the type of the based-member. It has a last template parameter `UniqueID`,
|
|||||||
that is an `int`, to differentiate between multiple base classes that use
|
that is an `int`, to differentiate between multiple base classes that use
|
||||||
the same based-member type. The last template parameter has a default value
|
the same based-member type. The last template parameter has a default value
|
||||||
of zero if it is omitted. The class template has a protected data member
|
of zero if it is omitted. The class template has a protected data member
|
||||||
called `member` that the derived class can use for later base classes (or
|
called `member` that the derived class can use for later base classes or
|
||||||
itself).
|
itself.
|
||||||
|
|
||||||
If the appropriate features of C++11 are present, there will be a single
|
If the appropriate features of C++11 are present, there will be a single
|
||||||
constructor template. It implements ['perfect forwarding] to the best
|
constructor template. It implements ['perfect forwarding] to the best
|
||||||
constructor call of `member` (if any). The constructor template is marked
|
constructor call of `member` if any. The constructor template is marked
|
||||||
both `constexpr` and `explicit`. The former will be ignored if the
|
both `constexpr` and `explicit`. The former will be ignored if the
|
||||||
corresponding inner constructor call (of `member`) does not have the marker.
|
corresponding inner constructor call of `member` does not have the marker.
|
||||||
The latter binds the other way; always taking effect, even when the inner
|
The latter binds the other way; always taking effect, even when the inner
|
||||||
constructor call does not have the marker. The constructor template
|
constructor call does not have the marker. The constructor template
|
||||||
propagates the `noexcept` status of the inner constructor call. (The
|
propagates the `noexcept` status of the inner constructor call. The
|
||||||
constructor template has a trailing parameter with a default value that
|
constructor template has a trailing parameter with a default value that
|
||||||
disables the template when its signature is too close to the signatures of
|
disables the template when its signature is too close to the signatures of
|
||||||
the automatically-defined non-template copy- and/or move-constructors of
|
the automatically-defined non-template copy- and/or move-constructors of
|
||||||
`base_from_member`.)
|
__base_from_member__.
|
||||||
|
|
||||||
On earlier-standard compilers, there is a default constructor and several
|
On earlier-standard compilers, there is a default constructor and several
|
||||||
constructor member templates. These constructor templates can take as many
|
constructor member templates. These constructor templates can take as many
|
||||||
@ -195,150 +190,157 @@ maintain the same maximum size. (Example code would be a class that uses
|
|||||||
this class template as a base class for a member with a flexible set of
|
this class template as a base class for a member with a flexible set of
|
||||||
constructors.) This constant is ignored when C++11 features are present.
|
constructors.) This constant is ignored when C++11 features are present.
|
||||||
|
|
||||||
[endsect]
|
|
||||||
|
|
||||||
[section Usage]
|
[heading Basic Usage]
|
||||||
|
|
||||||
With the starting example, the `fdoutbuf` sub-object needs to be
|
With the starting example, the `fdoutbuf` sub-object needs to be
|
||||||
encapsulated in a base class that is inheirited before `std::ostream`.
|
encapsulated in a base class that is inherited before `__std_ostream__`.
|
||||||
|
|
||||||
#include <boost/utility/base_from_member.hpp>
|
```
|
||||||
|
#include <boost/utility/base_from_member.hpp>
|
||||||
|
|
||||||
#include <streambuf> // for std::streambuf
|
#include <streambuf> // for std::streambuf
|
||||||
#include <ostream> // for std::ostream
|
#include <ostream> // for __std_ostream__
|
||||||
|
|
||||||
class fdoutbuf
|
class fdoutbuf
|
||||||
: public std::streambuf
|
: public __std_streambuf__
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit fdoutbuf( int fd );
|
explicit fdoutbuf( int fd );
|
||||||
//...
|
//...
|
||||||
};
|
};
|
||||||
|
|
||||||
class fdostream
|
class fdostream
|
||||||
: private boost::base_from_member<fdoutbuf>
|
: private __boost_base_from_member__<fdoutbuf>
|
||||||
, public std::ostream
|
, public __std_ostream__
|
||||||
{
|
{
|
||||||
// Helper typedef's
|
// Helper typedef's
|
||||||
typedef boost::base_from_member<fdoutbuf> pbase_type;
|
typedef __boost_base_from_member__<fdoutbuf> pbase_type;
|
||||||
typedef std::ostream base_type;
|
typedef __std_ostream__ base_type;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit fdostream( int fd )
|
explicit fdostream( int fd )
|
||||||
: pbase_type( fd ), base_type( &member ){}
|
: pbase_type( fd ), base_type( &member ){}
|
||||||
//...
|
//...
|
||||||
};
|
};
|
||||||
|
```
|
||||||
|
|
||||||
The base-from-member idiom is an implementation detail, so it should not
|
The base-from-member idiom is an implementation detail, so it should not
|
||||||
be visible to the clients (or any derived classes) of `fdostream`. Due to
|
be visible to the clients (or any derived classes) of `fdostream`. Due to
|
||||||
the initialization order, the `fdoutbuf` sub-object will get initialized
|
the initialization order, the `fdoutbuf` sub-object will get initialized
|
||||||
before the `std::ostream` sub-object does, making the former sub-object
|
before the `__std_ostream__` sub-object does, making the former sub-object
|
||||||
safe to use in the latter sub-object's construction. Since the `fdoutbuf`
|
safe to use in the latter sub-object's construction. Since the `fdoutbuf`
|
||||||
sub-object of the final type is the only sub-object with the name `member`
|
sub-object of the final type is the only sub-object with the name `member`
|
||||||
that name can be used unqualified within the final class.
|
that name can be used unqualified within the final class.
|
||||||
|
|
||||||
[endsect]
|
|
||||||
|
|
||||||
[section Example]
|
[heading Multiple Sub-Objects]
|
||||||
|
|
||||||
The base-from-member class templates should commonly involve only one
|
The base-from-member class templates should commonly involve only one
|
||||||
base-from-member sub-object, usually for attaching a stream-buffer to an
|
base-from-member sub-object, usually for attaching a stream-buffer to an
|
||||||
I/O stream. The next example demonstrates how to use multiple
|
I/O stream. The next example demonstrates how to use multiple
|
||||||
base-from-member sub-objects and the resulting qualification issues.
|
base-from-member sub-objects and the resulting qualification issues.
|
||||||
|
|
||||||
#include <boost/utility/base_from_member.hpp>
|
```
|
||||||
|
#include <boost/utility/base_from_member.hpp>
|
||||||
|
|
||||||
#include <cstddef> /* for NULL */
|
#include <cstddef> /* for NULL */
|
||||||
|
|
||||||
struct an_int
|
struct an_int
|
||||||
{
|
{
|
||||||
int y;
|
int y;
|
||||||
|
|
||||||
an_int( float yf );
|
an_int( float yf );
|
||||||
};
|
};
|
||||||
|
|
||||||
class switcher
|
class switcher
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
switcher();
|
switcher();
|
||||||
switcher( double, int * );
|
switcher( double, int * );
|
||||||
//...
|
//...
|
||||||
};
|
};
|
||||||
|
|
||||||
class flow_regulator
|
class flow_regulator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
flow_regulator( switcher &, switcher & );
|
flow_regulator( switcher &, switcher & );
|
||||||
//...
|
//...
|
||||||
};
|
};
|
||||||
|
|
||||||
template < unsigned Size >
|
template < unsigned Size >
|
||||||
class fan
|
class fan
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit fan( switcher );
|
explicit fan( switcher );
|
||||||
//...
|
//...
|
||||||
};
|
};
|
||||||
|
|
||||||
class system
|
class system
|
||||||
: private boost::base_from_member<an_int>
|
: private __boost_base_from_member__<an_int>
|
||||||
, private boost::base_from_member<switcher>
|
, private __boost_base_from_member__<switcher>
|
||||||
, private boost::base_from_member<switcher, 1>
|
, private __boost_base_from_member__<switcher, 1>
|
||||||
, private boost::base_from_member<switcher, 2>
|
, private __boost_base_from_member__<switcher, 2>
|
||||||
, protected flow_regulator
|
, protected flow_regulator
|
||||||
, public fan<6>
|
, public fan<6>
|
||||||
{
|
{
|
||||||
// Helper typedef's
|
// Helper typedef's
|
||||||
typedef boost::base_from_member<an_int> pbase0_type;
|
typedef __boost_base_from_member__<an_int> pbase0_type;
|
||||||
typedef boost::base_from_member<switcher> pbase1_type;
|
typedef __boost_base_from_member__<switcher> pbase1_type;
|
||||||
typedef boost::base_from_member<switcher, 1> pbase2_type;
|
typedef __boost_base_from_member__<switcher, 1> pbase2_type;
|
||||||
typedef boost::base_from_member<switcher, 2> pbase3_type;
|
typedef __boost_base_from_member__<switcher, 2> pbase3_type;
|
||||||
|
|
||||||
typedef flow_regulator base1_type;
|
typedef flow_regulator base1_type;
|
||||||
typedef fan<6> base2_type;
|
typedef fan<6> base2_type;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
system( double x );
|
system( double x );
|
||||||
//...
|
//...
|
||||||
};
|
};
|
||||||
|
|
||||||
system::system( double x )
|
system::system( double x )
|
||||||
: pbase0_type( 0.2 )
|
: pbase0_type( 0.2 )
|
||||||
, pbase1_type()
|
, pbase1_type()
|
||||||
, pbase2_type( -16, &this->pbase0_type::member.y )
|
, pbase2_type( -16, &this->pbase0_type::member.y )
|
||||||
, pbase3_type( x, static_cast<int *>(NULL) )
|
, pbase3_type( x, static_cast<int *>(NULL) )
|
||||||
, base1_type( pbase3_type::member, pbase1_type::member )
|
, base1_type( pbase3_type::member, pbase1_type::member )
|
||||||
, base2_type( pbase2_type::member )
|
, base2_type( pbase2_type::member )
|
||||||
{
|
{
|
||||||
//...
|
//...
|
||||||
}
|
}
|
||||||
|
```
|
||||||
|
|
||||||
The final class has multiple sub-objects with the name `member`, so any
|
The final class has multiple sub-objects with the name `member`, so any
|
||||||
use of that name needs qualification by a name of the appropriate base
|
use of that name needs qualification by a name of the appropriate base
|
||||||
type. (Using `typedef`s ease mentioning the base types.) However, the fix
|
type. Using `typedef`s ease mentioning the base types.
|
||||||
introduces a new problem when a pointer is needed. Using the address
|
|
||||||
operator with a sub-object qualified with its class's name results in a
|
However, the fix introduces a new problem when a pointer is needed. Using the
|
||||||
pointer-to-member (here, having a type of `an_int boost::base_from_member<
|
address operator with a sub-object qualified with its class's name results in a
|
||||||
an_int, 0> :: *`) instead of a pointer to the member (having a type of
|
pointer-to-member (here, having a type of `an_int __boost_base_from_member__<an_int, 0>:: *`)
|
||||||
`an_int *`). The new problem is fixed by qualifying the sub-object with
|
instead of a pointer to the member (having a type of `an_int *`).
|
||||||
`this->` and is needed just for pointers, and not for references or values.
|
The new problem is fixed by qualifying the sub-object with `this->` and is needed
|
||||||
|
just for pointers, and not for references or values.
|
||||||
|
|
||||||
There are some argument conversions in the initialization. The constructor
|
There are some argument conversions in the initialization. The constructor
|
||||||
argument for `pbase0_type` is converted from `double` to `float`. The first
|
argument for `pbase0_type` is converted from `double` to `float`. The first
|
||||||
constructor argument for `pbase2_type` is converted from `int` to `double`.
|
constructor argument for `pbase2_type` is converted from `int` to `double`.
|
||||||
|
|
||||||
The second constructor argument for `pbase3_type` is a special case of
|
The second constructor argument for `pbase3_type` is a special case of
|
||||||
necessary conversion; all forms of the null-pointer literal in C++ (except
|
necessary conversion; all forms of the null-pointer literal in C++ (except
|
||||||
`nullptr` from C++11) also look like compile-time integral expressions, so
|
`nullptr` from C++11) also look like compile-time integral expressions, so
|
||||||
C++ always interprets such code as an integer when it has overloads that can
|
C++ always interprets such code as an integer when it has overloads that can
|
||||||
take either an integer or a pointer. The last conversion is necessary for the
|
take either an integer or a pointer.
|
||||||
compiler to call a constructor form with the exact pointer type used in
|
|
||||||
`switcher`'s constructor. (If C++11's `nullptr` is used, it still needs a
|
|
||||||
conversion if multiple pointer types can be accepted in a constructor call
|
|
||||||
but `std::nullptr_t` cannot.)
|
|
||||||
|
|
||||||
[endsect]
|
The last conversion is necessary for the compiler to call a constructor form
|
||||||
|
with the exact pointer type used in `switcher`'s constructor. (If C++11's
|
||||||
|
__nullptr__ is used, it still needs a conversion if multiple pointer types can
|
||||||
|
be accepted in a constructor call but `__std_nullptr_t__` cannot.)
|
||||||
|
|
||||||
[section Acknowledgments]
|
[heading Acknowledgments]
|
||||||
|
|
||||||
|
Author: Walker, Daryle
|
||||||
|
|
||||||
|
Copyright 2001, 2003, 2004, 2012 Daryle Walker
|
||||||
|
|
||||||
* [@http://www.boost.org/people/ed_brey.htm Ed Brey] suggested some interface
|
* [@http://www.boost.org/people/ed_brey.htm Ed Brey] suggested some interface
|
||||||
changes.
|
changes.
|
||||||
@ -353,10 +355,10 @@ the idiom of how to use a class member for initializing a base class.
|
|||||||
|
|
||||||
* Jonathan Turkanis supplied an implementation of generating the constructor
|
* Jonathan Turkanis supplied an implementation of generating the constructor
|
||||||
templates that can be controlled and automated with macros. The
|
templates that can be controlled and automated with macros. The
|
||||||
implementation uses the [@../../../preprocessor/index.html Preprocessor library].
|
implementation uses the [@boost:/doc/html/preprocessor/index.html Preprocessor library].
|
||||||
|
|
||||||
* [@http://www.boost.org/people/daryle_walker.html">Daryle Walker] started the
|
* [@http://www.boost.org/people/daryle_walker.html">Daryle Walker] started the
|
||||||
library. Contributed the test file [@../../test/base_from_member_test.cpp
|
library. Contributed the test file [@../../../test/base_from_member_test.cpp
|
||||||
base_from_member_test.cpp].
|
base_from_member_test.cpp].
|
||||||
|
|
||||||
[endsect]
|
[endsect]
|
||||||
|
432
doc/call_traits.qbk
Normal file
432
doc/call_traits.qbk
Normal file
@ -0,0 +1,432 @@
|
|||||||
|
[/
|
||||||
|
/ Copyright (c) 2012 Marshall Clow
|
||||||
|
/ Copyright (c) 2021, Alan Freitas
|
||||||
|
/
|
||||||
|
/ Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
/]
|
||||||
|
|
||||||
|
[/===============]
|
||||||
|
[section Call Traits]
|
||||||
|
[/===============]
|
||||||
|
|
||||||
|
[heading Introduction]
|
||||||
|
|
||||||
|
All of the contents of [@../../../include/boost/call_traits.hpp `<boost/call_traits.hpp>`] are
|
||||||
|
defined inside `namespace boost`.
|
||||||
|
|
||||||
|
The template class __call_traits_T__ encapsulates the
|
||||||
|
"best" method to pass a parameter of some type `T` to or
|
||||||
|
from a function, and consists of a collection of `typedef`s defined
|
||||||
|
as in the table below. The purpose of __call_traits__ is to ensure
|
||||||
|
that problems like [link sec:refs "references to references"]
|
||||||
|
never occur, and that parameters are passed in the most efficient
|
||||||
|
manner possible, as in the [link sec:examples examples]. In each
|
||||||
|
case, if your existing practice is to use the type defined on the
|
||||||
|
left, then replace it with the __call_traits__ defined type on the
|
||||||
|
right.
|
||||||
|
|
||||||
|
Note that for compilers that do not support either partial
|
||||||
|
specialization or member templates, no benefit will occur from
|
||||||
|
using __call_traits__: the __call_traits__ defined types will always be
|
||||||
|
the same as the existing practice in this case. In addition if
|
||||||
|
only member templates and not partial template specialisation is
|
||||||
|
support by the compiler (for example Visual C++ 6) then
|
||||||
|
__call_traits__ cannot be used with array types, although it can still be
|
||||||
|
used to solve the reference to reference problem.
|
||||||
|
|
||||||
|
[table __call_traits__ types
|
||||||
|
[[Existing practice] [__call_traits__ equivalent] [Description] [Notes]]
|
||||||
|
[
|
||||||
|
[`T`
|
||||||
|
|
||||||
|
(return by value)
|
||||||
|
]
|
||||||
|
[
|
||||||
|
__call_traits_T__`::value_type`
|
||||||
|
]
|
||||||
|
[
|
||||||
|
Defines a type that represents the "value" of type `T`.
|
||||||
|
|
||||||
|
Use this for functions that return by value, or possibly for stored values of type `T`.
|
||||||
|
]
|
||||||
|
[2]
|
||||||
|
]
|
||||||
|
[
|
||||||
|
[`T&`
|
||||||
|
|
||||||
|
(return value)
|
||||||
|
]
|
||||||
|
[
|
||||||
|
__call_traits_T__`::reference`
|
||||||
|
]
|
||||||
|
[
|
||||||
|
Defines a type that represents a reference to type `T`.
|
||||||
|
|
||||||
|
Use for functions that would normally return a `T&`.
|
||||||
|
]
|
||||||
|
[1]
|
||||||
|
]
|
||||||
|
[
|
||||||
|
[`const T&`
|
||||||
|
|
||||||
|
(return value)
|
||||||
|
]
|
||||||
|
[
|
||||||
|
__call_traits_T__`::const_reference`
|
||||||
|
]
|
||||||
|
[
|
||||||
|
Defines a type that represents a constant reference to type `T`.
|
||||||
|
|
||||||
|
Use for functions that would normally return a `const T&`.
|
||||||
|
]
|
||||||
|
[1]
|
||||||
|
]
|
||||||
|
[
|
||||||
|
[`const T&`
|
||||||
|
|
||||||
|
(function parameter)
|
||||||
|
]
|
||||||
|
[
|
||||||
|
__call_traits_T__`::param_type`
|
||||||
|
]
|
||||||
|
[
|
||||||
|
Defines a type that represents the "best" way to pass a parameter of type `T` to a function.
|
||||||
|
]
|
||||||
|
[1,3]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
|
||||||
|
# If `T` is already reference type, then __call_traits__ is
|
||||||
|
defined such that [link sec:refs "references to references"]
|
||||||
|
do not occur (requires partial specialization).
|
||||||
|
# If `T` is an array type, then __call_traits__ defines `value_type`
|
||||||
|
as a "constant pointer to type" rather than an
|
||||||
|
"array of type" (requires partial specialization).
|
||||||
|
Note that if you are using `value_type` as a stored value
|
||||||
|
then this will result in storing a "constant pointer to
|
||||||
|
an array" rather than the array itself. This may or may
|
||||||
|
not be a good thing depending upon what you actually
|
||||||
|
need (in other words take care!).
|
||||||
|
# If `T` is a small built in type or a pointer, then `param_type`
|
||||||
|
is defined as `T const`, instead of `T const&`. This can
|
||||||
|
improve the ability of the compiler to optimize loops in
|
||||||
|
the body of the function if they depend upon the passed
|
||||||
|
parameter, the semantics of the passed parameter is
|
||||||
|
otherwise unchanged (requires partial specialization).
|
||||||
|
|
||||||
|
|
||||||
|
[heading Copy constructibility]
|
||||||
|
|
||||||
|
The following table defines which __call_traits__ types can always
|
||||||
|
be copy-constructed from which other types:
|
||||||
|
|
||||||
|
[table Which __call_traits__ types can always be copy-constructed from which other types
|
||||||
|
[[] [To `T`] [To `value_type`] [To `reference`] [To `const_reference`] [To `param_type`]]
|
||||||
|
[[From `T`] [iff `T` is copy constructible] [iff `T` is copy constructible] [Yes] [Yes] [Yes]]
|
||||||
|
[[From `value_type`] [iff `T` is copy constructible] [iff `T` is copy constructible] [No] [No] [Yes]]
|
||||||
|
[[From `reference`] [iff `T` is copy constructible] [iff `T` is copy constructible] [Yes] [Yes] [Yes]]
|
||||||
|
[[From `const_reference`] [iff `T` is copy constructible] [No] [No] [Yes] [Yes]]
|
||||||
|
[[From `param_type`] [iff `T` is copy constructible] [iff `T` is copy constructible] [No] [No] [Yes]]
|
||||||
|
]
|
||||||
|
|
||||||
|
If `T` is an assignable type the following assignments are possible:
|
||||||
|
|
||||||
|
[table Which __call_traits__ types are assignable from which other types
|
||||||
|
[[] [To `T`] [To `value_type`] [To `reference`] [To `const_reference`] [To `param_type`]]
|
||||||
|
[[From `T`] [Yes] [Yes] [-] [-] [-]]
|
||||||
|
[[From `value_type`] [Yes] [Yes] [-] [-] [-]]
|
||||||
|
[[From `reference`] [Yes] [Yes] [-] [-] [-]]
|
||||||
|
[[From `const_reference`] [Yes] [Yes] [-] [-] [-]]
|
||||||
|
[[From `param_type`] [Yes] [Yes] [-] [-] [-]]
|
||||||
|
]
|
||||||
|
|
||||||
|
[#sec:examples]
|
||||||
|
[heading Examples]
|
||||||
|
|
||||||
|
The following table shows the effect that __call_traits__ has on
|
||||||
|
various types.
|
||||||
|
|
||||||
|
[table Examples of __call_traits__ types
|
||||||
|
[[] [__call_traits__::`value_type`] [__call_traits__::`reference`] [__call_traits__::`const_reference`] [__call_traits__::`param_type`] [Applies to:]]
|
||||||
|
[[From `my_class`] [`my_class`] [`my_class&`] [`const my_class&`] [`my_class const&`] [All user-defined types]]
|
||||||
|
[[From `int`] [`int`] [`int&`] [`const int&`] [`int const`] [All small built-in types]]
|
||||||
|
[[From `int*`] [`int*`] [`int*&`] [`int* const &`] [`int* const`] [All pointer types]]
|
||||||
|
[[From `int&`] [`int&`] [`int&`] [`const int&`] [`int&`] [All reference types]]
|
||||||
|
[[From `const int&`] [`const int&`] [`const int&`] [`const int&`] [`const int&`] [All constant reference types]]
|
||||||
|
[[From `int[3]`] [`const int*`] [`int(&)[3]`] [`const int(&)[3]`] [`const int* const`] [All array types]]
|
||||||
|
[[From `const int[3]`] [`const int*`] [`const int(&)[3]`] [`const int(&)[3]`] [`const int *const`] [All constant array types]]
|
||||||
|
]
|
||||||
|
|
||||||
|
The table assumes the compiler supports partial
|
||||||
|
specialization: if it does not then all types behave in
|
||||||
|
the same way as the entry for "`my_class`", and
|
||||||
|
__call_traits__ can not be used with reference or array types.
|
||||||
|
|
||||||
|
[heading Example 1:]
|
||||||
|
|
||||||
|
The following class is a trivial class that stores some type `T`
|
||||||
|
by value (see the [@../../../test/call_traits_test.cpp `call_traits_test.cpp`]
|
||||||
|
file). The aim is to illustrate how each of the available
|
||||||
|
__call_traits__ `typedef`s may be used:
|
||||||
|
|
||||||
|
```
|
||||||
|
template <class T>
|
||||||
|
struct contained
|
||||||
|
{
|
||||||
|
// define our typedefs first, arrays are stored by value
|
||||||
|
// so value_type is not the same as result_type:
|
||||||
|
typedef typename __boost_call_traits__<T>::param_type param_type;
|
||||||
|
typedef typename __boost_call_traits__<T>::reference reference;
|
||||||
|
typedef typename __boost_call_traits__<T>::const_reference const_reference;
|
||||||
|
typedef T value_type;
|
||||||
|
typedef typename __boost_call_traits__<T>::value_type result_type;
|
||||||
|
|
||||||
|
// stored value:
|
||||||
|
value_type v_;
|
||||||
|
|
||||||
|
// constructors:
|
||||||
|
contained() {}
|
||||||
|
contained(param_type p) : v_(p){}
|
||||||
|
// return byval:
|
||||||
|
result_type value() { return v_; }
|
||||||
|
// return by_ref:
|
||||||
|
reference get() { return v_; }
|
||||||
|
const_reference const_get()const { return v_; }
|
||||||
|
// pass value:
|
||||||
|
void call(param_type p){}
|
||||||
|
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
[#sec:refs]
|
||||||
|
[heading Example 2 (the reference to reference problem):]
|
||||||
|
|
||||||
|
Consider the definition of __std_binder1st__:
|
||||||
|
|
||||||
|
```
|
||||||
|
template <class Operation>
|
||||||
|
class binder1st :
|
||||||
|
public __std_unary_function__<typename Operation::second_argument_type, typename Operation::result_type>
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
Operation op;
|
||||||
|
typename Operation::first_argument_type value;
|
||||||
|
public:
|
||||||
|
binder1st(const Operation& x, const typename Operation::first_argument_type& y);
|
||||||
|
typename Operation::result_type operator()(const typename Operation::second_argument_type& x) const;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
Now consider what happens in the relatively common case that
|
||||||
|
the functor takes its second argument as a reference, that
|
||||||
|
implies that `Operation::second_argument_type` is a
|
||||||
|
reference type, `operator()` will now end up taking a
|
||||||
|
reference to a reference as an argument, and that is not
|
||||||
|
currently legal. The solution here is to modify `operator()`
|
||||||
|
to use __call_traits__:
|
||||||
|
|
||||||
|
```
|
||||||
|
typename Operation::result_type operator()(typename __call_traits__<typename Operation::second_argument_type>::param_type x) const;
|
||||||
|
```
|
||||||
|
|
||||||
|
Now in the case that `Operation::second_argument_type`
|
||||||
|
is a reference type, the argument is passed as a reference, and
|
||||||
|
the no "reference to reference" occurs.
|
||||||
|
|
||||||
|
[#sec:example3]
|
||||||
|
[heading Example 3 (the `make_pair` problem):]
|
||||||
|
|
||||||
|
If we pass the name of an array as one (or both) arguments to `__std_make_pair__`,
|
||||||
|
then template argument deduction deduces the passed parameter as
|
||||||
|
"const reference to array of `T`", this also applies to
|
||||||
|
string literals (which are really array literals). Consequently
|
||||||
|
instead of returning a pair of pointers, it tries to return a
|
||||||
|
pair of arrays, and since an array type is not copy-constructible
|
||||||
|
the code fails to compile. One solution is to explicitly cast the
|
||||||
|
arguments to __std_make_pair__ to pointers, but __call_traits__ provides a
|
||||||
|
better automatic solution that works safely even in generic code where the
|
||||||
|
cast might do the wrong thing:
|
||||||
|
|
||||||
|
```
|
||||||
|
template <class T1, class T2>
|
||||||
|
__std_pair__<
|
||||||
|
typename __boost_call_traits__<T1>::value_type,
|
||||||
|
typename __boost_call_traits__<T2>::value_type>
|
||||||
|
make_pair(const T1& t1, const T2& t2)
|
||||||
|
{
|
||||||
|
return __std_pair__<
|
||||||
|
typename __boost_call_traits__<T1>::value_type,
|
||||||
|
typename __boost_call_traits__<T2>::value_type>(t1, t2);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Here, the deduced argument types will be automatically
|
||||||
|
degraded to pointers if the deduced types are arrays, similar
|
||||||
|
situations occur in the standard binders and adapters: in
|
||||||
|
principle in any function that "wraps" a temporary
|
||||||
|
whose type is deduced. Note that the function arguments to
|
||||||
|
__std_make_pair__ are not expressed in terms of __call_traits__: doing so
|
||||||
|
would prevent template argument deduction from functioning.
|
||||||
|
|
||||||
|
[#sec:example4]
|
||||||
|
[heading Example 4 (optimising fill):]
|
||||||
|
|
||||||
|
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 [@boost:/doc/html/type_traits/examples/fill_example.cpp `fill_example.cpp`]),
|
||||||
|
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++ implementation is
|
||||||
|
used, but with the passed parameter "optimized" using
|
||||||
|
__call_traits__:
|
||||||
|
|
||||||
|
```
|
||||||
|
template <bool opt>
|
||||||
|
struct filler
|
||||||
|
{
|
||||||
|
template <typename I, typename T>
|
||||||
|
static void do_fill(I first, I last, typename __boost_call_traits__<T>::param_type val)
|
||||||
|
{
|
||||||
|
while(first != last)
|
||||||
|
{
|
||||||
|
*first = val;
|
||||||
|
++first;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct filler<true>
|
||||||
|
{
|
||||||
|
template <typename I, typename T>
|
||||||
|
static void do_fill(I first, I last, T val)
|
||||||
|
{
|
||||||
|
__std_memset__(first, val, last-first);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class I, class T>
|
||||||
|
inline void fill(I first, I last, const T& val)
|
||||||
|
{
|
||||||
|
enum { can_opt = boost::is_pointer<I>::value
|
||||||
|
&& boost::is_arithmetic<T>::value
|
||||||
|
&& (sizeof(T) == 1) };
|
||||||
|
typedef filler<can_opt> filler_t;
|
||||||
|
filler_t::template do_fill<I,T>(first, last, val);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The reason that this is "optimal" for small built-in types is that
|
||||||
|
with the value passed as `T const` instead of `const T&` the compiler is
|
||||||
|
able to tell both that the value is constant and that it is free
|
||||||
|
of aliases. With this information the compiler is able to cache
|
||||||
|
the passed value in a register, unroll the loop, or use
|
||||||
|
explicitly parallel instructions: if any of these are supported.
|
||||||
|
Exactly how much mileage you will get from this depends upon your
|
||||||
|
compiler - we could really use some accurate benchmarking
|
||||||
|
software as part of boost for cases like this.
|
||||||
|
|
||||||
|
Note that the function arguments to fill are not expressed in
|
||||||
|
terms of __call_traits__: doing so would prevent template argument
|
||||||
|
deduction from functioning. Instead fill acts as a "thin
|
||||||
|
wrapper" that is there to perform template argument
|
||||||
|
deduction, the compiler will optimise away the call to fill all
|
||||||
|
together, replacing it with the call to `filler<>::do_fill`,
|
||||||
|
which does use __call_traits__.
|
||||||
|
|
||||||
|
[heading Rationale]
|
||||||
|
|
||||||
|
The following notes are intended to briefly describe the
|
||||||
|
rationale behind choices made in __call_traits__.
|
||||||
|
|
||||||
|
All user-defined types follow "existing practice" and need no comment.
|
||||||
|
|
||||||
|
Small built-in types, what the standard calls [@https://en.cppreference.com/w/cpp/language/types fundamental
|
||||||
|
types], differ from existing practice only in the `param_type`
|
||||||
|
`typedef`. In this case passing `T const` is compatible
|
||||||
|
with existing practice, but may improve performance in some cases
|
||||||
|
(see [link sec:example4 Example 4]). In any case this should never
|
||||||
|
be any worse than existing practice.
|
||||||
|
|
||||||
|
Pointers follow the same rationale as small built-in types.
|
||||||
|
|
||||||
|
For reference types the rationale follows [link sec:refs Example 2]
|
||||||
|
- references to references are not allowed, so the __call_traits__
|
||||||
|
members must be defined such that these problems do
|
||||||
|
not occur. There is a proposal to modify the language such that
|
||||||
|
"a reference to a reference is a reference" (issue #106,
|
||||||
|
submitted by Bjarne Stroustrup). __call_traits_T__`::value_type`
|
||||||
|
and __call_traits_T__`::param_type` both provide the same effect
|
||||||
|
as that proposal, without the need for a language change. In
|
||||||
|
other words, it's a workaround.
|
||||||
|
|
||||||
|
For array types, a function that takes an array as an argument
|
||||||
|
will degrade the array type to a pointer type: this means that
|
||||||
|
the type of the actual parameter is different from its declared
|
||||||
|
type, something that can cause endless problems in template code
|
||||||
|
that relies on the declared type of a parameter.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
```
|
||||||
|
template <class T>
|
||||||
|
struct A
|
||||||
|
{
|
||||||
|
void foo(T t);
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
In this case if we instantiate `A<int[2]>` then the declared type of
|
||||||
|
the parameter passed to member function `foo` is `int[2]`, but its
|
||||||
|
actual type is `const int*`. If we try to use the type `T` within the
|
||||||
|
function body, then there is a strong likelihood that our code will not compile:
|
||||||
|
|
||||||
|
```
|
||||||
|
template <class T>
|
||||||
|
void A<T>::foo(T t)
|
||||||
|
{
|
||||||
|
T dup(t); // doesn't compile for case that T is an array.
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
By using __call_traits__ the degradation from array to pointer is
|
||||||
|
explicit, and the type of the parameter is the same as it's
|
||||||
|
declared type:
|
||||||
|
|
||||||
|
```
|
||||||
|
template <class T>
|
||||||
|
struct A
|
||||||
|
{
|
||||||
|
void foo(typename __call_traits__<T>::value_type t);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
void A<T>::foo(typename __call_traits__<T>::value_type t)
|
||||||
|
{
|
||||||
|
typename __call_traits__<T>::value_type dup(t); // OK even if T is an array type.
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
For `value_type` (return by value), again only a pointer may be
|
||||||
|
returned, not a copy of the whole array, and again __call_traits__
|
||||||
|
makes the degradation explicit. The `value_type` member is useful
|
||||||
|
whenever an array must be explicitly degraded to a pointer -
|
||||||
|
[link sec:example3 Example 3] provides the test case.
|
||||||
|
|
||||||
|
Footnote: the array specialisation for __call_traits__ is the least
|
||||||
|
well understood of all the __call_traits__ specialisations. If the given
|
||||||
|
semantics cause specific problems for you, or does not solve a particular
|
||||||
|
array-related problem, then I would be interested to hear about
|
||||||
|
it. Most people though will probably never need to use this
|
||||||
|
specialisation.
|
||||||
|
|
||||||
|
[endsect]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
|||||||
[/
|
[/
|
||||||
Copyright 2000 Beman Dawes & John Maddock.
|
Copyright 2000 Beman Dawes & John Maddock.
|
||||||
|
Copyright (c) 2021, Alan Freitas
|
||||||
|
|
||||||
Distributed under the Boost Software License, Version 1.0.
|
Distributed under the Boost Software License, Version 1.0.
|
||||||
|
|
||||||
@ -7,89 +8,77 @@
|
|||||||
or copy at http://boost.org/LICENSE_1_0.txt
|
or copy at http://boost.org/LICENSE_1_0.txt
|
||||||
]
|
]
|
||||||
|
|
||||||
[article Compressed_Pair
|
[section Compressed Pair]
|
||||||
[quickbook 1.5]
|
|
||||||
[authors [Cleary, Steve]]
|
|
||||||
[authors [Dawes, Beman]]
|
|
||||||
[authors [Hinnant, Howard]]
|
|
||||||
[authors [Maddock, John]]
|
|
||||||
[copyright 2000 Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock]
|
|
||||||
[license
|
|
||||||
Distributed under the Boost Software License, Version 1.0.
|
|
||||||
(See accompanying file LICENSE_1_0.txt or copy at
|
|
||||||
[@http://www.boost.org/LICENSE_1_0.txt])
|
|
||||||
]
|
|
||||||
]
|
|
||||||
|
|
||||||
[section Overview]
|
[heading Introduction]
|
||||||
|
|
||||||
All of the contents of `<boost/compressed_pair.hpp>` are defined inside
|
All of the contents of [@../../../include/boost/compressed_pair.hpp `<boost/compressed_pair.hpp>`] are defined inside
|
||||||
`namespace boost`.
|
`namespace boost`.
|
||||||
|
|
||||||
The class `compressed_pair` is very similar to `std::pair`, but if either of
|
The class __compressed_pair__ is very similar to __std_pair__. However, if either of
|
||||||
the template arguments are empty classes, then the ['empty base-class
|
the template arguments are empty classes, then the
|
||||||
optimisation] is applied to compress the size of the pair.
|
[@https://en.cppreference.com/w/cpp/language/ebo ['empty base-class optimisation]]
|
||||||
|
is applied to compress the size of the pair.
|
||||||
|
|
||||||
[endsect]
|
[heading Synopsis]
|
||||||
|
|
||||||
[section Synopsis]
|
```cpp
|
||||||
|
template <class T1, class T2>
|
||||||
|
class __compressed_pair__
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef T1 first_type;
|
||||||
|
typedef T2 second_type;
|
||||||
|
typedef typename __call_traits__<first_type>::param_type first_param_type;
|
||||||
|
typedef typename __call_traits__<second_type>::param_type second_param_type;
|
||||||
|
typedef typename __call_traits__<first_type>::reference first_reference;
|
||||||
|
typedef typename __call_traits__<second_type>::reference second_reference;
|
||||||
|
typedef typename __call_traits__<first_type>::const_reference first_const_reference;
|
||||||
|
typedef typename __call_traits__<second_type>::const_reference second_const_reference;
|
||||||
|
|
||||||
template <class T1, class T2>
|
compressed_pair() : base() {}
|
||||||
class compressed_pair
|
compressed_pair(first_param_type x, second_param_type y);
|
||||||
{
|
explicit compressed_pair(first_param_type x);
|
||||||
public:
|
explicit compressed_pair(second_param_type y);
|
||||||
typedef T1 first_type;
|
|
||||||
typedef T2 second_type;
|
|
||||||
typedef typename call_traits<first_type>::param_type first_param_type;
|
|
||||||
typedef typename call_traits<second_type>::param_type second_param_type;
|
|
||||||
typedef typename call_traits<first_type>::reference first_reference;
|
|
||||||
typedef typename call_traits<second_type>::reference second_reference;
|
|
||||||
typedef typename call_traits<first_type>::const_reference first_const_reference;
|
|
||||||
typedef typename call_traits<second_type>::const_reference second_const_reference;
|
|
||||||
|
|
||||||
compressed_pair() : base() {}
|
compressed_pair& operator=(const compressed_pair&);
|
||||||
compressed_pair(first_param_type x, second_param_type y);
|
|
||||||
explicit compressed_pair(first_param_type x);
|
|
||||||
explicit compressed_pair(second_param_type y);
|
|
||||||
|
|
||||||
compressed_pair& operator=(const compressed_pair&);
|
first_reference first();
|
||||||
|
first_const_reference first() const;
|
||||||
|
|
||||||
first_reference first();
|
second_reference second();
|
||||||
first_const_reference first() const;
|
second_const_reference second() const;
|
||||||
|
|
||||||
second_reference second();
|
void swap(compressed_pair& y);
|
||||||
second_const_reference second() const;
|
};
|
||||||
|
```
|
||||||
void swap(compressed_pair& y);
|
|
||||||
};
|
|
||||||
|
|
||||||
The two members of the pair can be accessed using the member functions
|
The two members of the pair can be accessed using the member functions
|
||||||
`first()` and `second()`. Note that not all member functions can be
|
`first()` and `second()`. Note that not all member functions can be
|
||||||
instantiated for all template parameter types. In particular
|
instantiated for all template parameter types. In particular
|
||||||
`compressed_pair` can be instantiated for reference and array types,
|
__compressed_pair__ can be instantiated for reference and array types,
|
||||||
however in these cases the range of constructors that can be used are
|
however in these cases the range of constructors that can be used is
|
||||||
limited. If types `T1` and `T2` are the same type, then there is only
|
limited. If types `T1` and `T2` are the same type, then there is only
|
||||||
one version of the single-argument constructor, and this constructor
|
one version of the single-argument constructor, and this constructor
|
||||||
initialises both values in the pair to the passed value.
|
initialises both values in the pair to the passed value.
|
||||||
|
|
||||||
Note that if either member is a POD type, then that member is not
|
Note that if either member is a [@https://en.cppreference.com/w/cpp/named_req/PODType POD]
|
||||||
zero-initialized by the `compressed_pair` default constructor: it's up
|
type, then that member is not zero-initialized by the __compressed_pair__ default constructor:
|
||||||
to you to supply an initial value for these types if you want them to have
|
it is up to you to supply an initial value for these types if you want them to have
|
||||||
a default value.
|
a default value.
|
||||||
|
|
||||||
Note that `compressed_pair` can not be instantiated if either of the
|
Note that __compressed_pair__ can not be instantiated if either of the
|
||||||
template arguments is a union type, unless there is compiler support for
|
template arguments is a union type, unless there is compiler support for
|
||||||
`boost::is_union`, or if `boost::is_union` is specialised for the union
|
[@boost:/doc/html/type_traits/index.html `boost::is_union`], or
|
||||||
type.
|
if [@boost:/doc/html/type_traits/index.html `boost::is_union`] is
|
||||||
|
specialised for the union type.
|
||||||
|
|
||||||
Finally, a word of caution for Visual C++ 6 users: if either argument is an
|
Finally, a word of caution for Visual C++ 6 users: if either argument is an
|
||||||
empty type, then assigning to that member will produce memory corruption,
|
empty type, then assigning to that member will produce memory corruption,
|
||||||
unless the empty type has a "do nothing" assignment operator defined. This
|
unless the empty type has a "do nothing" assignment operator defined. This
|
||||||
is due to a bug in the way VC6 generates implicit assignment operators.
|
is due to a bug in the way VC6 generates implicit assignment operators.
|
||||||
|
|
||||||
[endsect]
|
[heading Acknowledgments]
|
||||||
|
|
||||||
[section Acknowledgments]
|
|
||||||
|
|
||||||
Based on contributions by Steve Cleary, Beman Dawes, Howard Hinnant and
|
Based on contributions by Steve Cleary, Beman Dawes, Howard Hinnant and
|
||||||
John Maddock.
|
John Maddock.
|
||||||
|
114
doc/declval.qbk
114
doc/declval.qbk
@ -1,114 +0,0 @@
|
|||||||
[/
|
|
||||||
/ Copyright (c) 2008 Howard Hinnant
|
|
||||||
/ Copyright (c) 2009-2012 Vicente J. Botet Escriba
|
|
||||||
/
|
|
||||||
/ Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
||||||
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
||||||
/]
|
|
||||||
|
|
||||||
[article Declval
|
|
||||||
[quickbook 1.5]
|
|
||||||
[authors [Hinnant, Howard]]
|
|
||||||
[authors [Botet Escriba, Vicente J.]]
|
|
||||||
[copyright 2008 Howard Hinnant]
|
|
||||||
[copyright 2009-2012 Vicente J. Botet Escriba]
|
|
||||||
[license
|
|
||||||
Distributed under the Boost Software License, Version 1.0.
|
|
||||||
(See accompanying file LICENSE_1_0.txt or copy at
|
|
||||||
[@http://www.boost.org/LICENSE_1_0.txt])
|
|
||||||
]
|
|
||||||
]
|
|
||||||
|
|
||||||
[/===============]
|
|
||||||
[section Overview]
|
|
||||||
[/===============]
|
|
||||||
|
|
||||||
The motivation for `declval` was introduced in [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2958.html#Value N2958:
|
|
||||||
Moving Swap Forward]. Here follows a rewording of this chapter.
|
|
||||||
|
|
||||||
With the provision of decltype, late-specified return types, and default template-arguments for function templates a
|
|
||||||
new generation of SFINAE patterns will emerge to at least partially compensate the lack of concepts on the C++0x timescale.
|
|
||||||
Using this technique, it is sometimes necessary to obtain an object of a known type in a non-using context, e.g. given the declaration
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
T&& declval(); // not used
|
|
||||||
|
|
||||||
as part of the function template declaration
|
|
||||||
|
|
||||||
template<class To, class From>
|
|
||||||
decltype(static_cast<To>(declval<From>())) convert(From&&);
|
|
||||||
|
|
||||||
or as part of a class template definition
|
|
||||||
|
|
||||||
template<class> class result_of;
|
|
||||||
|
|
||||||
template<class Fn, class... ArgTypes>
|
|
||||||
struct result_of<Fn(ArgTypes...)>
|
|
||||||
{
|
|
||||||
typedef decltype(declval<Fn>()(declval<ArgTypes>()...)) type;
|
|
||||||
};
|
|
||||||
|
|
||||||
The role of the function template declval() is a transformation of a type T into a value without using or evaluating this function.
|
|
||||||
The name is supposed to direct the reader's attention to the fact that the expression `declval<T>()` is an lvalue if and only if
|
|
||||||
T is an lvalue-reference, otherwise an rvalue. To extend the domain of this function we can do a bit better by changing its declaration to
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
typename std::add_rvalue_reference<T>::type declval(); // not used
|
|
||||||
|
|
||||||
which ensures that we can also use cv void as template parameter. The careful reader might have noticed that `declval()`
|
|
||||||
already exists under the name create() as part of the definition of the semantics of the type trait is_convertible in the C++0x standard.
|
|
||||||
|
|
||||||
The provision of a new library component that allows the production of values in unevaluated expressions is considered
|
|
||||||
important to realize constrained templates in C++0x where concepts are not available.
|
|
||||||
This extremely light-weight function is expected to be part of the daily tool-box of the C++0x programmer.
|
|
||||||
|
|
||||||
[endsect]
|
|
||||||
|
|
||||||
|
|
||||||
[/=================]
|
|
||||||
[section:reference Reference ]
|
|
||||||
[/=================]
|
|
||||||
|
|
||||||
`#include <boost/utility/declval.hpp>`
|
|
||||||
|
|
||||||
namespace boost {
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
typename add_rvalue_reference<T>::type declval() noexcept; // as unevaluated operand
|
|
||||||
|
|
||||||
} // namespace boost
|
|
||||||
|
|
||||||
|
|
||||||
The library provides the function template declval to simplify the definition of expressions which occur as unevaluated operands.
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
typename add_rvalue_reference<T>::type declval();
|
|
||||||
|
|
||||||
[*Remarks:] If this function is used, the program is ill-formed.
|
|
||||||
|
|
||||||
[*Remarks:] The template parameter T of declval may be an incomplete type.
|
|
||||||
|
|
||||||
[*Example:]
|
|
||||||
|
|
||||||
template <class To, class From>
|
|
||||||
decltype(static_cast<To>(declval<From>())) convert(From&&);
|
|
||||||
|
|
||||||
Declares a function template convert which only participates in overloading if the type From can be explicitly converted to type To.
|
|
||||||
|
|
||||||
[endsect]
|
|
||||||
|
|
||||||
[/===============]
|
|
||||||
[section History]
|
|
||||||
[/===============]
|
|
||||||
|
|
||||||
[heading boost 1.50]
|
|
||||||
|
|
||||||
Fixes:
|
|
||||||
|
|
||||||
* [@http://svn.boost.org/trac/boost/ticket/6570 #6570] Adding noexcept to boost::declval.
|
|
||||||
|
|
||||||
[endsect]
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
300
doc/in_place_factory.qbk
Normal file
300
doc/in_place_factory.qbk
Normal file
@ -0,0 +1,300 @@
|
|||||||
|
[/
|
||||||
|
/ Copyright (c) 2012 Marshall Clow
|
||||||
|
/ Copyright (c) 2021, Alan Freitas
|
||||||
|
/
|
||||||
|
/ Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
/]
|
||||||
|
|
||||||
|
[/===============]
|
||||||
|
[#sec:in_place_factory]
|
||||||
|
[section In-place Factory]
|
||||||
|
[/===============]
|
||||||
|
|
||||||
|
[heading Introduction]
|
||||||
|
|
||||||
|
Suppose we have a class
|
||||||
|
|
||||||
|
```
|
||||||
|
struct X
|
||||||
|
{
|
||||||
|
X ( int, _std__string_ ) ;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
And a container for it which supports an empty state. That is, a container which can contain zero objects:
|
||||||
|
|
||||||
|
```
|
||||||
|
struct C
|
||||||
|
{
|
||||||
|
C() : contained_(0) {}
|
||||||
|
~C() { delete contained_ ; }
|
||||||
|
X* contained_ ;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
A container designed to support an empty state typically does not require the contained type to be
|
||||||
|
__DefaultConstructible__, but it typically requires it to be __CopyConstructible__ as a mechanism to
|
||||||
|
initialize the object to store:
|
||||||
|
|
||||||
|
```
|
||||||
|
struct C
|
||||||
|
{
|
||||||
|
C() : contained_(0) {}
|
||||||
|
C ( X const& v ) : contained_ ( new X(v) ) {}
|
||||||
|
~C() { delete contained_ ; }
|
||||||
|
X* contained_ ;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
There is a subtle problem with this: since the mechanism used to initialize the stored object is copy construction,
|
||||||
|
there must exist a previously constructed source object to copy from. This object is likely to be temporary and serve
|
||||||
|
no purpose besides being the source:
|
||||||
|
|
||||||
|
```
|
||||||
|
void foo()
|
||||||
|
{
|
||||||
|
// Temporary object created.
|
||||||
|
C c( X(123,"hello") ) ;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
A solution to this problem is to support direct construction of the contained
|
||||||
|
object right in the container's storage.
|
||||||
|
|
||||||
|
In this scheme, the user supplies the arguments for the `X` constructor
|
||||||
|
directly to the container:
|
||||||
|
|
||||||
|
```
|
||||||
|
struct C
|
||||||
|
{
|
||||||
|
C() : contained_(0) {}
|
||||||
|
C ( X const& v ) : contained_ ( new X(v) ) {}
|
||||||
|
C ( int a0, std::string a1 ) : contained_ ( new X(a0,a1) ) {}
|
||||||
|
~C() { delete contained_ ; }
|
||||||
|
X* contained_ ;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
void foo()
|
||||||
|
{
|
||||||
|
// Wrapped object constructed in-place
|
||||||
|
// No temporary created.
|
||||||
|
C c(123,"hello");
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Clearly, this solution does not scale well since the container must duplicate all the constructor overloads
|
||||||
|
from the contained type, or at least all those which are to be supported directly in the container.
|
||||||
|
|
||||||
|
[heading Framework]
|
||||||
|
|
||||||
|
This library proposes a framework to allow some containers to directly construct contained objects in-place without requiring
|
||||||
|
the entire set of constructor overloads from the contained type. It also allows the container to remove the __CopyConstructible__
|
||||||
|
requirement from the contained type since objects can be directly constructed in-place without need of a copy.
|
||||||
|
|
||||||
|
The only requirement on the container is that it must provide proper storage. That is, the container should be
|
||||||
|
correctly aligned and sized. Naturally, the container will typically support uninitialized storage to avoid the
|
||||||
|
in-place construction to override a fully-constructed object, as this would defeat the purpose of in-place construction.
|
||||||
|
|
||||||
|
For this purpose, the framework provides two concepts called: InPlaceFactories and TypedInPlaceFactories.
|
||||||
|
Helpers to declare these classes are declared in [@../../../include/boost/utility/in_place_factory.hpp `<boost/utility/in_place_factory.hpp>`]
|
||||||
|
and [@../../../include/boost/utility/typed_in_place_factory.hpp `<boost/utility/typed_in_place_factory.hpp>`].
|
||||||
|
|
||||||
|
Essentially, these classes hold a sequence of actual parameters and a method to construct an object in place using these parameters.
|
||||||
|
Each member of the family differs only in the number and type of the parameter list. The first family
|
||||||
|
takes the type of the object to construct directly in method provided for that
|
||||||
|
purpose, whereas the second family incorporates that type in the factory class
|
||||||
|
itself. From the container point of view, using the framework amounts to calling the
|
||||||
|
factory's method to contruct the object in place. From the user point of view, it amounts to creating
|
||||||
|
the right factory object to hold the parameters and pass it to the container.
|
||||||
|
|
||||||
|
The following simplified example shows the basic idea. A complete example follows the formal specification of the framework:
|
||||||
|
|
||||||
|
```
|
||||||
|
struct C
|
||||||
|
{
|
||||||
|
template <class InPlaceFactory>
|
||||||
|
C ( InPlaceFactory const& aFactory )
|
||||||
|
:
|
||||||
|
contained_ ( uninitialized_storage() )
|
||||||
|
{
|
||||||
|
aFactory.template apply<X>(contained_);
|
||||||
|
}
|
||||||
|
|
||||||
|
~C()
|
||||||
|
{
|
||||||
|
contained_ -> X::~X();
|
||||||
|
delete[] contained_ ;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* uninitialized_storage() { return new char[sizeof(X)] ; }
|
||||||
|
|
||||||
|
char* contained_ ;
|
||||||
|
};
|
||||||
|
|
||||||
|
void foo()
|
||||||
|
{
|
||||||
|
C c( in_place(123,"hello") ) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
[heading Specification]
|
||||||
|
|
||||||
|
The following is the first member of the family of `InPlaceFactory` classes, along with its corresponding helper template function.
|
||||||
|
The rest of the family varies only in the number and type of template and constructor parameters.
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
namespace boost {
|
||||||
|
|
||||||
|
struct __in_place_factory_base__ {};
|
||||||
|
|
||||||
|
template<class A0>
|
||||||
|
class in_place_factory : public __in_place_factory_base__
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
in_place_factory ( A0 const& a0 ) : m_a0(a0) {}
|
||||||
|
|
||||||
|
template< class T >
|
||||||
|
void apply ( void* address ) const
|
||||||
|
{
|
||||||
|
new (address) T(m_a0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
A0 const& m_a0 ;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class A0>
|
||||||
|
in_place_factory<A0> in_place ( A0 const& a0 )
|
||||||
|
{
|
||||||
|
return in_place_factory<A0>(a0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Similarly, the following is the first member of the family of `typed_in_place_factory` classes, along with its corresponding
|
||||||
|
helper template function. The rest of the family varies only in the number and type of template and constructor parameters.
|
||||||
|
|
||||||
|
```
|
||||||
|
namespace boost {
|
||||||
|
|
||||||
|
struct __typed_in_place_factory_base__ {};
|
||||||
|
|
||||||
|
template<class T, class A0>
|
||||||
|
class typed_in_place_factory : public __typed_in_place_factory_base__
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typed_in_place_factory ( A0 const& a0 ) : m_a0(a0) {}
|
||||||
|
|
||||||
|
void apply ( void* address ) const
|
||||||
|
{
|
||||||
|
new (address) T(m_a0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
A0 const& m_a0 ;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class T, class A0>
|
||||||
|
typed_in_place_factory<A0> in_place ( A0 const& a0 )
|
||||||
|
{
|
||||||
|
return typed_in_place_factory<T,A0>(a0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
As you can see, the `in_place_factory` and `typed_in_place_factory` template classes vary only in the way they specify
|
||||||
|
the target type: in the first family, the type is given as a template argument to the apply member function while in the
|
||||||
|
second it is given directly as part of the factory class.
|
||||||
|
|
||||||
|
When the container holds a unique non-polymorphic type, such as the case of [@boost:/doc/html/optional/index.html Boost.Optional],
|
||||||
|
it knows the exact dynamic-type of the contained object and can pass it to the `apply()` method of a non-typed factory.
|
||||||
|
In this case, end users can use an `in_place_factory` instance which can be constructed without the type of the object to construct.
|
||||||
|
|
||||||
|
However, if the container holds heterogeneous or polymorphic objects, such as the case of [@boost:/doc/html/variant/index.html Boost.Variant],
|
||||||
|
the dynamic-type of the object to be constructed must be known by the factory. In this case, end users must use a `typed_in_place_factory`
|
||||||
|
instead.
|
||||||
|
|
||||||
|
[heading Container-side Usage]
|
||||||
|
|
||||||
|
As shown in the introductory simplified example, the container class must contain methods that accept an instance of
|
||||||
|
these factories and pass the object's storage to the factory's apply method.
|
||||||
|
|
||||||
|
However, the type of the factory class cannot be completely specified in the container class because that would
|
||||||
|
defeat the whole purpose of the factories which is to allow the container to accept a variadic argument list
|
||||||
|
for the constructor of its contained object.
|
||||||
|
|
||||||
|
The correct function overload must be based on the only distinctive and common
|
||||||
|
characteristic of all the classes in each family: the base class.
|
||||||
|
|
||||||
|
Depending on the container class, you can use `enable_if` to generate the right overload, or use the following
|
||||||
|
dispatch technique, which is used in the [@boost:/doc/html/optional/index.html Boost.Optional] class:
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
struct C
|
||||||
|
{
|
||||||
|
C() : contained_(0) {}
|
||||||
|
C ( X const& v ) : contained_ ( new X(v) ) {}
|
||||||
|
|
||||||
|
template <class Expr>
|
||||||
|
C ( Expr const& expr )
|
||||||
|
:
|
||||||
|
contained_ ( uninitialized_storage() )
|
||||||
|
{
|
||||||
|
construct(expr,&expr);
|
||||||
|
}
|
||||||
|
|
||||||
|
~C() { delete contained_ ; }
|
||||||
|
|
||||||
|
template<class InPlaceFactory>
|
||||||
|
void construct ( InPlaceFactory const& aFactory, boost::__in_place_factory_base__* )
|
||||||
|
{
|
||||||
|
aFactory.template apply<X>(contained_);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class TypedInPlaceFactory>
|
||||||
|
void construct ( TypedInPlaceFactory const& aFactory, boost::__typed_in_place_factory_base__* )
|
||||||
|
{
|
||||||
|
aFactory.apply(contained_);
|
||||||
|
}
|
||||||
|
|
||||||
|
X* uninitialized_storage() { return static_cast<X*>(new char[sizeof(X)]) ; }
|
||||||
|
|
||||||
|
X* contained_ ;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
[heading User-side Usage]
|
||||||
|
|
||||||
|
End users pass to the container an instance of a factory object holding the actual parameters needed to construct the
|
||||||
|
contained object directly within the container. For this, the helper template function `in_place` is used.
|
||||||
|
|
||||||
|
The call `in_place(a0,a1,a2,...,an)` constructs a (non-typed) `in_place_factory` instance with the given argument list.
|
||||||
|
|
||||||
|
The call `in_place<T>(a0,a1,a2,...,an)` constructs a `typed_in_place_factory` instance with the given argument list for the
|
||||||
|
type `T`.
|
||||||
|
|
||||||
|
```
|
||||||
|
void foo()
|
||||||
|
{
|
||||||
|
C a( in_place(123, "hello") ) ; // in_place_factory passed
|
||||||
|
C b( in_place<X>(456, "world") ) ; // typed_in_place_factory passed
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
[heading Acknowledgments]
|
||||||
|
|
||||||
|
Copyright Fernando Luis Cacciola Carballal, 2004
|
||||||
|
|
||||||
|
[endsect]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
1986
doc/operators.qbk
Normal file
1986
doc/operators.qbk
Normal file
File diff suppressed because it is too large
Load Diff
407
doc/result_of.qbk
Normal file
407
doc/result_of.qbk
Normal file
@ -0,0 +1,407 @@
|
|||||||
|
[/
|
||||||
|
/ Copyright (c) 2012 Marshall Clow
|
||||||
|
/ Copyright (c) 2021, Alan Freitas
|
||||||
|
/
|
||||||
|
/ Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
/]
|
||||||
|
|
||||||
|
[/===============]
|
||||||
|
[section Result of]
|
||||||
|
[/===============]
|
||||||
|
|
||||||
|
[heading Introduction]
|
||||||
|
|
||||||
|
The class template __result_of__ helps determine the type of a
|
||||||
|
call expression. For example, given an lvalue `f` of type `F`
|
||||||
|
and lvalues `t1`,`t2`, ..., `tN` of types `T1`, `T2`, ..., `TN`,
|
||||||
|
respectively, the type __result_of__`<F(T1, T2, ..., TN)>::type` defines
|
||||||
|
the result type of the expression `f(t1, t2, ...,tN)`.
|
||||||
|
|
||||||
|
This implementation permits the type `F` to be a function pointer,
|
||||||
|
function reference, member function pointer, or class type. By default,
|
||||||
|
N may be any value between 0 and 16. To change the upper limit, define
|
||||||
|
the macro `BOOST_RESULT_OF_NUM_ARGS` to the maximum value for N. Class
|
||||||
|
template __result_of__ resides in the header
|
||||||
|
[@../../../include/boost/utility/result_of.hpp `<boost/utility/result_of.hpp>`].
|
||||||
|
|
||||||
|
If your compiler's support for __decltype__ is adequate, __result_of__
|
||||||
|
automatically uses it to deduce the type of the call expression, in
|
||||||
|
which case __result_of__`<F(T1, T2, ..., TN)>::type` names the type
|
||||||
|
__decltype__`(boost::declval<F>()(boost::declval<T1>(),
|
||||||
|
boost::declval<T2>(), ..., boost::declval<TN>()))`, as in the
|
||||||
|
following example.
|
||||||
|
|
||||||
|
```
|
||||||
|
struct functor {
|
||||||
|
template<class T>
|
||||||
|
T operator()(T x)
|
||||||
|
{
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef __boost_result_of__<functor(int)>::type type; // type is int
|
||||||
|
```
|
||||||
|
|
||||||
|
You can test whether __result_of__ is using __decltype__ by checking if
|
||||||
|
the macro `BOOST_RESULT_OF_USE_DECLTYPE` is defined after
|
||||||
|
including `result_of.hpp`. You can also force __result_of__ to use
|
||||||
|
__decltype__ by defining `BOOST_RESULT_OF_USE_DECLTYPE` prior
|
||||||
|
to including `result_of.hpp`.
|
||||||
|
|
||||||
|
If __decltype__ is not used, then automatic result type deduction of function
|
||||||
|
objects is not possible. Instead, __result_of__ uses the following protocol
|
||||||
|
to allow the programmer to specify a type. When `F` is a class type with a
|
||||||
|
member type `result_type`, `result_of<F(T1, T2, ..., TN)>::type` is
|
||||||
|
`F::result_type`. When `F` does not contain `result_type`,
|
||||||
|
`result_of<F(T1, T2, ..., TN)>::type` is
|
||||||
|
`F::result<F(T1, T2, ..., TN)>::type` when
|
||||||
|
`N > 0` or `void` when `N = 0`.
|
||||||
|
|
||||||
|
Note that it is the responsibility of the programmer to ensure that
|
||||||
|
function objects accurately advertise their result
|
||||||
|
type via this protocol, as in the following example.
|
||||||
|
|
||||||
|
```
|
||||||
|
struct functor {
|
||||||
|
template <class> struct result;
|
||||||
|
|
||||||
|
template<class F, class T>
|
||||||
|
struct result<F(T)> {
|
||||||
|
typedef T type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
T operator()(T x)
|
||||||
|
{
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef __boost_result_of__<functor(int)>::type type; // type is int
|
||||||
|
```
|
||||||
|
|
||||||
|
Since __decltype__ is a language feature standardized in C++11, if you are
|
||||||
|
writing a function object to be used with __result_of__, for maximum
|
||||||
|
portability, you might consider following the above protocol
|
||||||
|
even if your compiler has proper __decltype__ support.
|
||||||
|
|
||||||
|
If you wish to continue to use the protocol on compilers that
|
||||||
|
support __decltype__, there are two options:
|
||||||
|
|
||||||
|
* You can use __boost_tr1_result_of__, which is also defined in
|
||||||
|
[@../../../boost/utility/result_of.hpp `<boost/utility/result_of.hpp>`].
|
||||||
|
|
||||||
|
* Alternatively, you can define the macro `BOOST_RESULT_OF_USE_TR1`,
|
||||||
|
which causes __result_of__ to use the protocol described above instead
|
||||||
|
of __decltype__. If you choose to follow the protocol, take care to
|
||||||
|
ensure that the `result_type` and `result<>` members accurately
|
||||||
|
represent the return type of `operator()` given a call expression.
|
||||||
|
|
||||||
|
Additionally, __boost_result_of__ provides a third mode of operation,
|
||||||
|
which some users may find convenient. When
|
||||||
|
`BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK` is defined,
|
||||||
|
__boost_result_of__ behaves as follows. If the function object has a member
|
||||||
|
type `result_type` or member template `result<>`, then __boost_result_of__
|
||||||
|
will use the TR1 protocol.
|
||||||
|
|
||||||
|
Otherwise, __boost_result_of__ will use __decltype__. Using TR1 with
|
||||||
|
a __decltype__ fallback may workaround certain problems at the cost of portability.
|
||||||
|
For example:
|
||||||
|
|
||||||
|
* Deficient compiler: If your code requires __boost_result_of__ to work
|
||||||
|
with incomplete return types but your compiler's __decltype__ implementation
|
||||||
|
does not support incomplete return types, then you can use the TR1 protocol
|
||||||
|
as a workaround. Support for incomplete return types was added late in the
|
||||||
|
C++11 standardization process
|
||||||
|
(see [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3276.pdf N3276])
|
||||||
|
and is not implemented by some compilers.
|
||||||
|
|
||||||
|
* Deficient legacy code: If your existing TR1 function object advertises a different type than
|
||||||
|
the actual result type deduced by __decltype__, then using TR1 with a __decltype__ fallback
|
||||||
|
will allow you to work with both your existing TR1 function objects and new C++11
|
||||||
|
function object. This situation could occur if your legacy function objects
|
||||||
|
misused the TR1 protocol. See the documentation on known [link sec:result_of_tr1_diff differences]
|
||||||
|
between __boost_result_of__ and TR1.
|
||||||
|
|
||||||
|
* [#BOOST_NO_RESULT_OF] This implementation of __result_of__ requires class template
|
||||||
|
partial specialization, the ability to parse function types properly, and support
|
||||||
|
for SFINAE. If __result_of__ is not supported by your compiler, including the header
|
||||||
|
[@../../../boost/utility/result_of.hpp `<boost/utility/result_of.hpp>`] will define
|
||||||
|
the macro `BOOST_NO_RESULT_OF`.
|
||||||
|
|
||||||
|
For additional information about __result_of__, see the C++ Library
|
||||||
|
Technical Report, [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf N1836],
|
||||||
|
or, for motivation and design rationale, the __result_of__
|
||||||
|
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1454.html proposal].
|
||||||
|
|
||||||
|
[#sec:result_of_guidelines]
|
||||||
|
[heading Usage guidelines for __boost_result_of__]
|
||||||
|
|
||||||
|
The following are general suggestions about when and how to use __boost_result_of__.
|
||||||
|
|
||||||
|
# If you are targeting C++11 and are not concerned about portability to
|
||||||
|
non-compliant compilers or previous versions of the standard, then use
|
||||||
|
`__std_result_of__`. If `__std_result_of__` meets your needs, then
|
||||||
|
there's no reason to stop using it.
|
||||||
|
|
||||||
|
# If you are targeting C++11 but may port your code to legacy compilers
|
||||||
|
at some time in the future, then use __boost_result_of__ with __decltype__.
|
||||||
|
When __decltype__ is used __boost_result_of__ and `__std_result_of__` are usually
|
||||||
|
interchangeable. See the documentation on known [link sec:result_of_cxx11_diff differences]
|
||||||
|
between __boost_result_of__ and C++11 __std_result_of__.
|
||||||
|
|
||||||
|
# If compiler portability is required, use __boost_result_of__ with the TR1 protocol
|
||||||
|
|
||||||
|
Regardless of how you configure __boost_result_of__, it is
|
||||||
|
important to bear in mind that the return type of a
|
||||||
|
function may change depending on its arguments, and
|
||||||
|
additionally, the return type of a member function may
|
||||||
|
change depending on the cv-qualification of the
|
||||||
|
object. __boost_result_of__ must be passed
|
||||||
|
the appropriately cv-qualified types in order to
|
||||||
|
deduce the corresponding return type.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
```
|
||||||
|
struct functor {
|
||||||
|
int& operator()(int);
|
||||||
|
int const& operator()(int) const;
|
||||||
|
|
||||||
|
float& operator()(float&);
|
||||||
|
float const& operator()(float const&);
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef __boost_result_of__<
|
||||||
|
functor(int)
|
||||||
|
>::type type1; // type1 is int &
|
||||||
|
|
||||||
|
typedef __boost_result_of__<
|
||||||
|
const functor(int)
|
||||||
|
>::type type2; // type2 is int const &
|
||||||
|
|
||||||
|
typedef __boost_result_of__<
|
||||||
|
functor(float&)
|
||||||
|
>::type type3; // type3 is float &
|
||||||
|
|
||||||
|
typedef __boost_result_of__<
|
||||||
|
functor(float const&)
|
||||||
|
>::type type4; // type4 is float const &
|
||||||
|
```
|
||||||
|
|
||||||
|
[#sec:result_of_tr1_protocol_guidelines]
|
||||||
|
[heading Usage guidelines for the TR1 result_of protocol]
|
||||||
|
|
||||||
|
On compliant C++11 compilers, __boost_result_of__ can
|
||||||
|
use __decltype__ to deduce the type of any
|
||||||
|
call expression, including calls to function
|
||||||
|
objects. However, on pre-C++11 compilers or on
|
||||||
|
compilers without adequate decltype support,
|
||||||
|
additional scaffolding is needed from function
|
||||||
|
objects as described above. The following are
|
||||||
|
suggestions about how to use the TR1 protocol.
|
||||||
|
|
||||||
|
* When the return type does not depend on the
|
||||||
|
argument types or the cv-qualification of the
|
||||||
|
function object, simply
|
||||||
|
define `result_type`. There is no need
|
||||||
|
to use the `result` template unless the
|
||||||
|
return type varies.</li>
|
||||||
|
|
||||||
|
* Use the protocol specified type when defining
|
||||||
|
function prototypes. This can help ensure the
|
||||||
|
actual return type does not get out of sync with
|
||||||
|
the protocol specification. For example:
|
||||||
|
|
||||||
|
```
|
||||||
|
struct functor {
|
||||||
|
typedef int result_type;
|
||||||
|
result_type operator()(int);
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
* Always specify the `result` specialization near the corresponding
|
||||||
|
`operator()` overload. This can make it easier to keep the specializations
|
||||||
|
in sync with the overloads. For example:
|
||||||
|
|
||||||
|
```
|
||||||
|
struct functor {
|
||||||
|
template<class> struct result;
|
||||||
|
|
||||||
|
template<class F>
|
||||||
|
struct result<F(int)> {
|
||||||
|
typedef int& type;
|
||||||
|
};
|
||||||
|
result<functor(int)>::type operator()(int);
|
||||||
|
|
||||||
|
template<class F>
|
||||||
|
struct result<const F(int)> {
|
||||||
|
typedef int const& type;
|
||||||
|
};
|
||||||
|
result<const functor(int)>::type operator()(int) const;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
* Use type transformations to simplify
|
||||||
|
the `result` template specialization. For
|
||||||
|
example, the following uses [@../type_traits/doc/html/index.html Boost.TypeTraits]
|
||||||
|
to specialize the `result` template for
|
||||||
|
a single `operator()` that can be called on
|
||||||
|
both a const and non-const function object with
|
||||||
|
either an lvalue or rvalue argument.
|
||||||
|
|
||||||
|
```
|
||||||
|
struct functor {
|
||||||
|
template<class> struct result;
|
||||||
|
|
||||||
|
template<class F, class T>
|
||||||
|
struct result<F(T)>
|
||||||
|
: boost::remove_cv<
|
||||||
|
typename boost::remove_reference<T>::type
|
||||||
|
>
|
||||||
|
{};
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
T operator()(T const& x) const;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
[#sec:result_of_tr1_diff]
|
||||||
|
[heading Known differences between __boost_result_of__ and __boost_tr1_result_of__]
|
||||||
|
|
||||||
|
When using __decltype__, __boost_result_of__ ignores the TR1 protocol and instead deduces the
|
||||||
|
return type of function objects directly via __decltype__. In most situations, users
|
||||||
|
will not notice a difference, so long as they use the protocol correctly. The following are situations in
|
||||||
|
which the type deduced by __boost_result_of__ is known to differ depending on whether
|
||||||
|
__decltype__ or the TR1 protocol is used.
|
||||||
|
|
||||||
|
TR1 protocol misusage: When using the TR1 protocol, __boost_result_of__ cannot
|
||||||
|
detect whether the actual type of a call to a function object is the same as the
|
||||||
|
type specified by the protocol, which allows for the possibility of inadvertent
|
||||||
|
mismatches between the specified type and the actual type. When using __decltype__,
|
||||||
|
these subtle bugs may result in compilation errors. For example:
|
||||||
|
|
||||||
|
```
|
||||||
|
struct functor {
|
||||||
|
typedef short result_type;
|
||||||
|
int operator()(short);
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef BOOST_RESULT_OF_USE_DECLTYPE
|
||||||
|
|
||||||
|
BOOST_STATIC_ASSERT((
|
||||||
|
boost::is_same<__boost_result_of__<functor(short)>::type, int>::value
|
||||||
|
));
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
BOOST_STATIC_ASSERT((
|
||||||
|
boost::is_same<__boost_result_of__<functor(short)>::type, short>::value
|
||||||
|
));
|
||||||
|
|
||||||
|
#endif
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that the user can force __boost_result_of__ to use the TR1
|
||||||
|
protocol even on platforms that support __decltype__ by
|
||||||
|
defining `BOOST_RESULT_OF_USE_TR1`.
|
||||||
|
|
||||||
|
Nullary function objects: When using the TR1 protocol, __boost_result_of__
|
||||||
|
cannot always deduce the type of calls to nullary function objects, in which case the
|
||||||
|
type defaults to void. When using __decltype__, __boost_result_of__ always gives the
|
||||||
|
actual type of the call expression. For example:
|
||||||
|
|
||||||
|
```
|
||||||
|
struct functor {
|
||||||
|
template<class> struct result {
|
||||||
|
typedef int type;
|
||||||
|
};
|
||||||
|
int operator()();
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef BOOST_RESULT_OF_USE_DECLTYPE
|
||||||
|
|
||||||
|
BOOST_STATIC_ASSERT((
|
||||||
|
boost::is_same<__boost_result_of__<functor()>::type, int>::value
|
||||||
|
));
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
BOOST_STATIC_ASSERT((
|
||||||
|
boost::is_same<__boost_result_of__<functor()>::type, void>::value
|
||||||
|
));
|
||||||
|
|
||||||
|
#endif
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that there are some workarounds for the nullary function problem.
|
||||||
|
So long as the return type does not vary, `result_type` can always be used to
|
||||||
|
specify the return type regardless of arity. If the return type does vary,
|
||||||
|
then the user can specialize __boost_result_of__ itself for nullary calls.
|
||||||
|
|
||||||
|
Non-class prvalues and cv-qualification: When using the TR1 protocol, __boost_result_of__ will
|
||||||
|
report the cv-qualified type specified by `result_type` or the `result` template regardless of
|
||||||
|
the actual cv-qualification of the call expression. When using __decltype__, __boost_result_of__
|
||||||
|
will report the actual type of the call expression, which is not cv-qualified when the expression
|
||||||
|
is a non-class prvalue. For example:
|
||||||
|
|
||||||
|
```
|
||||||
|
struct functor {
|
||||||
|
template<class> struct result;
|
||||||
|
template<class F, class T> struct result<F(const T)> {
|
||||||
|
typedef const T type;
|
||||||
|
};
|
||||||
|
|
||||||
|
const short operator()(const short);
|
||||||
|
int const & operator()(int const &);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Non-prvalue call expressions work the same with or without decltype.
|
||||||
|
|
||||||
|
BOOST_STATIC_ASSERT((
|
||||||
|
boost::is_same<
|
||||||
|
__boost_result_of__<functor(int const &)>::type,
|
||||||
|
int const &
|
||||||
|
::value
|
||||||
|
));
|
||||||
|
|
||||||
|
// Non-class prvalue call expressions are not actually cv-qualified,
|
||||||
|
// but only the decltype-based result_of reports this accurately.
|
||||||
|
|
||||||
|
#ifdef BOOST_RESULT_OF_USE_DECLTYPE
|
||||||
|
|
||||||
|
BOOST_STATIC_ASSERT((
|
||||||
|
boost::is_same<
|
||||||
|
__boost_result_of__<functor(const short)>::type,
|
||||||
|
short
|
||||||
|
::value
|
||||||
|
));
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
BOOST_STATIC_ASSERT((
|
||||||
|
boost::is_same<
|
||||||
|
__boost_result_of__<functor(const short)>::type,
|
||||||
|
const short
|
||||||
|
::value
|
||||||
|
));
|
||||||
|
|
||||||
|
#endif
|
||||||
|
```
|
||||||
|
|
||||||
|
[#sec:result_of_cxx11_diff]
|
||||||
|
[heading Known differences between __boost_result_of__ and C++11 result_of]
|
||||||
|
|
||||||
|
When using __decltype__, __boost_result_of__ implements most of the C++11 __std_result_of__
|
||||||
|
specification. One known exception is that __boost_result_of__ does not implement the
|
||||||
|
requirements regarding pointers to member data.
|
||||||
|
|
||||||
|
[heading Acknowledgments]
|
||||||
|
|
||||||
|
Created by Doug Gregor. Contributions from Daniel Walker, Eric Niebler, Michel Morin and others.
|
||||||
|
|
||||||
|
[endsect]
|
||||||
|
|
||||||
|
|
@ -1,172 +0,0 @@
|
|||||||
[/
|
|
||||||
/ Copyright (c) 2012 Marshall Clow
|
|
||||||
/
|
|
||||||
/ Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
||||||
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
||||||
/]
|
|
||||||
|
|
||||||
[article String_Ref
|
|
||||||
[quickbook 1.5]
|
|
||||||
[authors [Clow, Marshall]]
|
|
||||||
[copyright 2012 Marshall Clow]
|
|
||||||
[license
|
|
||||||
Distributed under the Boost Software License, Version 1.0.
|
|
||||||
(See accompanying file LICENSE_1_0.txt or copy at
|
|
||||||
[@http://www.boost.org/LICENSE_1_0.txt])
|
|
||||||
]
|
|
||||||
]
|
|
||||||
|
|
||||||
[/===============]
|
|
||||||
[section Overview]
|
|
||||||
[/===============]
|
|
||||||
|
|
||||||
Boost.StringRef is an implementation of Jeffrey Yaskin's [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3442.html N3442:
|
|
||||||
string_ref: a non-owning reference to a string].
|
|
||||||
|
|
||||||
When you are parsing/processing strings from some external source, frequently you want to pass a piece of text to a procedure for specialized processing. The canonical way to do this is as a `std::string`, but that has certain drawbacks:
|
|
||||||
|
|
||||||
1) If you are processing a buffer of text (say a HTTP response or the contents of a file), then you have to create the string from the text you want to pass, which involves memory allocation and copying of data.
|
|
||||||
|
|
||||||
2) if a routine receives a constant `std::string` and wants to pass a portion of that string to another routine, then it must create a new string of that substring.
|
|
||||||
|
|
||||||
3) A routine receives a constant `std::string` and wants to return a portion of the string, then it must create a new string to return.
|
|
||||||
|
|
||||||
`string_ref` is designed to solve these efficiency problems. A `string_ref` is a read-only reference to a contiguous sequence of characters, and provides much of the functionality of `std::string`. A `string_ref` is cheap to create, copy and pass by value, because it does not actually own the storage that it points to.
|
|
||||||
|
|
||||||
A `string_ref` is implemented as a small struct that contains a pointer to the start of the character data and a count. A `string_ref` is cheap to create and cheap to copy.
|
|
||||||
|
|
||||||
`string_ref` acts as a container; it includes all the methods that you would expect in a container, including iteration support, `operator []`, `at` and `size`. It can be used with any of the iterator-based algorithms in the STL - as long as you don't need to change the underlying data (`sort` and `remove`, for example, will not work)
|
|
||||||
|
|
||||||
Besides generic container functionality, `string_ref` provides a subset of the interface of `std::string`. This makes it easy to replace parameters of type `const std::string &` with `boost::string_ref`. Like `std::string`, `string_ref` has a static member variable named `npos` to denote the result of failed searches, and to mean "the end".
|
|
||||||
|
|
||||||
Because a `string_ref` does not own the data that it "points to", it introduces lifetime issues into code that uses it. The programmer must ensure that the data that a `string_ref` refers to exists as long as the `string_ref` does.
|
|
||||||
|
|
||||||
[endsect]
|
|
||||||
|
|
||||||
|
|
||||||
[/===============]
|
|
||||||
[section Examples]
|
|
||||||
[/===============]
|
|
||||||
|
|
||||||
Integrating `string_ref` into your code is fairly simple. Wherever you pass a `const std::string &` or `std::string` as a parameter, that's a candidate for passing a `boost::string_ref`.
|
|
||||||
|
|
||||||
std::string extract_part ( const std::string &bar ) {
|
|
||||||
return bar.substr ( 2, 3 );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( extract_part ( "ABCDEFG" ).front() == 'C' ) { /* do something */ }
|
|
||||||
|
|
||||||
Let's figure out what happens in this (contrived) example.
|
|
||||||
|
|
||||||
First, a temporary string is created from the string literal `"ABCDEFG"`, and it is passed (by reference) to the routine `extract_part`. Then a second string is created in the call `std::string::substr` and returned to `extract_part` (this copy may be elided by RVO). Then `extract_part` returns that string back to the caller (again this copy may be elided). The first temporary string is deallocated, and `front` is called on the second string, and then it is deallocated as well.
|
|
||||||
|
|
||||||
Two `std::string`s are created, and two copy operations. That's (potentially) four memory allocations and deallocations, and the associated copying of data.
|
|
||||||
|
|
||||||
Now let's look at the same code with `string_ref`:
|
|
||||||
|
|
||||||
boost::string_ref extract_part ( boost::string_ref bar ) {
|
|
||||||
return bar.substr ( 2, 3 );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( extract_part ( "ABCDEFG" ).front() == "C" ) { /* do something */ }
|
|
||||||
|
|
||||||
No memory allocations. No copying of character data. No changes to the code other than the types. There are two `string_ref`s created, and two `string_ref`s copied, but those are cheap operations.
|
|
||||||
|
|
||||||
[endsect]
|
|
||||||
|
|
||||||
|
|
||||||
[/=================]
|
|
||||||
[section:reference Reference ]
|
|
||||||
[/=================]
|
|
||||||
|
|
||||||
The header file "string_ref.hpp" defines a template `boost::basic_string_ref`, and four specializations - for `char` / `wchar_t` / `char16_t` / `char32_t` .
|
|
||||||
|
|
||||||
`#include <boost/utility/string_ref.hpp>`
|
|
||||||
|
|
||||||
Construction and copying:
|
|
||||||
|
|
||||||
BOOST_CONSTEXPR basic_string_ref (); // Constructs an empty string_ref
|
|
||||||
BOOST_CONSTEXPR basic_string_ref(const charT* str); // Constructs from a NULL-terminated string
|
|
||||||
BOOST_CONSTEXPR basic_string_ref(const charT* str, size_type len); // Constructs from a pointer, length pair
|
|
||||||
template<typename Allocator>
|
|
||||||
basic_string_ref(const std::basic_string<charT, traits, Allocator>& str); // Constructs from a std::string
|
|
||||||
basic_string_ref (const basic_string_ref &rhs);
|
|
||||||
basic_string_ref& operator=(const basic_string_ref &rhs);
|
|
||||||
|
|
||||||
`string_ref` does not define a move constructor nor a move-assignment operator because copying a `string_ref` is just a cheap as moving one.
|
|
||||||
|
|
||||||
Basic container-like functions:
|
|
||||||
|
|
||||||
BOOST_CONSTEXPR size_type size() const ;
|
|
||||||
BOOST_CONSTEXPR size_type length() const ;
|
|
||||||
BOOST_CONSTEXPR size_type max_size() const ;
|
|
||||||
BOOST_CONSTEXPR bool empty() const ;
|
|
||||||
|
|
||||||
// All iterators are const_iterators
|
|
||||||
BOOST_CONSTEXPR const_iterator begin() const ;
|
|
||||||
BOOST_CONSTEXPR const_iterator cbegin() const ;
|
|
||||||
BOOST_CONSTEXPR const_iterator end() const ;
|
|
||||||
BOOST_CONSTEXPR const_iterator cend() const ;
|
|
||||||
const_reverse_iterator rbegin() const ;
|
|
||||||
const_reverse_iterator crbegin() const ;
|
|
||||||
const_reverse_iterator rend() const ;
|
|
||||||
const_reverse_iterator crend() const ;
|
|
||||||
|
|
||||||
Access to the individual elements (all of which are const):
|
|
||||||
|
|
||||||
BOOST_CONSTEXPR const charT& operator[](size_type pos) const ;
|
|
||||||
const charT& at(size_t pos) const ;
|
|
||||||
BOOST_CONSTEXPR const charT& front() const ;
|
|
||||||
BOOST_CONSTEXPR const charT& back() const ;
|
|
||||||
BOOST_CONSTEXPR const charT* data() const ;
|
|
||||||
|
|
||||||
Modifying the `string_ref` (but not the underlying data):
|
|
||||||
|
|
||||||
void clear();
|
|
||||||
void remove_prefix(size_type n);
|
|
||||||
void remove_suffix(size_type n);
|
|
||||||
|
|
||||||
Searching:
|
|
||||||
|
|
||||||
size_type find(basic_string_ref s) const ;
|
|
||||||
size_type find(charT c) const ;
|
|
||||||
size_type rfind(basic_string_ref s) const ;
|
|
||||||
size_type rfind(charT c) const ;
|
|
||||||
size_type find_first_of(charT c) const ;
|
|
||||||
size_type find_last_of (charT c) const ;
|
|
||||||
|
|
||||||
size_type find_first_of(basic_string_ref s) const ;
|
|
||||||
size_type find_last_of(basic_string_ref s) const ;
|
|
||||||
size_type find_first_not_of(basic_string_ref s) const ;
|
|
||||||
size_type find_first_not_of(charT c) const ;
|
|
||||||
size_type find_last_not_of(basic_string_ref s) const ;
|
|
||||||
size_type find_last_not_of(charT c) const ;
|
|
||||||
|
|
||||||
String-like operations:
|
|
||||||
|
|
||||||
BOOST_CONSTEXPR basic_string_ref substr(size_type pos, size_type n=npos) const ; // Creates a new string_ref
|
|
||||||
bool starts_with(charT c) const ;
|
|
||||||
bool starts_with(basic_string_ref x) const ;
|
|
||||||
bool ends_with(charT c) const ;
|
|
||||||
bool ends_with(basic_string_ref x) const ;
|
|
||||||
|
|
||||||
[endsect]
|
|
||||||
|
|
||||||
[/===============]
|
|
||||||
[section History]
|
|
||||||
[/===============]
|
|
||||||
|
|
||||||
[heading boost 1.71]
|
|
||||||
* Glen Fernandes updated the implementation of the stream insertion operator to
|
|
||||||
write directly to the `basic_streambuf` and refactored that functionality into
|
|
||||||
a common utility.
|
|
||||||
|
|
||||||
[heading boost 1.53]
|
|
||||||
* Introduced
|
|
||||||
|
|
||||||
|
|
||||||
[endsect]
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
199
doc/string_view.qbk
Normal file
199
doc/string_view.qbk
Normal file
@ -0,0 +1,199 @@
|
|||||||
|
[/
|
||||||
|
/ Copyright (c) 2012 Marshall Clow
|
||||||
|
/ Copyright (c) 2021, Alan Freitas
|
||||||
|
/
|
||||||
|
/ Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
/]
|
||||||
|
|
||||||
|
[/===============]
|
||||||
|
[section String View]
|
||||||
|
[/===============]
|
||||||
|
|
||||||
|
[heading Introduction]
|
||||||
|
|
||||||
|
The class __boost_string_view__ and other classes derived from __basic_string_view__ represent references to strings or substrings. When you are parsing/processing strings from some external source, frequently you want to pass a piece of text to a procedure for specialized processing. Before __std_string_view__, the canonical way to do this used to be a __std_string__, but that has certain drawbacks:
|
||||||
|
|
||||||
|
1) If you are processing a buffer of text (say a HTTP response or the contents of a file), then you have to create the string from the text you want to pass, which involves memory allocation and copying of data.
|
||||||
|
|
||||||
|
2) If a routine receives a constant __std_string__ and wants to pass a portion of that string to another routine, then it must create a new string of that substring.
|
||||||
|
|
||||||
|
3) If a routine receives a constant __std_string__ and wants to return a portion of the string, then it must create a new string to return.
|
||||||
|
|
||||||
|
__boost_string_view__ is designed to solve these efficiency problems. A __boost_string_view__ is a read-only reference to a contiguous sequence of characters, and provides much of the functionality of __std_string__. A __boost_string_view__ is cheap to create, copy and pass by value, because it does not actually own the storage that it points to.
|
||||||
|
|
||||||
|
A __boost_string_view__ is implemented as a small struct that contains a pointer to the start of the character `data` and a `count`. A __boost_string_view__ is cheap to create and cheap to copy.
|
||||||
|
|
||||||
|
__boost_string_view__ acts as a container; it includes all the methods that you would expect in a container, including iteration support, `operator[]`, `at` and `size`. It can be used with any of the iterator-based algorithms in the STL - as long as you do not need to change the underlying data. For example, __std_sort__ and __std_remove__ will not work.
|
||||||
|
|
||||||
|
Besides generic container functionality, __boost_string_view__ provides a subset of the interface of __std_string__. This makes it easy to replace parameters of type `const __std_string__ &` with __boost_string_view__. Like __std_string__, __boost_string_view__ has a static member variable named `npos` to denote the result of failed searches, and to mean "the end".
|
||||||
|
|
||||||
|
[caution Because a __boost_string_view__ does not own the data that it refers to, it introduces lifetime issues into code that uses it. The programmer must ensure that the data that a __string_view__ refers to exists as long as the __string_view__ does.]
|
||||||
|
|
||||||
|
[note
|
||||||
|
|
||||||
|
Boost.Utility also includes the class __string_ref__:
|
||||||
|
|
||||||
|
- __string_ref__ is the initial implementation of Jeffrey Yaskin's [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3442.html N3442:
|
||||||
|
string_ref: a non-owning reference to a string].
|
||||||
|
|
||||||
|
- __string_view__ is an updated implementation to reflect the Library Fundamentals TS [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4480.html N4480: \[string.view\]]
|
||||||
|
|
||||||
|
Please prefer __string_view__ / __basic_string_view__ over __string_ref__ / __basic_string_ref__:
|
||||||
|
|
||||||
|
- The __basic_string_view__ class better matches __std_basic_string_view__
|
||||||
|
|
||||||
|
- __basic_string_view__ has WAY more constexpr support.
|
||||||
|
|
||||||
|
- Code that uses __basic_string_ref__ should continue to work.
|
||||||
|
|
||||||
|
- No much code depends on __basic_string_ref__ anymore
|
||||||
|
|
||||||
|
|
||||||
|
]
|
||||||
|
|
||||||
|
[/===============]
|
||||||
|
[heading Examples]
|
||||||
|
[/===============]
|
||||||
|
|
||||||
|
Integrating __string_view__ into your code is fairly simple. Wherever you pass a `const __std_string__ &` or __std_string__ as a parameter, that's a candidate for passing a __boost_string_view__.
|
||||||
|
|
||||||
|
```
|
||||||
|
__std_string__ extract_part ( const __std_string__ &bar ) {
|
||||||
|
return bar.substr ( 2, 3 );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( extract_part ( "ABCDEFG" ).front() == 'C' ) { /* do something */ }
|
||||||
|
```
|
||||||
|
|
||||||
|
Let's figure out what happens in this contrived example.
|
||||||
|
|
||||||
|
* First, a temporary string is created from the string literal `"ABCDEFG"`, and it is passed (by reference) to the routine `extract_part`.
|
||||||
|
* Then a second string is created in the call `__std_string__::substr` and returned to `extract_part` (this copy may be elided by RVO).
|
||||||
|
* Then `extract_part` returns that string back to the caller (again this copy may be elided).
|
||||||
|
* The first temporary string is deallocated, and `front` is called on the second string, and then it is deallocated as well.
|
||||||
|
|
||||||
|
Two __std_string__ s are created, and two copy operations. That is potentially four memory allocations and deallocations, and the associated copying of data.
|
||||||
|
|
||||||
|
Now let's look at the same code with __string_view__:
|
||||||
|
|
||||||
|
```
|
||||||
|
__boost_string_view__ extract_part ( __boost_string_view__ bar ) {
|
||||||
|
return bar.substr ( 2, 3 );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( extract_part ( "ABCDEFG" ).front() == "C" ) { /* do something */ }
|
||||||
|
```
|
||||||
|
|
||||||
|
No memory allocations. No copying of character data. No changes to the code other than the types. There are two __string_view__ s created, and two __string_view__ s copied, but those are cheap operations.
|
||||||
|
|
||||||
|
[/=================]
|
||||||
|
[heading:reference Synopsis ]
|
||||||
|
[/=================]
|
||||||
|
|
||||||
|
The header file [@../../../include/boost/utility/string_view.hpp `<boost/utility/string_view.hpp>`] defines a template __boost_basic_string_view__, and four specializations __string_view__, __wstring_view__, __u16string_view__, __u32string_view__ - for `char` / `wchar_t` / `char16_t` / `char32_t`.
|
||||||
|
|
||||||
|
`#include <boost/utility/string_view.hpp>`
|
||||||
|
|
||||||
|
Construction and copying:
|
||||||
|
|
||||||
|
```
|
||||||
|
constexpr basic_string_view (); // Constructs an empty string_view
|
||||||
|
constexpr basic_string_view(const charT* str); // Constructs from a NULL-terminated string
|
||||||
|
constexpr basic_string_view(const charT* str, size_type len); // Constructs from a pointer, length pair
|
||||||
|
template<typename Allocator>
|
||||||
|
basic_string_view(const __std_basic_string__<charT, traits, Allocator>& str); // Constructs from a std::string
|
||||||
|
basic_string_view (const basic_string_view &rhs);
|
||||||
|
basic_string_view& operator=(const basic_string_view &rhs);
|
||||||
|
```
|
||||||
|
|
||||||
|
__string_view__ does not define a move constructor nor a move-assignment operator because copying a __string_view__ is just a cheap as moving one.
|
||||||
|
|
||||||
|
Basic container-like functions:
|
||||||
|
|
||||||
|
```
|
||||||
|
constexpr size_type size() const ;
|
||||||
|
constexpr size_type length() const ;
|
||||||
|
constexpr size_type max_size() const ;
|
||||||
|
constexpr bool empty() const ;
|
||||||
|
|
||||||
|
// All iterators are const_iterators
|
||||||
|
constexpr const_iterator begin() const ;
|
||||||
|
constexpr const_iterator cbegin() const ;
|
||||||
|
constexpr const_iterator end() const ;
|
||||||
|
constexpr const_iterator cend() const ;
|
||||||
|
const_reverse_iterator rbegin() const ;
|
||||||
|
const_reverse_iterator crbegin() const ;
|
||||||
|
const_reverse_iterator rend() const ;
|
||||||
|
const_reverse_iterator crend() const ;
|
||||||
|
```
|
||||||
|
|
||||||
|
Access to the individual elements (all of which are const):
|
||||||
|
|
||||||
|
```
|
||||||
|
constexpr const charT& operator[](size_type pos) const ;
|
||||||
|
const charT& at(size_t pos) const ;
|
||||||
|
constexpr const charT& front() const ;
|
||||||
|
constexpr const charT& back() const ;
|
||||||
|
constexpr const charT* data() const ;
|
||||||
|
```
|
||||||
|
|
||||||
|
Modifying the __string_view__ (but not the underlying data):
|
||||||
|
|
||||||
|
```
|
||||||
|
void clear();
|
||||||
|
void remove_prefix(size_type n);
|
||||||
|
void remove_suffix(size_type n);
|
||||||
|
```
|
||||||
|
|
||||||
|
Searching:
|
||||||
|
|
||||||
|
```
|
||||||
|
size_type find(basic_string_view s) const ;
|
||||||
|
size_type find(charT c) const ;
|
||||||
|
size_type rfind(basic_string_view s) const ;
|
||||||
|
size_type rfind(charT c) const ;
|
||||||
|
size_type find_first_of(charT c) const ;
|
||||||
|
size_type find_last_of (charT c) const ;
|
||||||
|
|
||||||
|
size_type find_first_of(basic_string_view s) const ;
|
||||||
|
size_type find_last_of(basic_string_view s) const ;
|
||||||
|
size_type find_first_not_of(basic_string_view s) const ;
|
||||||
|
size_type find_first_not_of(charT c) const ;
|
||||||
|
size_type find_last_not_of(basic_string_view s) const ;
|
||||||
|
size_type find_last_not_of(charT c) const ;
|
||||||
|
```
|
||||||
|
|
||||||
|
String-like operations:
|
||||||
|
|
||||||
|
```
|
||||||
|
constexpr basic_string_view substr(size_type pos, size_type n=npos) const ; // Creates a new string_view
|
||||||
|
bool starts_with(charT c) const ;
|
||||||
|
bool starts_with(basic_string_view x) const ;
|
||||||
|
bool ends_with(charT c) const ;
|
||||||
|
bool ends_with(basic_string_view x) const ;
|
||||||
|
```
|
||||||
|
|
||||||
|
[/===============]
|
||||||
|
[h1 History]
|
||||||
|
[/===============]
|
||||||
|
|
||||||
|
[h5 boost 1.71]
|
||||||
|
* Glen Fernandes updated the implementation of the stream insertion operator to
|
||||||
|
write directly to the `basic_streambuf` and refactored that functionality into
|
||||||
|
a common utility.
|
||||||
|
|
||||||
|
[h5 boost 1.53]
|
||||||
|
* Introduced
|
||||||
|
|
||||||
|
[heading Acknowledgments]
|
||||||
|
|
||||||
|
Author: Clow, Marshall
|
||||||
|
|
||||||
|
Copyright 2012 Marshall Clow
|
||||||
|
|
||||||
|
[endsect]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
564
doc/value_init.qbk
Normal file
564
doc/value_init.qbk
Normal file
@ -0,0 +1,564 @@
|
|||||||
|
[/
|
||||||
|
/ Copyright (c) 2012 Marshall Clow
|
||||||
|
/ Copyright (c) 2021, Alan Freitas
|
||||||
|
/
|
||||||
|
/ Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
/]
|
||||||
|
|
||||||
|
[/===============]
|
||||||
|
[#sec:value_init]
|
||||||
|
[section Value Init]
|
||||||
|
[/===============]
|
||||||
|
|
||||||
|
[heading Introduction]
|
||||||
|
|
||||||
|
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. The template __value_initialized__ provides
|
||||||
|
a solution with consistent syntax for value initialization of scalar,
|
||||||
|
union and class types. Moreover, __value_initialized__ offers a workaround to various
|
||||||
|
compiler issues regarding value-initialization.
|
||||||
|
|
||||||
|
Furthermore, a `const` object __initialized_value__ is provided,
|
||||||
|
to avoid repeating the type name when retrieving the value from a
|
||||||
|
`__value_initialized__<T>` object.
|
||||||
|
|
||||||
|
There are various ways to initialize a variable, in C++. The following
|
||||||
|
declarations all ['may] have a local variable initialized to its default
|
||||||
|
value:
|
||||||
|
|
||||||
|
```
|
||||||
|
T1 var1;
|
||||||
|
T2 var2 = 0;
|
||||||
|
T3 var3 = {};
|
||||||
|
T4 var4 = T4();
|
||||||
|
```
|
||||||
|
|
||||||
|
Unfortunately, whether or not any of those declarations correctly
|
||||||
|
initialize the variable very much depends on its type. The first
|
||||||
|
declaration is valid for any __DefaultConstructible__ type by definition.
|
||||||
|
|
||||||
|
However, it does not always do an initialization. It correctly initializes
|
||||||
|
the variable when it's an instance of a class, and the author of the class
|
||||||
|
has provided a proper default constructor. On the other hand, the value of
|
||||||
|
`var1` is ['indeterminate] when its type is an arithmetic type, like `int`,
|
||||||
|
`float`, or `char`.
|
||||||
|
|
||||||
|
An arithmetic variable is of course initialized properly by the second declaration,
|
||||||
|
`T2 var2 = 0`. But this initialization form will not usually work for a
|
||||||
|
class type, unless the class was especially written to support being
|
||||||
|
initialized that way.
|
||||||
|
|
||||||
|
The third form, `T3 var3 = {}`, initializes an aggregate, typically a "C-style"
|
||||||
|
`struct` or a "C-style" array. However, at the time this library was developed,
|
||||||
|
the syntax did not allow for a class that has an explicitly declared constructor.
|
||||||
|
|
||||||
|
The fourth form is the most generic form of them, as it can be used to initialize
|
||||||
|
arithmetic types, class types, aggregates, pointers, and other types.
|
||||||
|
The declaration, `T4 var4 = T4()`, should be read as follows: First a temporary
|
||||||
|
object is created, by `T4()`. This object is [link sec:valueinit value-initialized].
|
||||||
|
Next the temporary object is copied to the named variable, `var4`. Afterwards,
|
||||||
|
the temporary is destroyed. While the copying and the destruction are likely to
|
||||||
|
be optimized away, C++ still requires the type `T4` to be __CopyConstructible__.
|
||||||
|
So `T4` needs to be ['both] __DefaultConstructible__ ['and] __CopyConstructible__.
|
||||||
|
|
||||||
|
A class may not be CopyConstructible, for example because it may have a
|
||||||
|
private and undefined copy constructor, or because it may be derived from
|
||||||
|
`boost::noncopyable`. Scott Meyers \[[link sec:references 2]\] explains why a
|
||||||
|
class would be defined like that.
|
||||||
|
|
||||||
|
There is another, less obvious disadvantage to the fourth form, `T4 var4 = T4()`:
|
||||||
|
It suffers from various [link sec:compiler_issues compiler issues], causing
|
||||||
|
a variable to be left uninitialized in some compiler specific cases.
|
||||||
|
|
||||||
|
The template __value_initialized__ offers a generic way to initialize
|
||||||
|
an object, like `T4 var4 = T4()`, but without requiring its type
|
||||||
|
to be __CopyConstructible__. And it offers a workaround to those compiler issues
|
||||||
|
regarding value-initialization as well. It allows getting an initialized
|
||||||
|
variable of any type; it ['only] requires the type to be __DefaultConstructible__.
|
||||||
|
A properly ['value-initialized] object of type `T` is constructed by the following
|
||||||
|
declaration:
|
||||||
|
|
||||||
|
```
|
||||||
|
value_initialized<T> var;
|
||||||
|
```
|
||||||
|
|
||||||
|
The template __initialized__ offers both value-initialization and direct-initialization.
|
||||||
|
It is especially useful as a data member type, allowing the very same object
|
||||||
|
to be either direct-initialized or value-initialized.
|
||||||
|
|
||||||
|
The `const` object __initialized_value__ allows value-initializing a variable as follows:
|
||||||
|
|
||||||
|
```
|
||||||
|
T var = initialized_value;
|
||||||
|
```
|
||||||
|
|
||||||
|
This form of initialization is semantically equivalent to `T4 var4 = T4()`,
|
||||||
|
but robust against the aforementioned compiler issues.
|
||||||
|
|
||||||
|
[#sec:details]
|
||||||
|
[heading Details]
|
||||||
|
|
||||||
|
The C++ standard \[[link sec:references 3]\] contains the definitions
|
||||||
|
of `zero-initialization` and `default-initialization`. Informally, zero-initialization
|
||||||
|
means that the object is given the initial value `0` converted to the type and
|
||||||
|
default-initialization means that POD \[[link sec:references 4]\] types are zero-initialized,
|
||||||
|
while non-POD class types are initialized with their corresponding default constructors.
|
||||||
|
|
||||||
|
A ['declaration] can contain an ['initializer], which specifies the
|
||||||
|
object's initial value. The initializer can be just '()', which states that
|
||||||
|
the object shall be value-initialized (but see below). However, if a ['declaration]
|
||||||
|
has no ['initializer] and it is of a non-`const`, non-`static` POD type, the
|
||||||
|
initial value is indeterminate: (see §8.5, [dcl.init], for the
|
||||||
|
accurate definitions).
|
||||||
|
|
||||||
|
```
|
||||||
|
int x; // no initializer. x value is indeterminate.
|
||||||
|
__std_string__ s; // no initializer, s is default-constructed.
|
||||||
|
|
||||||
|
int y = int();
|
||||||
|
// y is initialized using copy-initialization
|
||||||
|
// but the temporary uses an empty set of parentheses as the initializer,
|
||||||
|
// so it is default-constructed.
|
||||||
|
// A default constructed POD type is zero-initialized,
|
||||||
|
// therefore, y == 0.
|
||||||
|
|
||||||
|
void foo ( __std_string__ ) ;
|
||||||
|
foo ( __std_string__() ) ;
|
||||||
|
// the temporary string is default constructed
|
||||||
|
// as indicated by the initializer ()
|
||||||
|
```
|
||||||
|
|
||||||
|
[#sec:valueinit]
|
||||||
|
[h5 value-initialization]
|
||||||
|
|
||||||
|
The first [@http://www.open-std.org/JTC1/SC22/WG21/docs/cwg_defects.html Technical
|
||||||
|
Corrigendum for the C++ Standard] (TC1), whose draft was released to the public in
|
||||||
|
November 2001, introduced [@http://www.open-std.org/JTC1/SC22/WG21/docs/cwg_defects.html#178 Core
|
||||||
|
Issue 178], among many other issues.
|
||||||
|
|
||||||
|
That issue introduced the new concept of `value-initialization`, and 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 will not 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).
|
||||||
|
|
||||||
|
In order to specify value-initialization of an object we need to use the
|
||||||
|
empty-set initializer: `()`.
|
||||||
|
|
||||||
|
As before, a declaration with no initializer specifies default-initialization,
|
||||||
|
and a declaration with a non-empty initializer specifies copy (`=xxx`) or
|
||||||
|
direct (`xxx`) initialization.
|
||||||
|
|
||||||
|
```
|
||||||
|
template<class T> void eat(T);
|
||||||
|
|
||||||
|
int x ; // indeterminate initial value.
|
||||||
|
|
||||||
|
__std_string__ s; // default-initialized.
|
||||||
|
|
||||||
|
eat ( int() ) ; // value-initialized
|
||||||
|
|
||||||
|
eat ( __std_string__() ) ; // value-initialized
|
||||||
|
```
|
||||||
|
|
||||||
|
[#sec:valueinitsyn]
|
||||||
|
[h5 value-initialization syntax]
|
||||||
|
|
||||||
|
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:
|
||||||
|
|
||||||
|
```
|
||||||
|
int x() ; // declares function int(*)()
|
||||||
|
```
|
||||||
|
|
||||||
|
Thus, the empty `()` must be put in some other initialization context.
|
||||||
|
|
||||||
|
One alternative is to use copy-initialization syntax:
|
||||||
|
|
||||||
|
```
|
||||||
|
int x = int();
|
||||||
|
```
|
||||||
|
|
||||||
|
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 does not 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.
|
||||||
|
|
||||||
|
One possible generic solution is to use value-initialization of a non static
|
||||||
|
data member:
|
||||||
|
|
||||||
|
```
|
||||||
|
template<class T>
|
||||||
|
struct W
|
||||||
|
{
|
||||||
|
// value-initialization of 'data' here.
|
||||||
|
W() : data() {}
|
||||||
|
|
||||||
|
T data;
|
||||||
|
};
|
||||||
|
|
||||||
|
W<int> w;
|
||||||
|
// w.data is value-initialized for any type.
|
||||||
|
```
|
||||||
|
|
||||||
|
This is the solution as it was supplied by earlier versions of the
|
||||||
|
`__value_initialized__<T>` template class. Unfortunately this approach
|
||||||
|
suffered from various compiler issues.
|
||||||
|
|
||||||
|
[#sec:compiler_issues]
|
||||||
|
[h5 Compiler issues]
|
||||||
|
|
||||||
|
Various compilers have not yet fully implemented value-initialization.
|
||||||
|
So when an object should be ['value-initialized] according to the C++ Standard,
|
||||||
|
it ['may] in practice still be left uninitialized, because of those
|
||||||
|
compiler issues. It is hard to make a general statement on what those issues
|
||||||
|
are like, because they depend on the compiler you are using, its version number,
|
||||||
|
and the type of object you would like to have value-initialized.
|
||||||
|
|
||||||
|
All compilers we have tested so far support value-initialization for arithmetic types properly.
|
||||||
|
However, various compilers may leave some types of ['aggregates] uninitialized, when they
|
||||||
|
should be value-initialized. Value-initialization of objects of a pointer-to-member type may also
|
||||||
|
go wrong on various compilers.
|
||||||
|
|
||||||
|
At the moment of writing, May 2010, the following reported issues regarding
|
||||||
|
value-initialization are still there in current compiler releases:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
* [@https://connect.microsoft.com/VisualStudio/feedback/details/100744 Microsoft Visual Studio Feedback ID 100744, Value-initialization in new-expression]: Reported by Pavel Kuznetsov (MetaCommunications Engineering), 2005.
|
||||||
|
* [@http://connect.microsoft.com/VisualStudio/feedback/details/484295 Microsoft Visual Studio Feedback ID 484295, VC++ does not value-initialize members of derived classes without user-declared constructor] Reported by Sylvester Hesp, 2009.
|
||||||
|
* [@https://connect.microsoft.com/VisualStudio/feedback/details/499606 Microsoft Visual Studio Feedback ID 499606, Presence of copy constructor breaks member class initialization] Reported by Alex Vakulenko, 2009
|
||||||
|
* [@http://qc.embarcadero.com/wc/qcmain.aspx?d=83751 Embarcadero/C++Builder Report 83751, Value-initialization: arrays should have each element value-initialized] Reported by Niels Dekker (LKEB), 2010.
|
||||||
|
* [@http://qc.embarcadero.com/wc/qcmain.aspx?d=83851 Embarcadero/C++Builder Report 83851, Value-initialized temporary triggers internal backend error C1798] Reported by Niels Dekker, 2010.
|
||||||
|
* [@http://qc.embarcadero.com/wc/qcmain.aspx?d=84279 Embarcadero/C++Builder Report 84279, Internal compiler error (F1004), value-initializing member function pointer by "new T()"] Reported by Niels Dekker, 2010
|
||||||
|
* Sun CR 6947016, Sun 5.10 may fail to value-initialize an object of a non-POD aggregate. Reported to Steve Clamage by Niels Dekker, 2010.
|
||||||
|
* IBM's XL V10.1 and V11.1 may fail to value-initialize a temporary of a non-POD aggregate. Reported to Michael Wong by Niels Dekker, 2010.
|
||||||
|
* Intel support issue 589832, Attempt to value-initialize pointer-to-member triggers internal error on Intel 11.1. Reported by John Maddock, 2010.
|
||||||
|
|
||||||
|
Note that all known GCC issues regarding value-initialization are fixed with GCC version 4.4, including
|
||||||
|
[@http://gcc.gnu.org/bugzilla/show_bug.cgi?id=30111 GCC Bug 30111]. Clang also has completely implemented
|
||||||
|
value-initialization, as far as we know, now that [@http://llvm.org/bugs/show_bug.cgi?id=7139 Clang Bug 7139]
|
||||||
|
is fixed.
|
||||||
|
|
||||||
|
New versions of __value_initialized__ (Boost release version 1.35 or higher) offer a workaround to these
|
||||||
|
issues: __value_initialized__ may now clear its internal data, prior to constructing the object that it
|
||||||
|
contains. It will do so for those compilers that need to have such a workaround, based on the
|
||||||
|
[@boost:/doc/html/config/doc/html/boost_config/boost_macro_reference.html#boost_config.boost_macro_reference.macros_that_describe_defects
|
||||||
|
compiler defect macro] `BOOST_NO_COMPLETE_VALUE_INITIALIZATION`.
|
||||||
|
|
||||||
|
[#sec:types]
|
||||||
|
[heading Types and objects]
|
||||||
|
|
||||||
|
[#sec:val_init]
|
||||||
|
[heading `template class value_initialized<T>`]
|
||||||
|
|
||||||
|
```
|
||||||
|
namespace boost {
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
class __value_initialized__
|
||||||
|
{
|
||||||
|
|
||||||
|
public :
|
||||||
|
|
||||||
|
__value_initialized__() : x() {}
|
||||||
|
|
||||||
|
operator T const &() const { return x ; }
|
||||||
|
|
||||||
|
operator T&() { return x ; }
|
||||||
|
|
||||||
|
T const &data() const { return x ; }
|
||||||
|
|
||||||
|
T& data() { return x ; }
|
||||||
|
|
||||||
|
void swap( __value_initialized__& );
|
||||||
|
|
||||||
|
private :
|
||||||
|
|
||||||
|
[unspecified] 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();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
void swap ( __value_initialized__<T>& lhs, __value_initialized__<T>& rhs )
|
||||||
|
{
|
||||||
|
lhs.swap(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace boost
|
||||||
|
```
|
||||||
|
|
||||||
|
An object of this template class is a `T`-wrapper convertible to `'T&'` whose
|
||||||
|
wrapped object (data member of type `T`) is [link sec:valueinit value-initialized] upon default-initialization
|
||||||
|
of this wrapper class:
|
||||||
|
|
||||||
|
```
|
||||||
|
int zero = 0;
|
||||||
|
__value_initialized__<int> x;
|
||||||
|
assert( x == zero ) ;
|
||||||
|
|
||||||
|
__std_string__ def;
|
||||||
|
__value_initialized__< __std_string__ > y;
|
||||||
|
assert( y == def ) ;
|
||||||
|
```
|
||||||
|
|
||||||
|
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 [link sec:valueinitsyn value-initialization syntax]).
|
||||||
|
|
||||||
|
The wrapped object can be accessed either through the conversion operator
|
||||||
|
`T&`, the member function `data()`, or the non-member function `get()`:
|
||||||
|
|
||||||
|
```
|
||||||
|
void watch(int);
|
||||||
|
|
||||||
|
__value_initialized__<int> x;
|
||||||
|
|
||||||
|
watch(x) ; // operator T& used.
|
||||||
|
watch(x.data());
|
||||||
|
watch( get(x) ) // function get() used
|
||||||
|
```
|
||||||
|
|
||||||
|
Both `const` and non-`const` objects can be wrapped. Mutable objects can be
|
||||||
|
modified directly from within the wrapper but constant objects cannot:
|
||||||
|
|
||||||
|
When `T` is a __Swappable__ type, `__value_initialized__<T>`
|
||||||
|
is swappable as well, by calling its `swap` member function
|
||||||
|
as well as by calling `boost::swap`.
|
||||||
|
|
||||||
|
```
|
||||||
|
__value_initialized__<int> x;
|
||||||
|
static_cast<int&>(x) = 1 ; // OK
|
||||||
|
get(x) = 1 ; // OK
|
||||||
|
|
||||||
|
__value_initialized__<int const> y ;
|
||||||
|
static_cast<int&>(y) = 1 ; // ERROR: cannot cast to int&
|
||||||
|
static_cast<int const&>(y) = 1 ; // ERROR: cannot modify a const value
|
||||||
|
get(y) = 1 ; // ERROR: cannot modify a const value
|
||||||
|
```
|
||||||
|
|
||||||
|
[warning
|
||||||
|
|
||||||
|
The __value_initialized__ implementation of Boost version 1.40.0 and older
|
||||||
|
allowed ['non-const] access to the wrapped object, from a constant wrapper,
|
||||||
|
both by its conversion operator and its `data()` member function.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
```
|
||||||
|
__value_initialized__<int> const x_c;
|
||||||
|
int& xr = x_c ; // OK, conversion to int& available even though x_c is itself const.
|
||||||
|
xr = 2 ;
|
||||||
|
```
|
||||||
|
|
||||||
|
The reason for this obscure behavior was that some compilers did not accept the following valid code:
|
||||||
|
|
||||||
|
```
|
||||||
|
struct X
|
||||||
|
{
|
||||||
|
operator int&() ;
|
||||||
|
operator int const&() const ;
|
||||||
|
};
|
||||||
|
X x ;
|
||||||
|
(x == 1) ; // ERROR HERE!
|
||||||
|
```
|
||||||
|
|
||||||
|
The current version of __value_initialized__ no longer has this obscure behavior.
|
||||||
|
As compilers nowadays widely support overloading the conversion operator by having a `const`
|
||||||
|
and a `non-const` version, we have decided to fix the issue accordingly. So the current version
|
||||||
|
supports the idea of logical constness.
|
||||||
|
|
||||||
|
]
|
||||||
|
|
||||||
|
[h5 Recommended practice: The non-member get() idiom]
|
||||||
|
|
||||||
|
The obscure behavior of being able to modify a non-`const`
|
||||||
|
wrapped object from within a constant wrapper (as was supported by previous
|
||||||
|
versions of __value_initialized__) can be avoided if access to the wrapped object
|
||||||
|
is always performed with the `get()` idiom:
|
||||||
|
|
||||||
|
```
|
||||||
|
value_initialized<int> x;
|
||||||
|
get(x) = 1; // OK
|
||||||
|
value_initialized<int const> cx;
|
||||||
|
get(x) = 1; // ERROR: Cannot modify a const object
|
||||||
|
|
||||||
|
value_initialized<int> const x_c;
|
||||||
|
get(x_c) = 1; // ERROR: Cannot modify a const object
|
||||||
|
|
||||||
|
value_initialized<int const> const cx_c;
|
||||||
|
get(cx_c) = 1; // ERROR: Cannot modify a const object
|
||||||
|
```
|
||||||
|
|
||||||
|
[#sec:initialized]
|
||||||
|
[heading `template class initialized<T>`]
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
namespace boost {
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
class __initialized__
|
||||||
|
{
|
||||||
|
|
||||||
|
public :
|
||||||
|
|
||||||
|
__initialized__() : x() {}
|
||||||
|
|
||||||
|
explicit __initialized__(T const & arg) : x(arg) {}
|
||||||
|
|
||||||
|
operator T const &() const;
|
||||||
|
|
||||||
|
operator T&();
|
||||||
|
|
||||||
|
T const &data() const;
|
||||||
|
|
||||||
|
T& data();
|
||||||
|
|
||||||
|
void swap( __initialized__& );
|
||||||
|
|
||||||
|
private :
|
||||||
|
|
||||||
|
[unspecified] x ;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
T const& get ( __initialized__<T> const& x );
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
T& get ( __initialized__<T>& x );
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
void swap ( __initialized__<T>& lhs, __initialized__<T>& rhs );
|
||||||
|
|
||||||
|
} // namespace boost
|
||||||
|
```
|
||||||
|
|
||||||
|
The template class `boost::__initialized__<T>` supports both value-initialization
|
||||||
|
and direct-initialization, so its interface is a superset of the interface
|
||||||
|
of `__value_initialized__<T>`: Its default-constructor value-initializes the
|
||||||
|
wrapped object just like the default-constructor of `__value_initialized__<T>`,
|
||||||
|
but `boost::__initialized__<T>` also offers an extra `explicit`
|
||||||
|
constructor, which direct-initializes the wrapped object by the specified value.
|
||||||
|
|
||||||
|
`__initialized__<T>` is especially useful when the wrapped
|
||||||
|
object must be either value-initialized or direct-initialized, depending on
|
||||||
|
runtime conditions. For example, `__initialized__<T>` could
|
||||||
|
hold the value of a data member that may be value-initialized by some
|
||||||
|
constructors, and direct-initialized by others.
|
||||||
|
|
||||||
|
On the other hand, if it is known beforehand that the
|
||||||
|
object must ['always] be value-initialized, `__value_initialized__<T>`
|
||||||
|
may be preferable. And if the object must always be
|
||||||
|
direct-initialized, none of the two wrappers really needs to be used.
|
||||||
|
|
||||||
|
[#sec:initialized_value]
|
||||||
|
[heading `initialized_value`]
|
||||||
|
|
||||||
|
```
|
||||||
|
namespace boost {
|
||||||
|
class __initialized_value_t__
|
||||||
|
{
|
||||||
|
public :
|
||||||
|
template <class T> operator T() const ;
|
||||||
|
};
|
||||||
|
|
||||||
|
__initialized_value_t__ const initialized_value = {} ;
|
||||||
|
|
||||||
|
} // namespace boost
|
||||||
|
```
|
||||||
|
|
||||||
|
__initialized_value__ provides a convenient way to get
|
||||||
|
an initialized value: its conversion operator provides an appropriate
|
||||||
|
['value-initialized] object for any __CopyConstructible__ type.
|
||||||
|
|
||||||
|
Suppose you need to have an initialized variable of type `T`.
|
||||||
|
You could do it as follows:
|
||||||
|
|
||||||
|
```
|
||||||
|
T var = T();
|
||||||
|
```
|
||||||
|
|
||||||
|
But as mentioned before, this form suffers from various compiler issues.
|
||||||
|
The template __value_initialized__ offers a workaround:
|
||||||
|
|
||||||
|
```
|
||||||
|
T var = get( __value_initialized__<T>() );
|
||||||
|
```
|
||||||
|
|
||||||
|
Unfortunately both forms repeat the type name, which
|
||||||
|
is rather short now (`T`), but could of course be
|
||||||
|
more like `Namespace::Template<Arg>::Type`.
|
||||||
|
|
||||||
|
Instead, one could use __initialized_value__ as follows:
|
||||||
|
|
||||||
|
```
|
||||||
|
T var = __initialized_value__;
|
||||||
|
```
|
||||||
|
|
||||||
|
[#sec:references]
|
||||||
|
[h5 References]
|
||||||
|
|
||||||
|
# Bjarne Stroustrup, Gabriel Dos Reis, and J. Stephen Adamczyk wrote various papers,
|
||||||
|
proposing to extend the support for brace-enclosed ['initializer lists]
|
||||||
|
in C++. This [@https://en.cppreference.com/w/cpp/language/list_initialization feature] has
|
||||||
|
now been available since C++11. This would allow a variable `var` of any __DefaultConstructible__ type
|
||||||
|
`T` to be ['value-initialized] by doing `T var = {}`. The papers are listed at Bjarne's web page,
|
||||||
|
[@http://www.research.att.com/~bs/WG21.html My C++ Standards committee papers].
|
||||||
|
|
||||||
|
# Scott Meyers, Effective C++, Third Edition, item 6, ['Explicitly disallow the use of
|
||||||
|
compiler-generated functions you do not want], [@http://www.aristeia.com/books.html Scott Meyers: Books and CDs]
|
||||||
|
|
||||||
|
# The C++ Standard, Second edition (2003), ISO/IEC 14882:2003
|
||||||
|
|
||||||
|
# POD stands for "Plain Old Data"
|
||||||
|
|
||||||
|
[#sec:acknowledgements]
|
||||||
|
[h5 Acknowledgements]
|
||||||
|
|
||||||
|
__value_initialized__ was developed by Fernando Cacciola, with help and suggestions
|
||||||
|
from David Abrahams and Darin Adler.
|
||||||
|
|
||||||
|
Special thanks to Bjorn Karlsson who carefully edited and completed this documentation.
|
||||||
|
|
||||||
|
__value_initialized__ was reimplemented by Fernando Cacciola and Niels Dekker
|
||||||
|
for Boost release version 1.35 (2008), offering a workaround to various compiler issues.
|
||||||
|
|
||||||
|
`boost::__initialized__` was very much inspired by feedback from Edward Diener and Jeffrey Hellrung.
|
||||||
|
|
||||||
|
__initialized_value__ was written by Niels Dekker, and added to Boost release version 1.36 (2008).
|
||||||
|
|
||||||
|
Developed by [@mailto:fernando_cacciola@hotmail.com Fernando Cacciola]. The latest version of
|
||||||
|
this file can be found at [@http://www.boost.org www.boost.org].
|
||||||
|
|
||||||
|
[endsect]
|
@ -1,15 +1,19 @@
|
|||||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta http-equiv=refresh content="0; URL=../core/doc/html/core/enable_if.html">
|
<title>Boost.Utility</title>
|
||||||
<title>Automatic redirection</title>
|
<meta http-equiv="refresh" content="0; URL=./doc/html/index.html">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
Automatic redirection failed, please go to
|
Automatic redirection failed, please go to
|
||||||
<a href="../core/doc/html/core/enable_if.html">enable_if.html</a>. <hr>
|
<a href="../core/doc/html/core/enable_if.html">../core/doc/html/core/enable_if.html</a>
|
||||||
<p>© Copyright Beman Dawes, 2001</p>
|
<hr>
|
||||||
<p>Distributed under the Boost Software License, Version 1.0. (See accompanying
|
<tt>
|
||||||
file <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or copy
|
Boost.Utility<br>
|
||||||
at <a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a>)</p>
|
<br>
|
||||||
|
Distributed under the Boost Software License, Version 1.0.
|
||||||
|
(See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
<a href=http://www.boost.org/LICENSE_1_0.txt>http://www.boost.org/LICENSE_1_0.txt</a>) <br>
|
||||||
|
<br>
|
||||||
|
</tt>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
<body>
|
<body>
|
||||||
Automatic redirection failed, click this
|
Automatic redirection failed, click this
|
||||||
<a href="doc/html/index.html">link</a> <hr>
|
<a href="doc/html/index.html">link</a> <hr>
|
||||||
<p>Š Copyright Lorenzo Caminiti, 2009-2012</p>
|
<p>Copyright © Lorenzo Caminiti, 2009-2012</p>
|
||||||
<p>Distributed under the Boost Software License, Version 1.0 (see
|
<p>Distributed under the Boost Software License, Version 1.0 (see
|
||||||
accompanying file <a href="../../../LICENSE_1_0.txt">
|
accompanying file <a href="../../../LICENSE_1_0.txt">
|
||||||
LICENSE_1_0.txt</a> or a copy at
|
LICENSE_1_0.txt</a> or a copy at
|
||||||
|
@ -1,296 +1,19 @@
|
|||||||
<!DOCTYPE HTML PUBLIC "-//SoftQuad Software//DTD HoTMetaL PRO 5.0::19981217::extensions to HTML 4.0//EN" "hmpro5.dtd">
|
<html>
|
||||||
|
<head>
|
||||||
<HTML>
|
<title>Boost.Utility</title>
|
||||||
|
<meta http-equiv="refresh" content="0; URL=./doc/html/index.html">
|
||||||
<HEAD>
|
</head>
|
||||||
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=windows-1252">
|
<body>
|
||||||
<TITLE>In_place_factory Documentation</TITLE>
|
Automatic redirection failed, please go to
|
||||||
</HEAD>
|
<a href="./doc/html/utility/utilities/in_place_factory.html">./doc/html/utility/utilities/in_place_factory.html</a>
|
||||||
|
|
||||||
<BODY BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#0000FF" VLINK="#800080">
|
|
||||||
<H2 align="left"><IMG SRC="../../boost.png" WIDTH="276" HEIGHT="86"></H2>
|
|
||||||
|
|
||||||
<blockquote>
|
|
||||||
<blockquote>
|
|
||||||
<blockquote>
|
|
||||||
<blockquote>
|
|
||||||
<blockquote>
|
|
||||||
<blockquote>
|
|
||||||
<H2 align="left">Header <<A
|
|
||||||
HREF="../../boost/utility/in_place_factory.hpp">boost/utility/in_place_factory.hpp</A>> </H2>
|
|
||||||
|
|
||||||
<H2 align="left">Header <<A
|
|
||||||
HREF="../../boost/utility/typed_in_place_factory.hpp">boost/utility/typed_in_place_factory.hpp</A>> </H2>
|
|
||||||
|
|
||||||
</blockquote>
|
|
||||||
</blockquote>
|
|
||||||
</blockquote>
|
|
||||||
</blockquote>
|
|
||||||
</blockquote>
|
|
||||||
</blockquote>
|
|
||||||
<p> </p>
|
|
||||||
|
|
||||||
<H2>Contents</H2>
|
|
||||||
<DL CLASS="page-index">
|
|
||||||
<DT><A HREF="#mot">Motivation</A></DT>
|
|
||||||
<DT><A HREF="#framework">Framework</A></DT>
|
|
||||||
<DT><A HREF="#specification">Specification</A></DT>
|
|
||||||
<DT><A HREF="#container-usage">Container-side Usage</A></DT>
|
|
||||||
<DT><A HREF="#user-usage">User-side Usage</A></DT>
|
|
||||||
</DL>
|
|
||||||
|
|
||||||
<HR>
|
|
||||||
|
|
||||||
<H2><A NAME="mot"></A>Motivation</H2>
|
|
||||||
|
|
||||||
<p>Suppose we have a class</p>
|
|
||||||
<pre>struct X
|
|
||||||
{
|
|
||||||
X ( int, std::string ) ;
|
|
||||||
} ;</pre>
|
|
||||||
<p>And a container for it which supports an empty state (that is, which can contain zero objects):</p>
|
|
||||||
<pre>struct C
|
|
||||||
{
|
|
||||||
C() : contained_(0) {}
|
|
||||||
~C() { delete contained_ ; }
|
|
||||||
X* contained_ ;
|
|
||||||
} ;</pre>
|
|
||||||
<p>A container designed to support an empty state typically doesn't require the contained type to be DefaultConstructible,
|
|
||||||
but it typically requires it to be CopyConstructible as a mechanism to
|
|
||||||
initialize the object to store:</p>
|
|
||||||
<pre>struct C
|
|
||||||
{
|
|
||||||
C() : contained_(0) {}
|
|
||||||
C ( X const& v ) : contained_ ( new X(v) ) {}
|
|
||||||
~C() { delete contained_ ; }
|
|
||||||
X* contained_ ;
|
|
||||||
} ;</pre>
|
|
||||||
<p>There is a subtle problem with this: since the mechanism used to initialize the stored object is copy construction,
|
|
||||||
there must exist a previously constructed source object to copy from. This
|
|
||||||
object is likely to be temporary and serve no purpose besides being the source</p>
|
|
||||||
<pre>void foo()
|
|
||||||
{
|
|
||||||
// Temporary object created.
|
|
||||||
C c( X(123,"hello") ) ;
|
|
||||||
}
|
|
||||||
</pre>
|
|
||||||
<p>A solution to this problem is to support direct construction of the contained
|
|
||||||
object right in the container's storage.<br>
|
|
||||||
In this scheme, the user supplies the arguments for the X constructor
|
|
||||||
directly to the container:</p>
|
|
||||||
<pre>struct C
|
|
||||||
{
|
|
||||||
C() : contained_(0) {}
|
|
||||||
C ( X const& v ) : contained_ ( new X(v) ) {}
|
|
||||||
C ( int a0, std::string a1 ) : contained_ ( new X(a0,a1) ) {}
|
|
||||||
~C() { delete contained_ ; }
|
|
||||||
X* contained_ ;
|
|
||||||
} ;</pre>
|
|
||||||
<pre>void foo()
|
|
||||||
{
|
|
||||||
// Wrapped object constructed in-place
|
|
||||||
// No temporary created.
|
|
||||||
C c(123,"hello") ;
|
|
||||||
}
|
|
||||||
</pre>
|
|
||||||
<p>Clearly, this solution doesn't scale well since the container must duplicate all the constructor overloads from the contained type
|
|
||||||
(at least all those which are to be supported directly in the container).</p>
|
|
||||||
|
|
||||||
<H2><A NAME="framework"></A>Framework</H2>
|
|
||||||
<p>
|
|
||||||
This library proposes a framework to allow some containers to directly contruct contained objects in-place without requiring
|
|
||||||
the entire set of constructor overloads from the contained type. It also allows the container to remove the CopyConstuctible
|
|
||||||
requirement from the contained type since objects can be directly constructed in-place without need of a copy.<br>
|
|
||||||
The only requirement on the container is that it must provide proper storage (that is, correctly aligned and sized).
|
|
||||||
Naturally, the container will typically support uninitialized storage to avoid the in-place construction to override
|
|
||||||
a fully-constructed object (as this would defeat the purpose of in-place construction)
|
|
||||||
</p>
|
|
||||||
<p>For this purpose, the framework provides two families of classes collectively called: InPlaceFactories and TypedInPlaceFactories.<br>
|
|
||||||
Essentially, these classes hold a sequence of actual parameters and a method to contruct an object in place using these parameters.
|
|
||||||
Each member of the family differs only in the number (and type) of the parameter list. The first family
|
|
||||||
takes the type of the object to construct directly in method provided for that
|
|
||||||
purpose, whereas the second family incorporates that type in the factory class
|
|
||||||
itself..</p>
|
|
||||||
<p>From the container POV, using the framework amounts to calling the factory's method to contruct the object in place.
|
|
||||||
From the user POV, it amounts to creating the right factory object to hold the parameters and pass it to the container.<br>
|
|
||||||
The following simplified example shows the basic idea. A complete example follows the formal specification of the framework:</p>
|
|
||||||
<pre>struct C
|
|
||||||
{
|
|
||||||
template<class InPlaceFactory>
|
|
||||||
C ( InPlaceFactory const& aFactory )
|
|
||||||
:
|
|
||||||
contained_ ( uninitialized_storage() )
|
|
||||||
{
|
|
||||||
aFactory.template apply<X>(contained_);
|
|
||||||
}
|
|
||||||
|
|
||||||
~C()
|
|
||||||
{
|
|
||||||
contained_ -> X::~X();
|
|
||||||
delete[] contained_ ;
|
|
||||||
}
|
|
||||||
|
|
||||||
char* uninitialized_storage() { return new char[sizeof(X)] ; }
|
|
||||||
|
|
||||||
char* contained_ ;
|
|
||||||
} ;
|
|
||||||
|
|
||||||
void foo()
|
|
||||||
{
|
|
||||||
C c( in_place(123,"hello") ) ;
|
|
||||||
}
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<HR>
|
|
||||||
|
|
||||||
<H2><A NAME="specification">Specification</A></H2>
|
|
||||||
|
|
||||||
<p>The following is the first member of the family of 'in_place_factory' classes, along with its corresponding helper template function.
|
|
||||||
The rest of the family varies only in the number and type of template (and constructor) parameters.</p>
|
|
||||||
<PRE>namespace boost {
|
|
||||||
|
|
||||||
struct in_place_factory_base {} ;
|
|
||||||
|
|
||||||
template<class A0>
|
|
||||||
class in_place_factory : public in_place_factory_base
|
|
||||||
{
|
|
||||||
public:</PRE>
|
|
||||||
|
|
||||||
<PRE> in_place_factory ( A0 const& a0 ) : m_a0(a0) {}
|
|
||||||
|
|
||||||
template< class T >
|
|
||||||
void apply ( void* address ) const
|
|
||||||
{
|
|
||||||
new (address) T(m_a0);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:</PRE>
|
|
||||||
|
|
||||||
<PRE> A0 const& m_a0 ;
|
|
||||||
} ;
|
|
||||||
|
|
||||||
template<class A0>
|
|
||||||
in_place_factory<A0> in_place ( A0 const& a0 )
|
|
||||||
{
|
|
||||||
return in_place_factory<A0>(a0);
|
|
||||||
}
|
|
||||||
</PRE>
|
|
||||||
|
|
||||||
<p>Similarly, the following is the first member of the family of 'typed_in_place_factory' classes, along with its corresponding
|
|
||||||
helper template function. The rest of the family varies only in the number and type of template (and constructor) parameters.</p>
|
|
||||||
<PRE>namespace boost {
|
|
||||||
|
|
||||||
struct typed_in_place_factory_base {} ;
|
|
||||||
|
|
||||||
template<class T, class A0>
|
|
||||||
class typed_in_place_factory : public typed_in_place_factory_base
|
|
||||||
{
|
|
||||||
public:</PRE>
|
|
||||||
|
|
||||||
<PRE> typed_in_place_factory ( A0 const& a0 ) : m_a0(a0) {}
|
|
||||||
|
|
||||||
void apply ( void* address ) const
|
|
||||||
{
|
|
||||||
new (address) T(m_a0);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:</PRE>
|
|
||||||
|
|
||||||
<PRE> A0 const& m_a0 ;
|
|
||||||
} ;
|
|
||||||
|
|
||||||
template<class T, class A0>
|
|
||||||
typed_in_place_factory<A0> in_place ( A0 const& a0 )
|
|
||||||
{
|
|
||||||
return typed_in_place_factory<T,A0>(a0);
|
|
||||||
}</PRE>
|
|
||||||
|
|
||||||
<PRE>}
|
|
||||||
</PRE>
|
|
||||||
|
|
||||||
<p>As you can see, the 'in_place_factory' and 'typed_in_place_factory' template classes varies only in the way they specify
|
|
||||||
the target type: in the first family, the type is given as a template argument to the apply member function while in the
|
|
||||||
second it is given directly as part of the factory class.<br>
|
|
||||||
When the container holds a unique non-polymorphic type (such as the case of Boost.Optional), it knows the exact dynamic-type
|
|
||||||
of the contained object and can pass it to the apply() method of a (non-typed) factory.
|
|
||||||
In this case, end users can use an 'in_place_factory' instance which can be constructed without the type of the object to construct.<br>
|
|
||||||
However, if the container holds heterogeneous or polymorphic objects (such as the case of Boost.Variant), the dynamic-type
|
|
||||||
of the object to be constructed must be known by the factory itslef. In this case, end users must use a 'typed_in_place_factory'
|
|
||||||
instead.</p>
|
|
||||||
|
|
||||||
<HR>
|
|
||||||
|
|
||||||
<h2><A NAME="container-usage">Container-side Usage</a></h2>
|
|
||||||
|
|
||||||
<p>As shown in the introductory simplified example, the container class must
|
|
||||||
contain methods that accept an instance of
|
|
||||||
these factories and pass the object's storage to the factory's apply method.<br>
|
|
||||||
However, the type of the factory class cannot be completly specified in the container class because that would
|
|
||||||
defeat the whole purpose of the factories which is to allow the container to accept a variadic argument list
|
|
||||||
for the constructor of its contained object.<br>
|
|
||||||
The correct function overload must be based on the only distinctive and common
|
|
||||||
characteristic of all the classes in each family, the base class.<br>
|
|
||||||
Depending on the container class, you can use 'enable_if' to generate the right overload, or use the following
|
|
||||||
dispatch technique (used in the Boost.Optional class):
|
|
||||||
</p>
|
|
||||||
<pre>struct C
|
|
||||||
{
|
|
||||||
C() : contained_(0) {}
|
|
||||||
C ( X const& v ) : contained_ ( new X(v) ) {}
|
|
||||||
|
|
||||||
template<class Expr>
|
|
||||||
C ( Expr const& expr )
|
|
||||||
:
|
|
||||||
contained_ ( uninitialized_storage() )
|
|
||||||
{
|
|
||||||
construct(expr,&expr)
|
|
||||||
}
|
|
||||||
|
|
||||||
~C() { delete contained_ ; }
|
|
||||||
|
|
||||||
template<class InPlaceFactory>
|
|
||||||
void construct ( InPlaceFactory const& aFactory, boost::in_place_factory_base* )
|
|
||||||
{
|
|
||||||
aFactory.template apply<X>(contained_);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class TypedInPlaceFactory>
|
|
||||||
void construct ( TypedInPlaceFactory const& aFactory, boost::typed_in_place_factory_base* )
|
|
||||||
{
|
|
||||||
aFactory.apply(contained_);
|
|
||||||
}
|
|
||||||
|
|
||||||
X* uninitialized_storage() { return static_cast<X*>(new char[sizeof(X)]) ; }
|
|
||||||
|
|
||||||
X* contained_ ;
|
|
||||||
} ;
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
|
<tt>
|
||||||
<h2><A NAME="user-usage">User-side Usage</a></h2>
|
Boost.Utility<br>
|
||||||
|
<br>
|
||||||
<p>End users pass to the container an instance of a factory object holding the actual parameters needed to construct the
|
Distributed under the Boost Software License, Version 1.0.
|
||||||
contained object directly within the container. For this, the helper template function 'in_place' is used.<br>
|
(See accompanying file LICENSE_1_0.txt or copy at
|
||||||
The call 'in_place(a0,a1,a2,...,an)' constructs a (non-typed) 'in_place_factory' instance with the given argument list.<br>
|
<a href=http://www.boost.org/LICENSE_1_0.txt>http://www.boost.org/LICENSE_1_0.txt</a>) <br>
|
||||||
The call 'in_place<T>(a0,a1,a2,...,an)' constructs a 'typed_in_place_factory' instance with the given argument list for the
|
<br>
|
||||||
type 'T'.</p>
|
</tt>
|
||||||
<pre>void foo()
|
</body>
|
||||||
{
|
</html>
|
||||||
C a( in_place(123,"hello") ) ; // in_place_factory passed
|
|
||||||
C b( in_place<X>(456,"world") ) ; // typed_in_place_factory passed
|
|
||||||
}
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<P>Revised September 17, 2004</P>
|
|
||||||
<p>© Copyright Fernando Luis Cacciola Carballal, 2004</p>
|
|
||||||
<p> Use, modification, and distribution are subject to the Boost Software
|
|
||||||
License, Version 1.0. (See accompanying file <a href="../../LICENSE_1_0.txt">
|
|
||||||
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
|
|
||||||
www.boost.org/LICENSE_1_0.txt</a>)</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
|
|
||||||
<A HREF="http://www.boost.org/more/mailing_lists.htm#main">discussion lists</A></P>
|
|
||||||
</BODY>
|
|
||||||
</HTML>
|
|
||||||
|
65
index.html
65
index.html
@ -1,50 +1,19 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta http-equiv="Content-Language" content="en-us">
|
<title>Boost.Utility</title>
|
||||||
<meta name="GENERATOR" content="Microsoft FrontPage 5.0">
|
<meta http-equiv="refresh" content="0; URL=./doc/html/index.html">
|
||||||
<meta name="ProgId" content="FrontPage.Editor.Document">
|
</head>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
|
<body>
|
||||||
<title>Boost Utility Library</title>
|
Automatic redirection failed, please go to
|
||||||
</head>
|
<a href="./doc/html/index.html">./doc/html/index.html</a>
|
||||||
<body bgcolor="#FFFFFF">
|
<hr>
|
||||||
<h1><IMG SRC="../../boost.png" WIDTH="276" HEIGHT="86" align="center">Boost
|
<tt>
|
||||||
Utility Library</h1>
|
Boost.Utility<br>
|
||||||
<p>The Boost Utility Library isn't really a single library at all. It is just a
|
<br>
|
||||||
collection for components too small to be called libraries in their own right.</p>
|
Distributed under the Boost Software License, Version 1.0.
|
||||||
<p>But that doesn't mean there isn't useful stuff here. Take a look:</p>
|
(See accompanying file LICENSE_1_0.txt or copy at
|
||||||
<ul>
|
<a href=http://www.boost.org/LICENSE_1_0.txt>http://www.boost.org/LICENSE_1_0.txt</a>) <br>
|
||||||
<li><a href="doc/html/base_from_member.html">base_from_member</a></li>
|
<br>
|
||||||
<li><a href="utility.htm#BOOST_BINARY">BOOST_BINARY</a></li>
|
</tt>
|
||||||
<li><a href="call_traits.htm">call_traits</a></li>
|
</body>
|
||||||
<li><a href="doc/html/compressed_pair.html">compressed_pair</a></li>
|
|
||||||
<li><a href="in_place_factories.html">in_place_factory</a></li>
|
|
||||||
<li><a href="iterator_adaptors.htm">iterator_adaptors</a></li>
|
|
||||||
<li><a href="operators.htm">operators</a></li>
|
|
||||||
<li><a href="utility.htm#result_of">result_of</a></li>
|
|
||||||
<li><a href="throw_exception.html">throw_exception</a></li>
|
|
||||||
<li><a href="utility.htm">utility</a></li>
|
|
||||||
<li><a href="doc/html/string_ref.html">string_ref</a></li>
|
|
||||||
<li><a href="value_init.htm">value_init</a></li>
|
|
||||||
</ul>
|
|
||||||
<p>Over time useful stuff here has moved to more appropriate Boost libraries:</p>
|
|
||||||
<ul>
|
|
||||||
<li><a href="../core/doc/html/core/addressof.html">addressof</a> (moved to Boost.Core)</li>
|
|
||||||
<li><a href="../core/doc/html/core/checked_delete.html">checked_delete</a> (moved to Boost.Core)</li>
|
|
||||||
<li><a href="../type_traits/doc/html/boost_typetraits/reference/declval.html">declval</a> (moved to Boost.TypeTraits)</li>
|
|
||||||
<li><a href="../core/doc/html/core/enable_if.html">enable_if</a> (moved to Boost.Core)</li>
|
|
||||||
<li><a href="../iterator/doc/generator_iterator.htm">generator iterator adaptors</a> (moved to Boost.Iterator)</li>
|
|
||||||
<li><a href="../iterator/doc/html/iterator/algorithms/next_prior.html">next/prior</a> (moved to Boost.Iterator)</li>
|
|
||||||
<li><a href="../core/doc/html/core/noncopyable.html">noncopyable</a> (moved to Boost.Core)</li>
|
|
||||||
<li><a href="../io/doc/html/io.html">ostream_string</a> (moved to Boost.IO)</li>
|
|
||||||
</ul>
|
|
||||||
<hr>
|
|
||||||
<p>© Copyright Beman Dawes, 2001</p>
|
|
||||||
<p>Distributed under the Boost Software License, Version 1.0. (See
|
|
||||||
accompanying file <a href="../../LICENSE_1_0.txt">
|
|
||||||
LICENSE_1_0.txt</a> or copy at
|
|
||||||
<a href="http://www.boost.org/LICENSE_1_0.txt">
|
|
||||||
www.boost.org/LICENSE_1_0.txt</a>)</p>
|
|
||||||
<p>Revised
|
|
||||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->07 November, 2006<!--webbot bot="Timestamp" endspan i-checksum="39368" --></p>
|
|
||||||
</body>
|
|
||||||
</html>
|
</html>
|
||||||
|
@ -1,11 +1,19 @@
|
|||||||
<!-- Copyright David Abrahams 2004. Distributed under the Boost -->
|
|
||||||
<!-- Software License, Version 1.0. (See accompanying -->
|
|
||||||
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
|
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta http-equiv="refresh" content="0; URL=../iterator/doc/index.html">
|
<title>Boost.Utility</title>
|
||||||
|
<meta http-equiv="refresh" content="0; URL=./doc/html/index.html">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
This documentation moved to <a href="../iterator/doc/index.html">../iterator/doc/index.html</a>.
|
Automatic redirection failed, please go to
|
||||||
|
<a href="../iterator/doc/generator_iterator.htm">../iterator/doc/generator_iterator.htm</a>
|
||||||
|
<hr>
|
||||||
|
<tt>
|
||||||
|
Boost.Utility<br>
|
||||||
|
<br>
|
||||||
|
Distributed under the Boost Software License, Version 1.0.
|
||||||
|
(See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
<a href=http://www.boost.org/LICENSE_1_0.txt>http://www.boost.org/LICENSE_1_0.txt</a>) <br>
|
||||||
|
<br>
|
||||||
|
</tt>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
2235
operators.htm
2235
operators.htm
File diff suppressed because it is too large
Load Diff
@ -1,15 +1,15 @@
|
|||||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta http-equiv=refresh content="0; URL=../exception/doc/throw_exception.html">
|
<meta http-equiv=refresh content="0; URL=../exception/doc/throw_exception.html">
|
||||||
<title>Automatic redirection</title>
|
<title>Automatic redirection</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
Automatic redirection failed, please go to
|
Automatic redirection failed, please go to
|
||||||
<a href="../exception/doc/throw_exception.html">throw_exception.html</a>. <hr>
|
<a href="../throw_exception/doc/html/throw_exception.html#using_boost_throw_exception">../throw_exception/doc/html/throw_exception.html#using_boost_throw_exception</a>. <hr>
|
||||||
<p>© Copyright Beman Dawes, 2001</p>
|
<p>Copyright © Beman Dawes, 2001</p>
|
||||||
<p>Distributed under the Boost Software License, Version 1.0. (See accompanying
|
<p>Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
file <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or copy
|
file <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or copy
|
||||||
at <a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a>)</p>
|
at <a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a>)</p>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
598
utility.htm
598
utility.htm
@ -1,583 +1,19 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
<title>Boost.Utility</title>
|
||||||
<title>Header boost/utility.hpp Documentation</title>
|
<meta http-equiv="refresh" content="0; URL=./doc/html/index.html">
|
||||||
</head>
|
</head>
|
||||||
<body bgcolor="#FFFFFF" text="#000000">
|
<body>
|
||||||
<h1><img src="../../boost.png" alt="boost.png (6897 bytes)" align="center" WIDTH="277" HEIGHT="86">Header
|
Automatic redirection failed, please go to
|
||||||
<a href="../../boost/utility.hpp">boost/utility.hpp</a></h1>
|
<a href="./doc/html/index.html">./doc/html/index.html</a>
|
||||||
<p>The entire contents of the header <code><a href="../../boost/utility.hpp"><boost/utility.hpp></a></code>
|
<hr>
|
||||||
are in <code>namespace boost</code>.</p>
|
<tt>
|
||||||
<h2>Contents</h2>
|
Boost.Utility<br>
|
||||||
<ul>
|
<br>
|
||||||
<li>
|
Distributed under the Boost Software License, Version 1.0.
|
||||||
Class templates supporting the <a href="doc/html/base_from_member.html">
|
(See accompanying file LICENSE_1_0.txt or copy at
|
||||||
base-from-member idiom</a></li>
|
<a href=http://www.boost.org/LICENSE_1_0.txt>http://www.boost.org/LICENSE_1_0.txt</a>) <br>
|
||||||
<li>
|
<br>
|
||||||
Function templates <a href="../core/doc/html/core/checked_delete.html">checked_delete() and
|
</tt>
|
||||||
checked_array_delete()</a> (moved to the Boost.Core library)</li>
|
</body>
|
||||||
<li>
|
|
||||||
Function templates <a href="../iterator/doc/html/iterator/algorithms/next_prior.html">next() and prior()</a> (moved to the Boost.Iterator library)</li>
|
|
||||||
<li>
|
|
||||||
Class <a href="../core/doc/html/core/noncopyable.html">noncopyable</a> (moved to the Boost.Core library)</li>
|
|
||||||
<li>
|
|
||||||
Function template <a href="../core/doc/html/core/addressof.html">addressof()</a> (moved to the Boost.Core library)</li>
|
|
||||||
<li>Class template <a href="#result_of">result_of</a></li>
|
|
||||||
<li>
|
|
||||||
Macro <a href="#BOOST_BINARY">BOOST_BINARY</a></li>
|
|
||||||
<li><a href="index.html">Other utilities not part of <code>utility.hpp</code></a></li>
|
|
||||||
</ul>
|
|
||||||
<h2>
|
|
||||||
|
|
||||||
<h2><a name="result_of">Class template
|
|
||||||
result_of</a></h2> <p>The class template
|
|
||||||
<code>result_of</code> helps determine the type of a
|
|
||||||
call expression. For example, given an lvalue <code>f</code> of
|
|
||||||
type <code>F</code> and lvalues <code>t1</code>,
|
|
||||||
<code>t2</code>, ..., <code>t<em>N</em></code> of
|
|
||||||
types <code>T1</code>, <code>T2</code>, ...,
|
|
||||||
<code>T<em>N</em></code>, respectively, the type
|
|
||||||
<code>result_of<F(T1, T2, ...,
|
|
||||||
T<em>N</em>)>::type</code> defines the result type
|
|
||||||
of the expression <code>f(t1, t2,
|
|
||||||
...,t<em>N</em>)</code>. This implementation permits
|
|
||||||
the type <code>F</code> to be a function pointer,
|
|
||||||
function reference, member function pointer, or class
|
|
||||||
type. By default, <em>N</em> may be any value between 0 and
|
|
||||||
16. To change the upper limit, define the macro
|
|
||||||
<code>BOOST_RESULT_OF_NUM_ARGS</code> to the maximum
|
|
||||||
value for <em>N</em>. Class template <code>result_of</code>
|
|
||||||
resides in the header <code><<a
|
|
||||||
href="../../boost/utility/result_of.hpp">boost/utility/result_of.hpp</a>></code>.</p>
|
|
||||||
|
|
||||||
<p>If your compiler's support for <code>decltype</code> is
|
|
||||||
adequate, <code>result_of</code> automatically uses it to
|
|
||||||
deduce the type of the call expression, in which case
|
|
||||||
<code>result_of<F(T1, T2, ...,
|
|
||||||
T<em>N</em>)>::type</code> names the type
|
|
||||||
<code>decltype(boost::declval<F>()(boost::declval<T1>(),
|
|
||||||
boost::declval<T2>(), ...,
|
|
||||||
boost::declval<T<em>N</em>>()))</code>, as in the
|
|
||||||
following example.</p>
|
|
||||||
|
|
||||||
<blockquote>
|
|
||||||
<pre>struct functor {
|
|
||||||
template<class T>
|
|
||||||
T operator()(T x)
|
|
||||||
{
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef boost::result_of<
|
|
||||||
functor(int)
|
|
||||||
>::type type; // type is int</pre>
|
|
||||||
</blockquote>
|
|
||||||
|
|
||||||
<p>You can test whether <code>result_of</code> is using
|
|
||||||
<code>decltype</code> by checking if the macro
|
|
||||||
<code>BOOST_RESULT_OF_USE_DECLTYPE</code> is defined after
|
|
||||||
including <code>result_of.hpp</code>. You can also force
|
|
||||||
<code>result_of</code> to use <code>decltype</code> by
|
|
||||||
defining <code>BOOST_RESULT_OF_USE_DECLTYPE</code> prior
|
|
||||||
to including <code>result_of.hpp</code>.</p>
|
|
||||||
|
|
||||||
<p>If <code>decltype</code> is not used,
|
|
||||||
then automatic result type deduction of function
|
|
||||||
objects is not possible. Instead, <code>result_of</code>
|
|
||||||
uses the following protocol to allow the programmer to
|
|
||||||
specify a type. When <code>F</code> is a class type with a
|
|
||||||
member type <code>result_type</code>,
|
|
||||||
<code>result_of<F(T1, T2, ...,
|
|
||||||
T<em>N</em>)>::type</code> is
|
|
||||||
<code>F::result_type</code>. When <code>F</code> does
|
|
||||||
not contain <code>result_type</code>,
|
|
||||||
<code>result_of<F(T1, T2, ...,
|
|
||||||
T<em>N</em>)>::type</code> is <code>F::result<F(T1,
|
|
||||||
T2, ..., T<em>N</em>)>::type</code> when
|
|
||||||
<code><em>N</em> > 0</code> or <code>void</code>
|
|
||||||
when <code><em>N</em> = 0</code>. Note that it is the
|
|
||||||
responsibility of the programmer to ensure that
|
|
||||||
function objects accurately advertise their result
|
|
||||||
type via this protocol, as in the following
|
|
||||||
example.</p>
|
|
||||||
|
|
||||||
<blockquote>
|
|
||||||
<pre>struct functor {
|
|
||||||
template<class> struct result;
|
|
||||||
|
|
||||||
template<class F, class T>
|
|
||||||
struct result<F(T)> {
|
|
||||||
typedef T type;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
T operator()(T x)
|
|
||||||
{
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef boost::result_of<
|
|
||||||
functor(int)
|
|
||||||
>::type type; // type is int</pre>
|
|
||||||
</blockquote>
|
|
||||||
|
|
||||||
<p>Since <code>decltype</code> is a new language
|
|
||||||
feature recently standardized in C++11,
|
|
||||||
if you are writing a function object
|
|
||||||
to be used with <code>result_of</code>, for
|
|
||||||
maximum portability, you might consider following
|
|
||||||
the above protocol even if your compiler has
|
|
||||||
proper <code>decltype</code> support. If you wish to continue to
|
|
||||||
use the protocol on compilers that
|
|
||||||
support <code>decltype</code>, there are two options:
|
|
||||||
You can use <code>boost::tr1_result_of</code>, which is also
|
|
||||||
defined in <code><<a href="../../boost/utility/result_of.hpp">boost/utility/result_of.hpp</a>></code>.
|
|
||||||
Alternatively, you can define the macro
|
|
||||||
<code>BOOST_RESULT_OF_USE_TR1</code>, which causes
|
|
||||||
<code>result_of</code> to use the protocol described
|
|
||||||
above instead of <code>decltype</code>. If you choose to
|
|
||||||
follow the protocol, take care to ensure that the
|
|
||||||
<code>result_type</code> and
|
|
||||||
<code>result<></code> members accurately
|
|
||||||
represent the return type of
|
|
||||||
<code>operator()</code> given a call expression.</p>
|
|
||||||
|
|
||||||
<p>Additionally, <code>boost::result_of</code>
|
|
||||||
provides a third mode of operation, which some users
|
|
||||||
may find convenient. When
|
|
||||||
<code>BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK</code>
|
|
||||||
is defined, <code>boost::result_of</code> behaves as
|
|
||||||
follows. If the function object has a member
|
|
||||||
type <code>result_type</code> or member
|
|
||||||
template <code>result<></code>, then
|
|
||||||
<code>boost::result_of</code> will use the TR1
|
|
||||||
protocol. Otherwise,
|
|
||||||
<code>boost::result_of</code> will
|
|
||||||
use <code>decltype</code>. Using TR1 with
|
|
||||||
a <code>declytpe</code> fallback may workaround
|
|
||||||
certain problems at the cost of portability. For
|
|
||||||
example:
|
|
||||||
<ul>
|
|
||||||
<li>Deficient compiler: If your code
|
|
||||||
requires <code>boost::result_of</code> to work
|
|
||||||
with incomplete return types but your
|
|
||||||
compiler's <code>decltype</code> implementation
|
|
||||||
does not support incomplete return types, then you
|
|
||||||
can use the TR1 protocol as a workaround. Support
|
|
||||||
for incomplete return types was added late in the
|
|
||||||
C++11 standardization process
|
|
||||||
(see <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3276.pdf">N3276</a>)
|
|
||||||
and is not implemented by some compilers.</li>
|
|
||||||
|
|
||||||
<li>Deficient legacy code: If your existing TR1
|
|
||||||
function object advertises a different type than
|
|
||||||
the actual result type deduced
|
|
||||||
by <code>decltype</code>, then using TR1 with a
|
|
||||||
<code>decltype</code> fallback will allow you to
|
|
||||||
work with both your existing TR1 function objects
|
|
||||||
and new C++11 function object. This situation
|
|
||||||
could occur if your legacy function objects
|
|
||||||
misused the TR1 protocol. See the documentation on
|
|
||||||
known <a href="#result_of_tr1_diff">differences</a>
|
|
||||||
between <code>boost::result_of</code> and TR1.</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<a name="BOOST_NO_RESULT_OF"></a>
|
|
||||||
<p>This implementation of <code>result_of</code>
|
|
||||||
requires class template partial specialization, the
|
|
||||||
ability to parse function types properly, and support
|
|
||||||
for SFINAE. If <code>result_of</code> is not supported
|
|
||||||
by your compiler, including the header
|
|
||||||
<code>boost/utility/result_of.hpp</code> will
|
|
||||||
define the macro <code>BOOST_NO_RESULT_OF</code>.</p>
|
|
||||||
|
|
||||||
<p>For additional information
|
|
||||||
about <code>result_of</code>, see the C++ Library
|
|
||||||
Technical Report,
|
|
||||||
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf">N1836</a>,
|
|
||||||
or, for motivation and design rationale,
|
|
||||||
the <code>result_of</code> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1454.html">proposal</a>.</p>
|
|
||||||
|
|
||||||
<a name="result_of_guidelines">
|
|
||||||
<h3>Usage guidelines for boost::result_of</h3>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<p>The following are general suggestions about when
|
|
||||||
and how to use <code>boost::result_of</code>.</p>
|
|
||||||
|
|
||||||
<ol>
|
|
||||||
<li> If you are targeting C++11 and are not concerned
|
|
||||||
about portability to non-compliant compilers or
|
|
||||||
previous versions of the standard, then use
|
|
||||||
<code>std::result_of</code>. If <code>std::result_of</code>
|
|
||||||
meets your needs, then there's no reason to stop using
|
|
||||||
it.</li>
|
|
||||||
|
|
||||||
<li> If you are targeting C++11 but may port your code
|
|
||||||
to legacy compilers at some time in the future, then
|
|
||||||
use <code>boost::result_of</code> with
|
|
||||||
<code>decltype</code>. When <code>decltype</code> is
|
|
||||||
used <code>boost::result_of</code>
|
|
||||||
and <code>std::result_of</code> are usually
|
|
||||||
interchangeable. See the documentation on
|
|
||||||
known <a href="#result_of_cxx11_diff">differences</a>
|
|
||||||
between boost::result_of and C++11 result_of.</li>
|
|
||||||
|
|
||||||
<li> If compiler portability is required,
|
|
||||||
use <code>boost::result_of</code> with the TR1 protocol.</li>
|
|
||||||
</ol>
|
|
||||||
|
|
||||||
<p>Regardless of how you
|
|
||||||
configure <code>boost::result_of</code>, it is
|
|
||||||
important to bear in mind that the return type of a
|
|
||||||
function may change depending on its arguments, and
|
|
||||||
additionally, the return type of a member function may
|
|
||||||
change depending on the cv-qualification of the
|
|
||||||
object. <code>boost::result_of</code> must be passed
|
|
||||||
the appropriately cv-qualified types in order to
|
|
||||||
deduce the corresponding return type. For example:
|
|
||||||
|
|
||||||
<blockquote>
|
|
||||||
<pre>struct functor {
|
|
||||||
int& operator()(int);
|
|
||||||
int const& operator()(int) const;
|
|
||||||
|
|
||||||
float& operator()(float&);
|
|
||||||
float const& operator()(float const&);
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef boost::result_of<
|
|
||||||
functor(int)
|
|
||||||
>::type type1; // type1 is int &
|
|
||||||
|
|
||||||
typedef boost::result_of<
|
|
||||||
const functor(int)
|
|
||||||
>::type type2; // type2 is int const &
|
|
||||||
|
|
||||||
typedef boost::result_of<
|
|
||||||
functor(float&)
|
|
||||||
>::type type3; // type3 is float &
|
|
||||||
|
|
||||||
typedef boost::result_of<
|
|
||||||
functor(float const&)
|
|
||||||
>::type type4; // type4 is float const &</pre>
|
|
||||||
</blockquote>
|
|
||||||
|
|
||||||
<a name="result_of_tr1_protocol_guidelines">
|
|
||||||
<h3>Usage guidelines for the TR1 result_of protocol</h3>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<p>On compliant C++11
|
|
||||||
compilers, <code>boost::result_of</code> can
|
|
||||||
use <code>decltype</code> to deduce the type of any
|
|
||||||
call expression, including calls to function
|
|
||||||
objects. However, on pre-C++11 compilers or on
|
|
||||||
compilers without adequate decltype support,
|
|
||||||
additional scaffolding is needed from function
|
|
||||||
objects as described above. The following are
|
|
||||||
suggestions about how to use the TR1 protocol.</p>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>When the return type does not depend on the
|
|
||||||
argument types or the cv-qualification of the
|
|
||||||
function object, simply
|
|
||||||
define <code>result_type</code>. There is no need
|
|
||||||
to use the <code>result</code> template unless the
|
|
||||||
return type varies.</li>
|
|
||||||
|
|
||||||
<li>Use the protocol specified type when defining
|
|
||||||
function prototypes. This can help ensure the
|
|
||||||
actual return type does not get out of sync with
|
|
||||||
the protocol specification. For example:
|
|
||||||
|
|
||||||
<blockquote>
|
|
||||||
<pre>struct functor {
|
|
||||||
typedef int result_type;
|
|
||||||
result_type operator()(int);
|
|
||||||
};</pre>
|
|
||||||
</blockquote> </li>
|
|
||||||
|
|
||||||
<li>Always specify the <code>result</code>
|
|
||||||
specialization near the corresponding
|
|
||||||
<code>operator()</code> overload. This can make it
|
|
||||||
easier to keep the specializations in sync with the
|
|
||||||
overloads. For example:
|
|
||||||
|
|
||||||
<blockquote>
|
|
||||||
<pre>struct functor {
|
|
||||||
template<class> struct result;
|
|
||||||
|
|
||||||
template<class F>
|
|
||||||
struct result<F(int)> {
|
|
||||||
typedef int& type;
|
|
||||||
};
|
|
||||||
result<functor(int)>::type operator()(int);
|
|
||||||
|
|
||||||
template<class F>
|
|
||||||
struct result<const F(int)> {
|
|
||||||
typedef int const& type;
|
|
||||||
};
|
|
||||||
result<const functor(int)>::type operator()(int) const;
|
|
||||||
};</pre>
|
|
||||||
</blockquote> </li>
|
|
||||||
|
|
||||||
<li>Use type transformations to simplify
|
|
||||||
the <code>result</code> template specialization. For
|
|
||||||
example, the following uses
|
|
||||||
<a href="../type_traits/doc/html/index.html">Boost.TypeTraits</a>
|
|
||||||
to specialize the <code>result</code> template for
|
|
||||||
a single <code>operator()</code> that can be called on
|
|
||||||
both a const and non-const function object with
|
|
||||||
either an lvalue or rvalue argument.
|
|
||||||
|
|
||||||
<blockquote>
|
|
||||||
<pre>struct functor {
|
|
||||||
template<class> struct result;
|
|
||||||
|
|
||||||
template<class F, class T>
|
|
||||||
struct result<F(T)>
|
|
||||||
: boost::remove_cv<
|
|
||||||
typename boost::remove_reference<T>::type
|
|
||||||
>
|
|
||||||
{};
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
T operator()(T const& x) const;
|
|
||||||
};</pre>
|
|
||||||
</blockquote></li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<a name="result_of_tr1_diff">
|
|
||||||
<h3>Known differences between boost::result_of and TR1 result_of</h3>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
When using <code>decltype</code>, <code>boost::result_of</code>
|
|
||||||
ignores the TR1 protocol and instead deduces the
|
|
||||||
return type of function objects directly
|
|
||||||
via <code>decltype</code>. In most situations, users
|
|
||||||
will not notice a difference, so long as they use the
|
|
||||||
protocol correctly. The following are situations in
|
|
||||||
which the type deduced
|
|
||||||
by <code>boost::result_of</code> is known to differ depending on
|
|
||||||
whether <code>decltype</code> or the TR1 protocol is
|
|
||||||
used.
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li> TR1 protocol misusage
|
|
||||||
|
|
||||||
<p>When using the TR1
|
|
||||||
protocol, <code>boost::result_of</code> cannot
|
|
||||||
detect whether the actual type of a call to a
|
|
||||||
function object is the same as the type specified
|
|
||||||
by the protocol, which allows for the possibility
|
|
||||||
of inadvertent mismatches between the specified
|
|
||||||
type and the actual type. When
|
|
||||||
using <code>decltype</code>, these subtle bugs
|
|
||||||
may result in compilation errors. For example:</p>
|
|
||||||
|
|
||||||
<blockquote>
|
|
||||||
<pre>struct functor {
|
|
||||||
typedef short result_type;
|
|
||||||
int operator()(short);
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef BOOST_RESULT_OF_USE_DECLTYPE
|
|
||||||
|
|
||||||
BOOST_STATIC_ASSERT((
|
|
||||||
boost::is_same<boost::result_of<functor(short)>::type, int>::value
|
|
||||||
));
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
BOOST_STATIC_ASSERT((
|
|
||||||
boost::is_same<boost::result_of<functor(short)>::type, short>::value
|
|
||||||
));
|
|
||||||
|
|
||||||
#endif</pre>
|
|
||||||
</blockquote>
|
|
||||||
|
|
||||||
<p>Note that the user can
|
|
||||||
force <code>boost::result_of</code> to use the TR1
|
|
||||||
protocol even on platforms that
|
|
||||||
support <code>decltype</code> by
|
|
||||||
defining <code>BOOST_RESULT_OF_USE_TR1</code>.</p></li>
|
|
||||||
|
|
||||||
<li> Nullary function objects
|
|
||||||
|
|
||||||
<p>When using the TR1 protocol, <code>boost::result_of</code>
|
|
||||||
cannot always deduce the type of calls to
|
|
||||||
nullary function objects, in which case the
|
|
||||||
type defaults to void. When using <code>decltype</code>,
|
|
||||||
<code>boost::result_of</code> always gives the actual type of the
|
|
||||||
call expression. For example:</p>
|
|
||||||
|
|
||||||
<blockquote>
|
|
||||||
<pre>struct functor {
|
|
||||||
template<class> struct result {
|
|
||||||
typedef int type;
|
|
||||||
};
|
|
||||||
int operator()();
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef BOOST_RESULT_OF_USE_DECLTYPE
|
|
||||||
|
|
||||||
BOOST_STATIC_ASSERT((
|
|
||||||
boost::is_same<boost::result_of<functor()>::type, int>::value
|
|
||||||
));
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
BOOST_STATIC_ASSERT((
|
|
||||||
boost::is_same<boost::result_of<functor()>::type, void>::value
|
|
||||||
));
|
|
||||||
|
|
||||||
#endif</pre>
|
|
||||||
</blockquote>
|
|
||||||
|
|
||||||
<p>Note that there are some workarounds for the
|
|
||||||
nullary function problem. So long as the return
|
|
||||||
type does not vary,
|
|
||||||
<code>result_type</code> can always be used to
|
|
||||||
specify the return type regardless of arity. If the
|
|
||||||
return type does vary, then the user can
|
|
||||||
specialize <code>boost::result_of</code> itself for
|
|
||||||
nullary calls.</p></li>
|
|
||||||
|
|
||||||
<li> Non-class prvalues and cv-qualification
|
|
||||||
|
|
||||||
<p>When using the TR1
|
|
||||||
protocol, <code>boost::result_of</code> will
|
|
||||||
report the cv-qualified type specified
|
|
||||||
by <code>result_type</code> or
|
|
||||||
the <code>result</code> template regardless of
|
|
||||||
the actual cv-qualification of the call
|
|
||||||
expression. When using
|
|
||||||
<code>decltype</code>, <code>boost::result_of</code>
|
|
||||||
will report the actual type of the call expression,
|
|
||||||
which is not cv-qualified when the expression is a
|
|
||||||
non-class prvalue. For example:</p>
|
|
||||||
|
|
||||||
<blockquote>
|
|
||||||
<pre>struct functor {
|
|
||||||
template<class> struct result;
|
|
||||||
template<class F, class T> struct result<F(const T)> {
|
|
||||||
typedef const T type;
|
|
||||||
};
|
|
||||||
|
|
||||||
const short operator()(const short);
|
|
||||||
int const & operator()(int const &);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Non-prvalue call expressions work the same with or without decltype.
|
|
||||||
|
|
||||||
BOOST_STATIC_ASSERT((
|
|
||||||
boost::is_same<
|
|
||||||
boost::result_of<functor(int const &)>::type,
|
|
||||||
int const &
|
|
||||||
::value
|
|
||||||
));
|
|
||||||
|
|
||||||
// Non-class prvalue call expressions are not actually cv-qualified,
|
|
||||||
// but only the decltype-based result_of reports this accurately.
|
|
||||||
|
|
||||||
#ifdef BOOST_RESULT_OF_USE_DECLTYPE
|
|
||||||
|
|
||||||
BOOST_STATIC_ASSERT((
|
|
||||||
boost::is_same<
|
|
||||||
boost::result_of<functor(const short)>::type,
|
|
||||||
short
|
|
||||||
::value
|
|
||||||
));
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
BOOST_STATIC_ASSERT((
|
|
||||||
boost::is_same<
|
|
||||||
boost::result_of<functor(const short)>::type,
|
|
||||||
const short
|
|
||||||
::value
|
|
||||||
));
|
|
||||||
|
|
||||||
#endif</pre>
|
|
||||||
</blockquote></li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<a name="result_of_cxx11_diff">
|
|
||||||
<h3>Known differences between boost::result_of and C++11 result_of</h3>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<p>When using <code>decltype</code>, <code>boost::result_of</code>
|
|
||||||
implements most of the C++11 result_of
|
|
||||||
specification. One known exception is that
|
|
||||||
<code>boost::result_of</code> does not implement the
|
|
||||||
requirements regarding pointers to member data.</p>
|
|
||||||
|
|
||||||
<p>Created by Doug Gregor. Contributions from Daniel Walker, Eric Niebler, Michel Morin and others</p>
|
|
||||||
|
|
||||||
<h2><a name="BOOST_BINARY">Macro BOOST_BINARY</a></h2>
|
|
||||||
|
|
||||||
<p>The macro <code>BOOST_BINARY</code> is used for the
|
|
||||||
representation of binary literals. It takes as an argument
|
|
||||||
a binary number arranged as an arbitrary amount of 1s and 0s in
|
|
||||||
groupings of length 1 to 8, with groups separated
|
|
||||||
by spaces. The type of the literal yielded is determined by
|
|
||||||
the same rules as those of hex and octal
|
|
||||||
literals (<i>2.13.1p1</i>). By implementation, this macro
|
|
||||||
expands directly to an octal literal during preprocessing, so
|
|
||||||
there is no overhead at runtime and the result is useable in
|
|
||||||
any place that an octal literal would be.</p>
|
|
||||||
|
|
||||||
<p>In order to directly support binary literals with suffixes,
|
|
||||||
additional macros of the form BOOST_BINARY_XXX are also
|
|
||||||
provided, where XXX is a standard integer suffix in all capital
|
|
||||||
letters. In addition, LL and ULL suffixes may be used for representing
|
|
||||||
long long and unsigned long long types in compilers which provide
|
|
||||||
them as an extension.</p>
|
|
||||||
|
|
||||||
|
|
||||||
<p>The BOOST_BINARY family of macros resides in the header
|
|
||||||
<a
|
|
||||||
href="../../boost/utility/binary.hpp"><boost/utility/binary.hpp></a>
|
|
||||||
which is automatically included by
|
|
||||||
<a
|
|
||||||
href="../../boost/utility.hpp"><boost/utility.hpp></a>.
|
|
||||||
|
|
||||||
<p>Contributed by Matt Calabrese.</p><p>
|
|
||||||
</p><h3>Example</h3>
|
|
||||||
<blockquote>
|
|
||||||
<pre>
|
|
||||||
void foo( int );
|
|
||||||
|
|
||||||
void foo( unsigned long );
|
|
||||||
|
|
||||||
void bar()
|
|
||||||
{
|
|
||||||
int value1 = BOOST_BINARY( 100 111000 01 1 110 );
|
|
||||||
|
|
||||||
unsigned long value2 = BOOST_BINARY_UL( 100 001 ); // unsigned long
|
|
||||||
|
|
||||||
long long value3 = BOOST_BINARY_LL( 11 000 ); // long long if supported
|
|
||||||
|
|
||||||
assert( BOOST_BINARY( 10010 )
|
|
||||||
& BOOST_BINARY( 11000 )
|
|
||||||
== BOOST_BINARY( 10000 )
|
|
||||||
);
|
|
||||||
|
|
||||||
foo( BOOST_BINARY( 1010 ) ); // calls the first foo
|
|
||||||
|
|
||||||
foo( BOOST_BINARY_LU( 1010 ) ); // calls the second foo
|
|
||||||
}
|
|
||||||
</pre></blockquote>
|
|
||||||
<hr>
|
|
||||||
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan
|
|
||||||
-->04 September, 2008<!--webbot bot="Timestamp" endspan i-checksum="39369"
|
|
||||||
-->
|
|
||||||
</p>
|
|
||||||
<p>© Copyright Beman Dawes 1999-2003.</p>
|
|
||||||
<p>Distributed under the Boost Software License, Version 1.0. See
|
|
||||||
<a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a></p>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
</html>
|
||||||
|
523
value_init.htm
523
value_init.htm
@ -1,514 +1,19 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
|
<title>Boost.Utility</title>
|
||||||
<meta http-equiv="Content-Type"
|
<meta http-equiv="refresh" content="0; URL=./doc/html/index.html">
|
||||||
content="text/html; charset=iso-8859-1">
|
|
||||||
<title>value_initialized</title>
|
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body vlink="#800080" link="#0000ff" text="#000000" bgcolor="#ffffff">
|
<body>
|
||||||
|
Automatic redirection failed, please go to
|
||||||
<h2><img src="../../boost.png" width="276" height="86">
|
<a href="./doc/html/utility/utilities/value_init.html">./doc/html/utility/utilities/value_init.html</a>
|
||||||
Header <<a href="../../boost/utility/value_init.hpp">boost/utility/value_init.hpp</a>>
|
<hr>
|
||||||
</h2>
|
<tt>
|
||||||
|
Boost.Utility<br>
|
||||||
<h2>Contents</h2>
|
<br>
|
||||||
|
Distributed under the Boost Software License, Version 1.0.
|
||||||
<dl>
|
(See accompanying file LICENSE_1_0.txt or copy at
|
||||||
<dt><a href="#rationale">Rationale</a></dt>
|
<a href=http://www.boost.org/LICENSE_1_0.txt>http://www.boost.org/LICENSE_1_0.txt</a>) <br>
|
||||||
<dt><a href="#intro">Introduction</a></dt>
|
<br>
|
||||||
<dt><a href="#details">Details</a></dt>
|
</tt>
|
||||||
</dl>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><a href="#valueinit">value-initialization</a></li>
|
|
||||||
<li><a href="#valueinitsyn">value-initialization syntax</a></li>
|
|
||||||
<li><a href="#compiler_issues">compiler issues</a></li>
|
|
||||||
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<dl class="page-index">
|
|
||||||
<dt><a href="#types">Types and objects</a></dt>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><a href="#val_init"><code>template class value_initialized<T></code></a></li>
|
|
||||||
<li><a href="#initialized"><code>template class initialized<T></code></a></li>
|
|
||||||
<li><a href="#initialized_value"><code>initialized_value</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. The template <code>value_initialized</code> provides
|
|
||||||
a solution with consistent syntax for value initialization of scalar,
|
|
||||||
union and class types.
|
|
||||||
Moreover, <code>value_initialized</code> offers a workaround to various
|
|
||||||
compiler issues regarding value-initialization.
|
|
||||||
|
|
||||||
Furthermore, a <code>const</code> object, <code>initialized_value</code> is provided,
|
|
||||||
to avoid repeating the type name when retrieving the value from a
|
|
||||||
<code>value_initialized<T></code> object.
|
|
||||||
<br>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h2><a name="intro"></a>Introduction</h2>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
There are various ways to initialize a variable, in C++. The following
|
|
||||||
declarations all <em>may</em> have a local variable initialized to its default
|
|
||||||
value:
|
|
||||||
<pre>
|
|
||||||
T1 var1;
|
|
||||||
T2 var2 = 0;
|
|
||||||
T3 var3 = {};
|
|
||||||
T4 var4 = T4();
|
|
||||||
</pre>
|
|
||||||
Unfortunately, whether or not any of those declarations correctly
|
|
||||||
initialize the variable very much depends on its type. The first
|
|
||||||
declaration is valid for any <a href="http://www.sgi.com/tech/stl/DefaultConstructible.html">
|
|
||||||
DefaultConstructible</a> type (by definition).
|
|
||||||
However, it does not always do an initialization!
|
|
||||||
It correctly initializes the variable when it's an instance of a
|
|
||||||
class, and the author of the class has provided a proper default
|
|
||||||
constructor. On the other hand, the value of <code>var1</code> is <em>indeterminate</em> when
|
|
||||||
its type is an arithmetic type, like <code>int</code>, <code>float</code>, or <code>char</code>.
|
|
||||||
An arithmetic variable
|
|
||||||
is of course initialized properly by the second declaration, <code>T2
|
|
||||||
var2 = 0</code>. But this initialization form usually won't work for a
|
|
||||||
class type (unless the class was especially written to support being
|
|
||||||
initialized that way). The third form, <code>T3 var3 = {}</code>
|
|
||||||
initializes an aggregate, typically a "C-style" <code>struct</code> or a "C-style" array.
|
|
||||||
However, the syntax is not allowed for a class that has an explicitly declared
|
|
||||||
constructor. (But watch out for an upcoming C++ language change,
|
|
||||||
by Bjarne Stroustrup et al [<a href="#references">1</a>]!)
|
|
||||||
The fourth form is the most generic form of them, as it
|
|
||||||
can be used to initialize arithmetic types, class types, aggregates, pointers, and
|
|
||||||
other types. The declaration, <code>T4 var4 = T4()</code>, should be read
|
|
||||||
as follows: First a temporary object is created, by <code>T4()</code>.
|
|
||||||
This object is <a href="#valueinit">value-initialized</a>. Next the temporary
|
|
||||||
object is copied to the named variable, <code>var4</code>. Afterwards, the temporary
|
|
||||||
is destroyed. While the copying and the destruction are likely to
|
|
||||||
be optimized away, C++ still requires the type <code>T4</code> to be
|
|
||||||
<a href="CopyConstructible.html">CopyConstructible</a>.
|
|
||||||
(So <code>T4</code> needs to be <em>both</em> DefaultConstructible <em>and</em> CopyConstructible.)
|
|
||||||
A class may not be CopyConstructible, for example because it may have a
|
|
||||||
private and undefined copy constructor,
|
|
||||||
or because it may be derived from <a href="utility.htm#Class_noncopyable">boost::noncopyable</a>.
|
|
||||||
Scott Meyers [<a href="#references">2</a>] explains why a class would be defined like that.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
There is another, less obvious disadvantage to the fourth form, <code>T4 var4 = T4()</code>:
|
|
||||||
It suffers from various <a href="#compiler_issues">compiler issues</a>, causing
|
|
||||||
a variable to be left uninitialized in some compiler specific cases.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
The template <a href="#val_init"><code>value_initialized</code></a>
|
|
||||||
offers a generic way to initialize
|
|
||||||
an object, like <code>T4 var4 = T4()</code>, but without requiring its type
|
|
||||||
to be CopyConstructible. And it offers a workaround to those compiler issues
|
|
||||||
regarding value-initialization as well! It allows getting an initialized
|
|
||||||
variable of any type; it <em>only</em> requires the type to be DefaultConstructible.
|
|
||||||
A properly <em>value-initialized</em> object of type <code>T</code> is
|
|
||||||
constructed by the following declaration:
|
|
||||||
<pre>
|
|
||||||
value_initialized<T> var;
|
|
||||||
</pre>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
The template <a href="#initialized"><code>initialized</code></a>
|
|
||||||
offers both value-initialization and direct-initialization.
|
|
||||||
It is especially useful as a data member type, allowing the very same object
|
|
||||||
to be either direct-initialized or value-initialized.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
The <code>const</code> object <a href="#initialized_value"><code>initialized_value</code></a>
|
|
||||||
allows value-initializing a variable as follows:
|
|
||||||
<pre>
|
|
||||||
T var = initialized_value ;
|
|
||||||
</pre>
|
|
||||||
This form of initialization is semantically equivalent to <code>T4 var4 = T4()</code>,
|
|
||||||
but robust against the aforementioned compiler issues.
|
|
||||||
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h2><a name="details"></a>Details</h2>
|
|
||||||
<p>The C++ standard [<a href="#references">3</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">4</a>] types are zero-initialized, while non-POD 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 value-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, [dcl.init], 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://www.open-std.org/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://www.open-std.org/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>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-initialized</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(*)()</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>This is the solution as it was supplied by earlier versions of the
|
|
||||||
<code>value_initialized<T></code> template
|
|
||||||
class. Unfortunately this approach suffered from various compiler issues.</p>
|
|
||||||
|
|
||||||
<h4><a name="compiler_issues">compiler issues</a> </h4>
|
|
||||||
|
|
||||||
Various compilers haven't yet fully implemented value-initialization.
|
|
||||||
So when an object should be <em>value-initialized</em> (according to the C++ Standard),
|
|
||||||
it <em>may</em> in practice still be left uninitialized, because of those
|
|
||||||
compiler issues! It's hard to make a general statement on what those issues
|
|
||||||
are like, because they depend on the compiler you are using, its version number,
|
|
||||||
and the type of object you would like to have value-initialized.
|
|
||||||
All compilers we have tested so far support value-initialization for arithmetic types properly.
|
|
||||||
However, various compilers may leave some types of <em>aggregates</em> uninitialized, when they
|
|
||||||
should be value-initialized. Value-initialization of objects of a pointer-to-member type may also
|
|
||||||
go wrong on various compilers.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
At the moment of writing, May 2010, the following reported issues regarding
|
|
||||||
value-initialization are still there in current compiler releases:
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<a href="https://connect.microsoft.com/VisualStudio/feedback/details/100744">
|
|
||||||
Microsoft Visual Studio Feedback ID 100744, Value-initialization in new-expression</a>
|
|
||||||
<br>Reported by Pavel Kuznetsov (MetaCommunications Engineering), 2005
|
|
||||||
</li><li>
|
|
||||||
<a href="http://connect.microsoft.com/VisualStudio/feedback/details/484295">
|
|
||||||
Microsoft Visual Studio Feedback ID 484295, VC++ does not value-initialize members of derived classes without user-declared constructor</a>
|
|
||||||
<br>Reported by Sylvester Hesp, 2009
|
|
||||||
</li><li>
|
|
||||||
<a href="https://connect.microsoft.com/VisualStudio/feedback/details/499606">
|
|
||||||
Microsoft Visual Studio Feedback ID 499606, Presence of copy constructor breaks member class initialization</a>
|
|
||||||
<br>Reported by Alex Vakulenko, 2009
|
|
||||||
</li><li>
|
|
||||||
<a href="http://qc.embarcadero.com/wc/qcmain.aspx?d=83751">
|
|
||||||
Embarcadero/C++Builder Report 83751, Value-initialization: arrays should have each element value-initialized</a>
|
|
||||||
<br>Reported by Niels Dekker (LKEB), 2010
|
|
||||||
</li><li>
|
|
||||||
<a href="http://qc.embarcadero.com/wc/qcmain.aspx?d=83851">
|
|
||||||
Embarcadero/C++Builder Report 83851, Value-initialized temporary triggers internal backend error C1798</a>
|
|
||||||
<br>Reported by Niels Dekker, 2010
|
|
||||||
</li><li>
|
|
||||||
<a href="http://qc.embarcadero.com/wc/qcmain.aspx?d=84279">
|
|
||||||
Embarcadero/C++Builder Report 84279, Internal compiler error (F1004), value-initializing member function pointer by "new T()"</a>
|
|
||||||
<br>Reported by Niels Dekker, 2010
|
|
||||||
</li><li>
|
|
||||||
Sun CR 6947016, Sun 5.10 may fail to value-initialize an object of a non-POD aggregate.
|
|
||||||
<br>Reported to Steve Clamage by Niels Dekker, 2010
|
|
||||||
</li><li>
|
|
||||||
IBM's XL V10.1 and V11.1 may fail to value-initialize a temporary of a non-POD aggregate.
|
|
||||||
<br>Reported to Michael Wong by Niels Dekker, 2010
|
|
||||||
</li><li>
|
|
||||||
Intel support issue 589832, Attempt to value-initialize pointer-to-member triggers internal error
|
|
||||||
on Intel 11.1.
|
|
||||||
<br>Reported by John Maddock, 2010
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
Note that all known GCC issues regarding value-initialization are
|
|
||||||
fixed with GCC version 4.4, including
|
|
||||||
<a href="http://gcc.gnu.org/bugzilla/show_bug.cgi?id=30111">GCC Bug 30111</a>.
|
|
||||||
Clang also has completely implemented value-initialization, as far as we know,
|
|
||||||
now that <a href="http://llvm.org/bugs/show_bug.cgi?id=7139">Clang Bug 7139</a> is fixed.
|
|
||||||
</p><p>
|
|
||||||
|
|
||||||
New versions of <code>value_initialized</code>
|
|
||||||
(Boost release version 1.35 or higher)
|
|
||||||
offer a workaround to these issues: <code>value_initialized</code> may now clear
|
|
||||||
its internal data, prior to constructing the object that it contains. It will do
|
|
||||||
so for those compilers that need to have such a workaround, based on the
|
|
||||||
<a href="../config/doc/html/boost_config/boost_macro_reference.html#boost_config.boost_macro_reference.macros_that_describe_defects"
|
|
||||||
>compiler defect macro</a> BOOST_NO_COMPLETE_VALUE_INITIALIZATION.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h2><a name="types"></a>Types and objects</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 &() const { return x ; }
|
|
||||||
<br> operator T&() { return x ; }
|
|
||||||
<br> T const &data() const { return x ; }
|
|
||||||
<br> T& data() { return x ; }
|
|
||||||
<br> void swap( value_initialized& );
|
|
||||||
<br>
|
|
||||||
<br> private :
|
|
||||||
<br> <i>unspecified</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>template<class T>
|
|
||||||
<br>void swap ( value_initialized<T>& lhs, value_initialized<T>& rhs )
|
|
||||||
<br>{
|
|
||||||
<br> lhs.swap(rhs) ;
|
|
||||||
<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>
|
|
||||||
|
|
||||||
<p>When <code>T</code> is a <em>Swappable</em> type, <code>value_initialized<T></code>
|
|
||||||
is swappable as well, by calling its <code>swap</code> member function
|
|
||||||
as well as by calling <code>boost::swap</code>.</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>The <code>value_initialized</code> implementation of Boost version 1.40.0 and older
|
|
||||||
allowed <i>non-const</i> access to the wrapped object, from a constant wrapper,
|
|
||||||
both by its conversion operator and its <code>data()</code> member function. For example:</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 was that some compilers
|
|
||||||
didn'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>The current version of <code>value_initialized</code> no longer has this obscure behavior.
|
|
||||||
As compilers nowadays widely support overloading the conversion operator by having a <code>const</code> and a <code>non-const</code> version, we have decided to fix the issue accordingly. So the current version supports the idea of logical constness.
|
|
||||||
<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 (as was supported by previous
|
|
||||||
versions of <code>value_initialized</code>)
|
|
||||||
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>
|
|
||||||
|
|
||||||
<h2><a name="initialized"><code>template class initialized<T></code></a></h2>
|
|
||||||
|
|
||||||
<pre>namespace boost {<br><br>template<class T><br>class initialized<br>{
|
|
||||||
<br> public :
|
|
||||||
<br> initialized() : x() {}
|
|
||||||
<br> explicit initialized(T const & arg) : x(arg) {}
|
|
||||||
<br> operator T const &() const;
|
|
||||||
<br> operator T&();
|
|
||||||
<br> T const &data() const;
|
|
||||||
<br> T& data();
|
|
||||||
<br> void swap( initialized& );
|
|
||||||
<br>
|
|
||||||
<br> private :
|
|
||||||
<br> <i>unspecified</i> x ;
|
|
||||||
<br>} ;
|
|
||||||
<br>
|
|
||||||
<br>template<class T>
|
|
||||||
<br>T const& get ( initialized<T> const& x );
|
|
||||||
<br>
|
|
||||||
<br>template<class T>
|
|
||||||
<br>T& get ( initialized<T>& x );
|
|
||||||
<br>
|
|
||||||
<br>template<class T>
|
|
||||||
<br>void swap ( initialized<T>& lhs, initialized<T>& rhs );
|
|
||||||
<br>
|
|
||||||
<br>} // namespace boost
|
|
||||||
<br></pre>
|
|
||||||
|
|
||||||
The template class <code>boost::initialized<T></code> supports both value-initialization
|
|
||||||
and direct-initialization, so its interface is a superset of the interface
|
|
||||||
of <code>value_initialized<T></code>: Its default-constructor
|
|
||||||
value-initializes the wrapped object just like the default-constructor of
|
|
||||||
<code>value_initialized<T></code>, but <code>boost::initialized<T></code>
|
|
||||||
also offers an extra <code>explicit</code>
|
|
||||||
constructor, which direct-initializes the wrapped object by the specified value.
|
|
||||||
<p>
|
|
||||||
|
|
||||||
<code>initialized<T></code> is especially useful when the wrapped
|
|
||||||
object must be either value-initialized or direct-initialized, depending on
|
|
||||||
runtime conditions. For example, <code>initialized<T></code> could
|
|
||||||
hold the value of a data member that may be value-initialized by some
|
|
||||||
constructors, and direct-initialized by others.
|
|
||||||
On the other hand, if it is known beforehand that the
|
|
||||||
object must <i>always</i> be value-initialized, <code>value_initialized<T></code>
|
|
||||||
may be preferable. And if the object must always be
|
|
||||||
direct-initialized, none of the two wrappers really needs to be used.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
|
|
||||||
<h2><a name="initialized_value"><code>initialized_value</code></a></h2>
|
|
||||||
|
|
||||||
<pre>
|
|
||||||
namespace boost {
|
|
||||||
class initialized_value_t
|
|
||||||
{
|
|
||||||
public :
|
|
||||||
template <class T> operator T() const ;
|
|
||||||
};
|
|
||||||
|
|
||||||
initialized_value_t const initialized_value = {} ;
|
|
||||||
|
|
||||||
} // namespace boost
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<code>initialized_value</code> provides a convenient way to get
|
|
||||||
an initialized value: its conversion operator provides an appropriate
|
|
||||||
<em>value-initialized</em> object for any CopyConstructible type.
|
|
||||||
|
|
||||||
Suppose you need to have an initialized variable of type <code>T</code>.
|
|
||||||
You could do it as follows:
|
|
||||||
<pre>
|
|
||||||
T var = T();
|
|
||||||
</pre>
|
|
||||||
But as mentioned before, this form suffers from various compiler issues.
|
|
||||||
The template <code>value_initialized</code> offers a workaround:
|
|
||||||
<pre>
|
|
||||||
T var = get( value_initialized<T>() );
|
|
||||||
</pre>
|
|
||||||
Unfortunately both forms repeat the type name, which
|
|
||||||
is rather short now (<code>T</code>), but could of course be
|
|
||||||
more like <code>Namespace::Template<Arg>::Type</code>.
|
|
||||||
Instead, one could use <code>initialized_value</code> as follows:
|
|
||||||
<pre>
|
|
||||||
T var = initialized_value ;
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<h3><a name="references">References</a></h3>
|
|
||||||
[1] Bjarne Stroustrup, Gabriel Dos Reis, and J. Stephen Adamczyk wrote
|
|
||||||
various papers, proposing to extend the support for brace-enclosed <em>initializer lists</em>
|
|
||||||
in the next version of C++.
|
|
||||||
This would allow a variable <code>var</code> of any DefaultConstructible type
|
|
||||||
<code>T</code> to be <em>value-initialized</em> by doing <code>T var = {}</code>.
|
|
||||||
The papers are listed at Bjarne's web page,
|
|
||||||
<a href="http://www.research.att.com/~bs/WG21.html">My C++ Standards committee papers</a> <br>
|
|
||||||
[2] Scott Meyers, Effective C++, Third Edition, item 6,
|
|
||||||
<em>Explicitly disallow the use of compiler-generated functions you do not want</em>,
|
|
||||||
<a href="http://www.aristeia.com/books.html">Scott Meyers: Books and CDs</a> <br>
|
|
||||||
[3] The C++ Standard, Second edition (2003), ISO/IEC 14882:2003 <br>
|
|
||||||
[4] POD stands for "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örn Karlsson who carefully edited and completed this documentation.
|
|
||||||
|
|
||||||
<p>value_initialized was reimplemented by Fernando Cacciola and Niels Dekker
|
|
||||||
for Boost release version 1.35 (2008), offering a workaround to various compiler issues.
|
|
||||||
</p>
|
|
||||||
<p><code>boost::initialized</code> was very much inspired by feedback from Edward Diener and
|
|
||||||
Jeffrey Hellrung.
|
|
||||||
</p>
|
|
||||||
<p>initialized_value was written by Niels Dekker, and added to Boost release version 1.36 (2008).
|
|
||||||
</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>.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
<p>Revised 30 May 2010</p>
|
|
||||||
|
|
||||||
<p>© Copyright Fernando Cacciola, 2002 - 2010.</p>
|
|
||||||
|
|
||||||
<p>Distributed under the Boost Software License, Version 1.0. See
|
|
||||||
<a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a></p>
|
|
||||||
|
|
||||||
<br>
|
|
||||||
<br>
|
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user