Merge branch 'develop'

This commit is contained in:
Andrzej Krzemienski
2014-05-13 21:12:44 +02:00
39 changed files with 2598 additions and 1089 deletions

15
README.md Normal file
View File

@ -0,0 +1,15 @@
optional
========
A library for representing optional (nullable) objects in C++.
```cpp
optional<int> readInt(); // this function may return either an int or a not-an-int
if (optional<int> oi = readInt()) // did I get a real int
cout << "my int is: " << *oi; // use my int
else
cout << "I have no int";
```
For more information refer to the documentation provided with this library.

View File

@ -10,6 +10,7 @@
# Quickbook
# -----------------------------------------------------------------------------
using boostbook ;
import quickbook ;
path-constant images : html ;
@ -24,7 +25,6 @@ boostbook standalone
optional
:
<xsl:param>boost.root=../../../..
<xsl:param>html.stylesheet=boostbook.css
<xsl:param>toc.max.depth=2
<xsl:param>toc.section.depth=2
<xsl:param>chunk.section.depth=1

View File

@ -14,4 +14,54 @@
The implementation uses `type_traits/alignment_of.hpp` and
`type_traits/type_with_alignment.hpp`
[section Optional Reference Binding]
On compilers that do not conform to Standard C++ rules of reference binding, operations on optional references might give adverse results: rather than binding a reference to a designated object they may create an unexpected temporary and bind to it. Compilers known to have these deficiencies include GCC versions 4.2, 4.3, 4.4, 4.5; QCC 4.4.2; MSVC versions 8.0, 9.0, 10.0, 11.0, 12.0. On these compilers prefer using direct-initialization and copy assignment of optional references to copy-initialization and assignment from `T&`:
const int i = 0;
optional<const int&> or1;
optional<const int&> or2 = i; // not portable
or1 = i; // not portable
optional<const int&> or3(i); // portable
or1 = optional<const int&>(i); // portable
In order to check if your compiler correctly implements reference binding use this test program.
#include <cassert>
const int global_i = 0;
struct TestingReferenceBinding
{
TestingReferenceBinding(const int& ii)
{
assert(&ii == &global_i);
}
void operator=(const int& ii)
{
assert(&ii == &global_i);
}
void operator=(int&&) // remove this if your compiler doesn't have rvalue refs
{
assert(false);
}
};
int main()
{
const int& iref = global_i;
assert(&iref == &global_i);
TestingReferenceBinding ttt = global_i;
ttt = global_i;
TestingReferenceBinding ttt2 = iref;
ttt2 = iref;
}
[endsect]
[endsect]

View File

@ -1,14 +0,0 @@
index.html
boost_optional/development.html
boost_optional/synopsis.html
boost_optional/detailed_semantics.html
boost_optional/examples.html
boost_optional/optional_references.html
boost_optional/rebinding_semantics_for_assignment_of_optional_references.html
boost_optional/in_place_factories.html
boost_optional/a_note_about_optional_bool_.html
boost_optional/exception_safety_guarantees.html
boost_optional/type_requirements.html
boost_optional/implementation_notes.html
boost_optional/dependencies_and_portability.html
boost_optional/acknowledgments.html

View File

@ -2,8 +2,8 @@
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>A note about optional&lt;bool&gt;</title>
<link rel="stylesheet" href="../boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.77.1">
<link rel="stylesheet" href="../../../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.78.1">
<link rel="home" href="../index.html" title="Chapter&#160;1.&#160;Boost.Optional">
<link rel="up" href="../index.html" title="Chapter&#160;1.&#160;Boost.Optional">
<link rel="prev" href="in_place_factories.html" title="In-Place Factories">
@ -32,7 +32,7 @@
be used with special caution and consideration.
</p>
<p>
First, it is functionally similar to a tristate boolean (false,maybe,true)
First, it is functionally similar to a tristate boolean (false, maybe, true)
&#8212;such as <a href="../../../../../doc/html/tribool.html" target="_top">boost::tribool</a>&#8212;
except that in a tristate boolean, the maybe state <span class="underline">represents
a valid value</span>, unlike the corresponding state of an uninitialized
@ -42,10 +42,11 @@
needed.
</p>
<p>
Second, <code class="computeroutput"><span class="identifier">optional</span><span class="special">&lt;&gt;</span></code>
provides an implicit conversion to <code class="computeroutput"><span class="keyword">bool</span></code>.
This conversion refers to the initialization state and not to the contained
value. Using <code class="computeroutput"><span class="identifier">optional</span><span class="special">&lt;</span><span class="keyword">bool</span><span class="special">&gt;</span></code> can
Second, although <code class="computeroutput"><span class="identifier">optional</span><span class="special">&lt;&gt;</span></code>
provides a contextual conversion to <code class="computeroutput"><span class="keyword">bool</span></code>
in C++11, this falls back to an implicit conversion on older compilers. This
conversion refers to the initialization state and not to the contained value.
Using <code class="computeroutput"><span class="identifier">optional</span><span class="special">&lt;</span><span class="keyword">bool</span><span class="special">&gt;</span></code> can
lead to subtle errors due to the implicit <code class="computeroutput"><span class="keyword">bool</span></code>
conversion:
</p>
@ -67,10 +68,33 @@
takes an <code class="computeroutput"><span class="keyword">int</span></code> instead, it won't
compile).
</p>
<p>
Third, mixed comparisons with <code class="computeroutput"><span class="keyword">bool</span></code>
work differently than similar mixed comparisons between pointers and <code class="computeroutput"><span class="keyword">bool</span></code>, so the results might surprise you:
</p>
<pre class="programlisting"><span class="identifier">optional</span><span class="special">&lt;</span><span class="keyword">bool</span><span class="special">&gt;</span> <span class="identifier">oEmpty</span><span class="special">(</span><span class="identifier">none</span><span class="special">),</span> <span class="identifier">oTrue</span><span class="special">(</span><span class="keyword">true</span><span class="special">),</span> <span class="identifier">oFalse</span><span class="special">(</span><span class="keyword">false</span><span class="special">);</span>
<span class="keyword">if</span> <span class="special">(</span><span class="identifier">oEmpty</span> <span class="special">==</span> <span class="identifier">none</span><span class="special">);</span> <span class="comment">// renders true</span>
<span class="keyword">if</span> <span class="special">(</span><span class="identifier">oEmpty</span> <span class="special">==</span> <span class="keyword">false</span><span class="special">);</span> <span class="comment">// renders false!</span>
<span class="keyword">if</span> <span class="special">(</span><span class="identifier">oEmpty</span> <span class="special">==</span> <span class="keyword">true</span><span class="special">);</span> <span class="comment">// renders false!</span>
<span class="keyword">if</span> <span class="special">(</span><span class="identifier">oFalse</span> <span class="special">==</span> <span class="identifier">none</span><span class="special">);</span> <span class="comment">// renders false</span>
<span class="keyword">if</span> <span class="special">(</span><span class="identifier">oFalse</span> <span class="special">==</span> <span class="keyword">false</span><span class="special">);</span> <span class="comment">// renders true!</span>
<span class="keyword">if</span> <span class="special">(</span><span class="identifier">oFalse</span> <span class="special">==</span> <span class="keyword">true</span><span class="special">);</span> <span class="comment">// renders false</span>
<span class="keyword">if</span> <span class="special">(</span><span class="identifier">oTrue</span> <span class="special">==</span> <span class="identifier">none</span><span class="special">);</span> <span class="comment">// renders false</span>
<span class="keyword">if</span> <span class="special">(</span><span class="identifier">oTrue</span> <span class="special">==</span> <span class="keyword">false</span><span class="special">);</span> <span class="comment">// renders false</span>
<span class="keyword">if</span> <span class="special">(</span><span class="identifier">oTrue</span> <span class="special">==</span> <span class="keyword">true</span><span class="special">);</span> <span class="comment">// renders true</span>
</pre>
<p>
In other words, for <code class="computeroutput"><span class="identifier">optional</span><span class="special">&lt;&gt;</span></code>, the following assertion does not hold:
</p>
<pre class="programlisting"><span class="identifier">assert</span><span class="special">((</span><span class="identifier">opt</span> <span class="special">==</span> <span class="keyword">false</span><span class="special">)</span> <span class="special">==</span> <span class="special">(!</span><span class="identifier">opt</span><span class="special">));</span>
</pre>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2003-2007 Fernando Luis Cacciola Carballal<p>
<td align="right"><div class="copyright-footer">Copyright &#169; 2003-2007 Fernando Luis Cacciola Carballal<br>Copyright &#169; 2014 Andrzej Krzemie&#324;ski<p>
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" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
</p>

View File

@ -2,8 +2,8 @@
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Acknowledgments</title>
<link rel="stylesheet" href="../boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.77.1">
<link rel="stylesheet" href="../../../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.78.1">
<link rel="home" href="../index.html" title="Chapter&#160;1.&#160;Boost.Optional">
<link rel="up" href="../index.html" title="Chapter&#160;1.&#160;Boost.Optional">
<link rel="prev" href="dependencies_and_portability.html" title="Dependencies and Portability">
@ -111,7 +111,7 @@
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2003-2007 Fernando Luis Cacciola Carballal<p>
<td align="right"><div class="copyright-footer">Copyright &#169; 2003-2007 Fernando Luis Cacciola Carballal<br>Copyright &#169; 2014 Andrzej Krzemie&#324;ski<p>
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" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
</p>

View File

@ -2,11 +2,11 @@
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Dependencies and Portability</title>
<link rel="stylesheet" href="../boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.77.1">
<link rel="stylesheet" href="../../../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.78.1">
<link rel="home" href="../index.html" title="Chapter&#160;1.&#160;Boost.Optional">
<link rel="up" href="../index.html" title="Chapter&#160;1.&#160;Boost.Optional">
<link rel="prev" href="implementation_notes.html" title="Implementation Notes">
<link rel="prev" href="type_requirements.html" title="Type requirements">
<link rel="next" href="acknowledgments.html" title="Acknowledgments">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
@ -20,21 +20,85 @@
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="implementation_notes.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="acknowledgments.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
<a accesskey="p" href="type_requirements.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="acknowledgments.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="boost_optional.dependencies_and_portability"></a><a class="link" href="dependencies_and_portability.html" title="Dependencies and Portability">Dependencies
and Portability</a>
</h2></div></div></div>
<div class="toc"><dl class="toc"><dt><span class="section"><a href="dependencies_and_portability.html#boost_optional.dependencies_and_portability.optional_reference_binding">Optional
Reference Binding</a></span></dt></dl></div>
<p>
The implementation uses <code class="computeroutput"><span class="identifier">type_traits</span><span class="special">/</span><span class="identifier">alignment_of</span><span class="special">.</span><span class="identifier">hpp</span></code> and
<code class="computeroutput"><span class="identifier">type_traits</span><span class="special">/</span><span class="identifier">type_with_alignment</span><span class="special">.</span><span class="identifier">hpp</span></code>
</p>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="boost_optional.dependencies_and_portability.optional_reference_binding"></a><a class="link" href="dependencies_and_portability.html#boost_optional.dependencies_and_portability.optional_reference_binding" title="Optional Reference Binding">Optional
Reference Binding</a>
</h3></div></div></div>
<p>
On compilers that do not conform to Standard C++ rules of reference binding,
operations on optional references might give adverse results: rather than
binding a reference to a designated object they may create an unexpected
temporary and bind to it. Compilers known to have these deficiencies include
GCC versions 4.2, 4.3, 4.4, 4.5; QCC 4.4.2; MSVC versions 8.0, 9.0, 10.0,
11.0, 12.0. On these compilers prefer using direct-initialization and copy
assignment of optional references to copy-initialization and assignment from
<code class="computeroutput"><span class="identifier">T</span><span class="special">&amp;</span></code>:
</p>
<pre class="programlisting"><span class="keyword">const</span> <span class="keyword">int</span> <span class="identifier">i</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span>
<span class="identifier">optional</span><span class="special">&lt;</span><span class="keyword">const</span> <span class="keyword">int</span><span class="special">&amp;&gt;</span> <span class="identifier">or1</span><span class="special">;</span>
<span class="identifier">optional</span><span class="special">&lt;</span><span class="keyword">const</span> <span class="keyword">int</span><span class="special">&amp;&gt;</span> <span class="identifier">or2</span> <span class="special">=</span> <span class="identifier">i</span><span class="special">;</span> <span class="comment">// not portable</span>
<span class="identifier">or1</span> <span class="special">=</span> <span class="identifier">i</span><span class="special">;</span> <span class="comment">// not portable</span>
<span class="identifier">optional</span><span class="special">&lt;</span><span class="keyword">const</span> <span class="keyword">int</span><span class="special">&amp;&gt;</span> <span class="identifier">or3</span><span class="special">(</span><span class="identifier">i</span><span class="special">);</span> <span class="comment">// portable</span>
<span class="identifier">or1</span> <span class="special">=</span> <span class="identifier">optional</span><span class="special">&lt;</span><span class="keyword">const</span> <span class="keyword">int</span><span class="special">&amp;&gt;(</span><span class="identifier">i</span><span class="special">);</span> <span class="comment">// portable</span>
</pre>
<p>
In order to check if your compiler correctly implements reference binding
use this test program.
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">cassert</span><span class="special">&gt;</span>
<span class="keyword">const</span> <span class="keyword">int</span> <span class="identifier">global_i</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span>
<span class="keyword">struct</span> <span class="identifier">TestingReferenceBinding</span>
<span class="special">{</span>
<span class="identifier">TestingReferenceBinding</span><span class="special">(</span><span class="keyword">const</span> <span class="keyword">int</span><span class="special">&amp;</span> <span class="identifier">ii</span><span class="special">)</span>
<span class="special">{</span>
<span class="identifier">assert</span><span class="special">(&amp;</span><span class="identifier">ii</span> <span class="special">==</span> <span class="special">&amp;</span><span class="identifier">global_i</span><span class="special">);</span>
<span class="special">}</span>
<span class="keyword">void</span> <span class="keyword">operator</span><span class="special">=(</span><span class="keyword">const</span> <span class="keyword">int</span><span class="special">&amp;</span> <span class="identifier">ii</span><span class="special">)</span>
<span class="special">{</span>
<span class="identifier">assert</span><span class="special">(&amp;</span><span class="identifier">ii</span> <span class="special">==</span> <span class="special">&amp;</span><span class="identifier">global_i</span><span class="special">);</span>
<span class="special">}</span>
<span class="keyword">void</span> <span class="keyword">operator</span><span class="special">=(</span><span class="keyword">int</span><span class="special">&amp;&amp;)</span> <span class="comment">// remove this if your compiler doesn't have rvalue refs</span>
<span class="special">{</span>
<span class="identifier">assert</span><span class="special">(</span><span class="keyword">false</span><span class="special">);</span>
<span class="special">}</span>
<span class="special">};</span>
<span class="keyword">int</span> <span class="identifier">main</span><span class="special">()</span>
<span class="special">{</span>
<span class="keyword">const</span> <span class="keyword">int</span><span class="special">&amp;</span> <span class="identifier">iref</span> <span class="special">=</span> <span class="identifier">global_i</span><span class="special">;</span>
<span class="identifier">assert</span><span class="special">(&amp;</span><span class="identifier">iref</span> <span class="special">==</span> <span class="special">&amp;</span><span class="identifier">global_i</span><span class="special">);</span>
<span class="identifier">TestingReferenceBinding</span> <span class="identifier">ttt</span> <span class="special">=</span> <span class="identifier">global_i</span><span class="special">;</span>
<span class="identifier">ttt</span> <span class="special">=</span> <span class="identifier">global_i</span><span class="special">;</span>
<span class="identifier">TestingReferenceBinding</span> <span class="identifier">ttt2</span> <span class="special">=</span> <span class="identifier">iref</span><span class="special">;</span>
<span class="identifier">ttt2</span> <span class="special">=</span> <span class="identifier">iref</span><span class="special">;</span>
<span class="special">}</span>
</pre>
</div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2003-2007 Fernando Luis Cacciola Carballal<p>
<td align="right"><div class="copyright-footer">Copyright &#169; 2003-2007 Fernando Luis Cacciola Carballal<br>Copyright &#169; 2014 Andrzej Krzemie&#324;ski<p>
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" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
</p>
@ -42,7 +106,7 @@
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="implementation_notes.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="acknowledgments.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
<a accesskey="p" href="type_requirements.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="acknowledgments.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>

View File

@ -2,8 +2,8 @@
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Detailed Semantics</title>
<link rel="stylesheet" href="../boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.77.1">
<link rel="stylesheet" href="../../../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.78.1">
<link rel="home" href="../index.html" title="Chapter&#160;1.&#160;Boost.Optional">
<link rel="up" href="../index.html" title="Chapter&#160;1.&#160;Boost.Optional">
<link rel="prev" href="synopsis.html" title="Synopsis">
@ -72,7 +72,7 @@
<span class="inlinemediaobject"><img src="../images/space.png" alt="space"></span>
</p>
<a name="reference_optional_constructor"></a><div class="blockquote"><blockquote class="blockquote"><p>
<code class="computeroutput"><span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</span><span class="identifier">optional</span><span class="special">();</span></code>
<code class="computeroutput"><span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</span><span class="identifier">optional</span><span class="special">()</span> <span class="keyword">noexcept</span><span class="special">;</span></code>
</p></blockquote></div>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
@ -82,11 +82,7 @@
<span class="bold"><strong>Postconditions:</strong></span> <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> is <span class="underline">uninitialized</span>.
</li>
<li class="listitem">
<span class="bold"><strong>Throws:</strong></span> Nothing.
</li>
<li class="listitem">
Notes: T's default constructor <span class="underline">is not</span>
called.
<span class="bold"><strong>Notes:</strong></span> T's default constructor <span class="underline">is not</span> called.
</li>
<li class="listitem">
<span class="bold"><strong>Example:</strong></span>
@ -99,7 +95,7 @@
<span class="inlinemediaobject"><img src="../images/space.png" alt="space"></span>
</p>
<a name="reference_optional_constructor_none_t"></a><div class="blockquote"><blockquote class="blockquote"><p>
<code class="computeroutput"><span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</span><span class="identifier">optional</span><span class="special">(</span> <span class="identifier">none_t</span> <span class="special">);</span></code>
<code class="computeroutput"><span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</span><span class="identifier">optional</span><span class="special">(</span> <span class="identifier">none_t</span> <span class="special">)</span> <span class="keyword">noexcept</span><span class="special">;</span></code>
</p></blockquote></div>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
@ -109,9 +105,6 @@
<li class="listitem">
<span class="bold"><strong>Postconditions:</strong></span> <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> is <span class="underline">uninitialized</span>.
</li>
<li class="listitem">
<span class="bold"><strong>Throws:</strong></span> Nothing.
</li>
<li class="listitem">
<span class="bold"><strong>Notes:</strong></span> <code class="computeroutput"><span class="identifier">T</span></code>'s
default constructor <span class="underline">is not</span> called.
@ -132,12 +125,16 @@
<code class="computeroutput"><span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span> </code><span class="emphasis"><em>(not a ref)</em></span><code class="computeroutput"><span class="special">&gt;::</span><span class="identifier">optional</span><span class="special">(</span> <span class="identifier">T</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">v</span> <span class="special">)</span></code>
</p></blockquote></div>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
<span class="bold"><strong>Requires:</strong></span> <code class="computeroutput"><span class="identifier">is_copy_constructible</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</span><span class="identifier">value</span></code>
is <code class="computeroutput"><span class="keyword">true</span></code>.
</li>
<li class="listitem">
<span class="bold"><strong>Effect:</strong></span> Directly-Constructs an <code class="computeroutput"><span class="identifier">optional</span></code>.
</li>
<li class="listitem">
<span class="bold"><strong>Postconditions:</strong></span> <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> is <span class="underline">initialized</span>
and its value is a<span class="emphasis"><em>copy</em></span> of <code class="computeroutput"><span class="identifier">v</span></code>.
and its value is a <span class="emphasis"><em>copy</em></span> of <code class="computeroutput"><span class="identifier">v</span></code>.
</li>
<li class="listitem">
<span class="bold"><strong>Throws:</strong></span> Whatever <code class="computeroutput"><span class="identifier">T</span><span class="special">::</span><span class="identifier">T</span><span class="special">(</span>
@ -193,6 +190,58 @@
</pre>
</li>
</ul></div>
<p>
<span class="inlinemediaobject"><img src="../images/space.png" alt="space"></span>
</p>
<a name="reference_optional_constructor_move_value"></a><div class="blockquote"><blockquote class="blockquote"><p>
<code class="computeroutput"><span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span> </code><span class="emphasis"><em>(not a ref)</em></span><code class="computeroutput"><span class="special">&gt;::</span><span class="identifier">optional</span><span class="special">(</span> <span class="identifier">T</span><span class="special">&amp;&amp;</span>
<span class="identifier">v</span> <span class="special">)</span></code>
</p></blockquote></div>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
<span class="bold"><strong>Requires:</strong></span> <code class="computeroutput"><span class="identifier">is_move_constructible</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</span><span class="identifier">value</span></code>
is <code class="computeroutput"><span class="keyword">true</span></code>.
</li>
<li class="listitem">
<span class="bold"><strong>Effect:</strong></span> Directly-Move-Constructs an <code class="computeroutput"><span class="identifier">optional</span></code>.
</li>
<li class="listitem">
<span class="bold"><strong>Postconditions:</strong></span> <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> is <span class="underline">initialized</span>
and its value is move-constructed from <code class="computeroutput"><span class="identifier">v</span></code>.
</li>
<li class="listitem">
<span class="bold"><strong>Throws:</strong></span> Whatever <code class="computeroutput"><span class="identifier">T</span><span class="special">::</span><span class="identifier">T</span><span class="special">(</span>
<span class="identifier">T</span><span class="special">&amp;&amp;</span>
<span class="special">)</span></code> throws.
</li>
<li class="listitem">
<span class="bold"><strong>Notes: </strong></span> <code class="computeroutput"><span class="identifier">T</span><span class="special">::</span><span class="identifier">T</span><span class="special">(</span>
<span class="identifier">T</span><span class="special">&amp;&amp;</span>
<span class="special">)</span></code> is called.
</li>
<li class="listitem">
<span class="bold"><strong>Exception Safety:</strong></span> Exceptions can only
be thrown during <code class="computeroutput"><span class="identifier">T</span><span class="special">::</span><span class="identifier">T</span><span class="special">(</span> <span class="identifier">T</span><span class="special">&amp;&amp;</span> <span class="special">);</span></code>
in that case, the state of <code class="computeroutput"><span class="identifier">v</span></code>
is determined by exception safety guarantees for <code class="computeroutput"><span class="identifier">T</span><span class="special">::</span><span class="identifier">T</span><span class="special">(</span><span class="identifier">T</span><span class="special">&amp;&amp;)</span></code>.
</li>
<li class="listitem">
<span class="bold"><strong>Example:</strong></span>
<pre class="programlisting"><span class="identifier">T</span> <span class="identifier">v1</span><span class="special">,</span> <span class="identifier">v2</span><span class="special">;</span>
<span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="identifier">opt</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">move</span><span class="special">(</span><span class="identifier">v1</span><span class="special">));</span>
<span class="identifier">assert</span> <span class="special">(</span> <span class="special">*</span><span class="identifier">opt</span> <span class="special">==</span> <span class="identifier">v2</span> <span class="special">)</span> <span class="special">;</span>
</pre>
</li>
</ul></div>
<p>
<span class="inlinemediaobject"><img src="../images/space.png" alt="space"></span>
</p>
<div class="blockquote"><blockquote class="blockquote"><p>
<code class="computeroutput"><span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&amp;&gt;::</span><span class="identifier">optional</span><span class="special">(</span> <span class="identifier">T</span><span class="special">&amp;&amp;</span> <span class="identifier">ref</span> <span class="special">)</span> <span class="special">=</span> <span class="keyword">delete</span></code>
</p></blockquote></div>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
<span class="bold"><strong>Notes:</strong></span> This constructor is deleted
</li></ul></div>
<p>
<span class="inlinemediaobject"><img src="../images/space.png" alt="space"></span>
</p>
@ -229,6 +278,10 @@
<code class="computeroutput"><span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span> </code><span class="emphasis"><em>(not a ref)</em></span><code class="computeroutput"><span class="special">&gt;::</span><span class="identifier">optional</span><span class="special">(</span> <span class="identifier">optional</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">rhs</span> <span class="special">);</span></code>
</p></blockquote></div>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
<span class="bold"><strong>Requires:</strong></span> <code class="computeroutput"><span class="identifier">is_copy_constructible</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</span><span class="identifier">value</span></code>
is <code class="computeroutput"><span class="keyword">true</span></code>.
</li>
<li class="listitem">
<span class="bold"><strong>Effect:</strong></span> Copy-Constructs an <code class="computeroutput"><span class="identifier">optional</span></code>.
</li>
@ -320,6 +373,116 @@
</pre>
</li>
</ul></div>
<p>
<span class="inlinemediaobject"><img src="../images/space.png" alt="space"></span>
</p>
<a name="reference_optional_move_constructor_optional"></a><div class="blockquote"><blockquote class="blockquote"><p>
<code class="computeroutput"><span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span> </code><span class="emphasis"><em>(not a ref)</em></span><code class="computeroutput"><span class="special">&gt;::</span><span class="identifier">optional</span><span class="special">(</span> <span class="identifier">optional</span><span class="special">&amp;&amp;</span> <span class="identifier">rhs</span>
<span class="special">)</span> <span class="keyword">noexcept</span><span class="special">(</span></code><span class="emphasis"><em>see below</em></span><code class="computeroutput"><span class="special">);</span></code>
</p></blockquote></div>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
<span class="bold"><strong>Requires:</strong></span> <code class="computeroutput"><span class="identifier">is_move_constructible</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</span><span class="identifier">value</span></code>
is <code class="computeroutput"><span class="keyword">true</span></code>.
</li>
<li class="listitem">
<span class="bold"><strong>Effect:</strong></span> Move-constructs an <code class="computeroutput"><span class="identifier">optional</span></code>.
</li>
<li class="listitem">
<span class="bold"><strong>Postconditions:</strong></span> If <code class="computeroutput"><span class="identifier">rhs</span></code>
is initialized, <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>
is initialized and its value is move constructed from <code class="computeroutput"><span class="identifier">rhs</span></code>;
else <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>
is uninitialized.
</li>
<li class="listitem">
<span class="bold"><strong>Throws:</strong></span> Whatever <code class="computeroutput"><span class="identifier">T</span><span class="special">::</span><span class="identifier">T</span><span class="special">(</span>
<span class="identifier">T</span><span class="special">&amp;&amp;</span>
<span class="special">)</span></code> throws.
</li>
<li class="listitem">
<span class="bold"><strong>Notes:</strong></span> If <code class="computeroutput"><span class="identifier">rhs</span></code>
is initialized, <code class="computeroutput"><span class="identifier">T</span><span class="special">::</span><span class="identifier">T</span><span class="special">(</span> <span class="identifier">T</span>
<span class="special">&amp;&amp;</span> <span class="special">)</span></code>
is called. The expression inside <code class="computeroutput"><span class="keyword">noexcept</span></code>
is equivalent to <code class="computeroutput"><span class="identifier">is_nothrow_move_constructible</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</span><span class="identifier">value</span></code>.
</li>
<li class="listitem">
<span class="bold"><strong>Exception Safety:</strong></span> Exceptions can only
be thrown during <code class="computeroutput"><span class="identifier">T</span><span class="special">::</span><span class="identifier">T</span><span class="special">(</span> <span class="identifier">T</span><span class="special">&amp;&amp;</span> <span class="special">);</span></code>
in that case, <code class="computeroutput"><span class="identifier">rhs</span></code> remains
initialized and the value of <code class="computeroutput"><span class="special">*</span><span class="identifier">rhs</span></code> is determined by exception safety
of <code class="computeroutput"><span class="identifier">T</span><span class="special">::</span><span class="identifier">T</span><span class="special">(</span><span class="identifier">T</span><span class="special">&amp;&amp;)</span></code>.
</li>
<li class="listitem">
<span class="bold"><strong>Example:</strong></span>
<pre class="programlisting"><span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">unique_ptr</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;&gt;</span> <span class="identifier">uninit</span> <span class="special">;</span>
<span class="identifier">assert</span> <span class="special">(!</span><span class="identifier">uninit</span><span class="special">);</span>
<span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">unique_ptr</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;&gt;</span> <span class="identifier">uinit2</span> <span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">move</span><span class="special">(</span><span class="identifier">uninit</span><span class="special">)</span> <span class="special">)</span> <span class="special">;</span>
<span class="identifier">assert</span> <span class="special">(</span> <span class="identifier">uninit2</span> <span class="special">==</span> <span class="identifier">uninit</span> <span class="special">);</span>
<span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">unique_ptr</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;&gt;</span> <span class="identifier">init</span><span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">uniqye_ptr</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;(</span><span class="keyword">new</span> <span class="identifier">T</span><span class="special">(</span><span class="number">2</span><span class="special">))</span> <span class="special">);</span>
<span class="identifier">assert</span> <span class="special">(</span> <span class="special">**</span><span class="identifier">init</span> <span class="special">==</span> <span class="identifier">T</span><span class="special">(</span><span class="number">2</span><span class="special">)</span> <span class="special">)</span> <span class="special">;</span>
<span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">unique_ptr</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;&gt;</span> <span class="identifier">init2</span> <span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">move</span><span class="special">(</span><span class="identifier">init</span><span class="special">)</span> <span class="special">)</span> <span class="special">;</span>
<span class="identifier">assert</span> <span class="special">(</span> <span class="identifier">init</span> <span class="special">);</span>
<span class="identifier">assert</span> <span class="special">(</span> <span class="special">*</span><span class="identifier">init</span> <span class="special">==</span> <span class="keyword">nullptr</span> <span class="special">);</span>
<span class="identifier">assert</span> <span class="special">(</span> <span class="identifier">init2</span> <span class="special">);</span>
<span class="identifier">assert</span> <span class="special">(</span> <span class="special">**</span><span class="identifier">init2</span> <span class="special">==</span> <span class="identifier">T</span><span class="special">(</span><span class="number">2</span><span class="special">)</span> <span class="special">)</span> <span class="special">;</span>
</pre>
</li>
</ul></div>
<p>
<span class="inlinemediaobject"><img src="../images/space.png" alt="space"></span>
</p>
<div class="blockquote"><blockquote class="blockquote"><p>
<code class="computeroutput"><span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&amp;&gt;::</span><span class="identifier">optional</span><span class="special">(</span> <span class="identifier">optional</span> <span class="special">&amp;&amp;</span>
<span class="identifier">rhs</span> <span class="special">);</span></code>
</p></blockquote></div>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
<span class="bold"><strong>Effect:</strong></span> Move-Constructs an <code class="computeroutput"><span class="identifier">optional</span></code>.
</li>
<li class="listitem">
<span class="bold"><strong>Postconditions:</strong></span> If <code class="computeroutput"><span class="identifier">rhs</span></code>
is initialized, <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>
is initialized and its value is another reference to the same object referenced
by <code class="computeroutput"><span class="special">*</span><span class="identifier">rhs</span></code>;
else <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>
is uninitialized.
</li>
<li class="listitem">
<span class="bold"><strong>Throws:</strong></span> Nothing.
</li>
<li class="listitem">
<span class="bold"><strong>Notes:</strong></span> If <code class="computeroutput"><span class="identifier">rhs</span></code>
is initialized, both <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>
and <code class="computeroutput"><span class="special">*</span><span class="identifier">rhs</span></code>
will reefer to the same object (they alias).
</li>
<li class="listitem">
<span class="bold"><strong>Example:</strong></span>
<pre class="programlisting"><span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">unique_ptr</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;&amp;&gt;</span> <span class="identifier">uninit</span> <span class="special">;</span>
<span class="identifier">assert</span> <span class="special">(!</span><span class="identifier">uninit</span><span class="special">);</span>
<span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">unique_ptr</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;&amp;&gt;</span> <span class="identifier">uinit2</span> <span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">move</span><span class="special">(</span><span class="identifier">uninit</span><span class="special">)</span> <span class="special">)</span> <span class="special">;</span>
<span class="identifier">assert</span> <span class="special">(</span> <span class="identifier">uninit2</span> <span class="special">==</span> <span class="identifier">uninit</span> <span class="special">);</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">unique_ptr</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="identifier">v</span><span class="special">(</span><span class="keyword">new</span> <span class="identifier">T</span><span class="special">(</span><span class="number">2</span><span class="special">))</span> <span class="special">;</span>
<span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">unique_ptr</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;&amp;&gt;</span> <span class="identifier">init</span><span class="special">(</span><span class="identifier">v</span><span class="special">);</span>
<span class="identifier">assert</span> <span class="special">(</span> <span class="special">*</span><span class="identifier">init</span> <span class="special">==</span> <span class="identifier">v</span> <span class="special">)</span> <span class="special">;</span>
<span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">unique_ptr</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;&amp;&gt;</span> <span class="identifier">init2</span> <span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">move</span><span class="special">(</span><span class="identifier">init</span><span class="special">)</span> <span class="special">)</span> <span class="special">;</span>
<span class="identifier">assert</span> <span class="special">(</span> <span class="special">*</span><span class="identifier">init2</span> <span class="special">==</span> <span class="identifier">v</span> <span class="special">)</span> <span class="special">;</span>
<span class="special">*</span><span class="identifier">v</span> <span class="special">=</span> <span class="number">3</span> <span class="special">;</span>
<span class="identifier">assert</span> <span class="special">(</span> <span class="special">**</span><span class="identifier">init</span> <span class="special">==</span> <span class="number">3</span> <span class="special">)</span> <span class="special">;</span>
<span class="identifier">assert</span> <span class="special">(</span> <span class="special">**</span><span class="identifier">init2</span> <span class="special">==</span> <span class="number">3</span> <span class="special">)</span> <span class="special">;</span>
</pre>
</li>
</ul></div>
<p>
<span class="inlinemediaobject"><img src="../images/space.png" alt="space"></span>
</p>
@ -368,6 +531,52 @@
</pre>
</li>
</ul></div>
<p>
<span class="inlinemediaobject"><img src="../images/space.png" alt="space"></span>
</p>
<a name="reference_optional_move_constructor_other_optional"></a><div class="blockquote"><blockquote class="blockquote"><p>
<code class="computeroutput"><span class="keyword">template</span><span class="special">&lt;</span><span class="identifier">U</span><span class="special">&gt;</span> <span class="keyword">explicit</span> <span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span></code>
<span class="emphasis"><em>(not a ref)</em></span><code class="computeroutput"><span class="special">&gt;::</span><span class="identifier">optional</span><span class="special">(</span> <span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">U</span><span class="special">&gt;&amp;&amp;</span>
<span class="identifier">rhs</span> <span class="special">);</span></code>
</p></blockquote></div>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
<span class="bold"><strong>Effect:</strong></span> Move-constructs an <code class="computeroutput"><span class="identifier">optional</span></code>.
</li>
<li class="listitem">
<span class="bold"><strong>Postconditions:</strong></span> If <code class="computeroutput"><span class="identifier">rhs</span></code>
is initialized, <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>
is initialized and its value is move constructed from <code class="computeroutput"><span class="special">*</span><span class="identifier">rhs</span></code>; else <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> is uninitialized.
</li>
<li class="listitem">
<span class="bold"><strong>Throws:</strong></span> Whatever <code class="computeroutput"><span class="identifier">T</span><span class="special">::</span><span class="identifier">T</span><span class="special">(</span>
<span class="identifier">U</span><span class="special">&amp;&amp;</span>
<span class="special">)</span></code> throws.
</li>
<li class="listitem">
<span class="bold"><strong>Notes: </strong></span> <code class="computeroutput"><span class="identifier">T</span><span class="special">::</span><span class="identifier">T</span><span class="special">(</span>
<span class="identifier">U</span><span class="special">&amp;&amp;</span>
<span class="special">)</span></code> is called if <code class="computeroutput"><span class="identifier">rhs</span></code>
is initialized, which requires a valid conversion from <code class="computeroutput"><span class="identifier">U</span></code>
to <code class="computeroutput"><span class="identifier">T</span></code>.
</li>
<li class="listitem">
<span class="bold"><strong>Exception Safety:</strong></span> Exceptions can only
be thrown during <code class="computeroutput"><span class="identifier">T</span><span class="special">::</span><span class="identifier">T</span><span class="special">(</span> <span class="identifier">U</span><span class="special">&amp;&amp;</span> <span class="special">);</span></code>
in that case, <code class="computeroutput"><span class="identifier">rhs</span></code> remains
initialized and the value of <code class="computeroutput"><span class="special">*</span><span class="identifier">rhs</span></code> is determined by exception safety
guarantee of <code class="computeroutput"><span class="identifier">T</span><span class="special">::</span><span class="identifier">T</span><span class="special">(</span> <span class="identifier">U</span><span class="special">&amp;&amp;</span> <span class="special">)</span></code>.
</li>
<li class="listitem">
<span class="bold"><strong>Example:</strong></span>
<pre class="programlisting"><span class="identifier">optional</span><span class="special">&lt;</span><span class="keyword">double</span><span class="special">&gt;</span> <span class="identifier">x</span><span class="special">(</span><span class="number">123.4</span><span class="special">);</span>
<span class="identifier">assert</span> <span class="special">(</span> <span class="special">*</span><span class="identifier">x</span> <span class="special">==</span> <span class="number">123.4</span> <span class="special">)</span> <span class="special">;</span>
<span class="identifier">optional</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;</span> <span class="identifier">y</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">move</span><span class="special">(</span><span class="identifier">x</span><span class="special">))</span> <span class="special">;</span>
<span class="identifier">assert</span><span class="special">(</span> <span class="special">*</span><span class="identifier">y</span> <span class="special">==</span> <span class="number">123</span> <span class="special">)</span> <span class="special">;</span>
</pre>
</li>
</ul></div>
<p>
<span class="inlinemediaobject"><img src="../images/space.png" alt="space"></span>
</p>
@ -420,6 +629,22 @@
</pre>
</li>
</ul></div>
<p>
<span class="inlinemediaobject"><img src="../images/space.png" alt="space"></span>
</p>
<a name="reference_optional_operator_equal_none_t"></a><div class="blockquote"><blockquote class="blockquote"><p>
<code class="computeroutput"><span class="identifier">optional</span><span class="special">&amp;</span>
<span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</span><span class="keyword">operator</span><span class="special">=</span> <span class="special">(</span> <span class="identifier">none_t</span> <span class="special">)</span> <span class="keyword">noexcept</span><span class="special">;</span></code>
</p></blockquote></div>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
<span class="bold"><strong>Effect:</strong></span> If <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> is initialized destroys its contained
value.
</li>
<li class="listitem">
<span class="bold"><strong>Postconditions: </strong></span> <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> is uninitialized.
</li>
</ul></div>
<p>
<span class="inlinemediaobject"><img src="../images/space.png" alt="space"></span>
</p>
@ -511,6 +736,66 @@
</pre>
</li>
</ul></div>
<p>
<span class="inlinemediaobject"><img src="../images/space.png" alt="space"></span>
</p>
<a name="reference_optional_operator_move_equal_value"></a><div class="blockquote"><blockquote class="blockquote"><p>
<code class="computeroutput"><span class="identifier">optional</span><span class="special">&amp;</span>
<span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span></code> <span class="emphasis"><em>(not a ref)</em></span><code class="computeroutput"><span class="special">&gt;::</span><span class="keyword">operator</span><span class="special">=</span> <span class="special">(</span> <span class="identifier">T</span><span class="special">&amp;&amp;</span> <span class="identifier">rhs</span>
<span class="special">)</span> <span class="special">;</span></code>
</p></blockquote></div>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
<span class="bold"><strong>Effect:</strong></span> Moves the value <code class="computeroutput"><span class="identifier">rhs</span></code> to an <code class="computeroutput"><span class="identifier">optional</span></code>.
</li>
<li class="listitem">
<span class="bold"><strong>Postconditions: </strong></span> <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> is initialized and its value is moved
from <code class="computeroutput"><span class="identifier">rhs</span></code>.
</li>
<li class="listitem">
<span class="bold"><strong>Throws:</strong></span> Whatever <code class="computeroutput"><span class="identifier">T</span><span class="special">::</span><span class="keyword">operator</span><span class="special">=(</span> <span class="identifier">T</span><span class="special">&amp;&amp;</span> <span class="special">)</span></code>
or <code class="computeroutput"><span class="identifier">T</span><span class="special">::</span><span class="identifier">T</span><span class="special">(</span><span class="identifier">T</span>
<span class="special">&amp;&amp;)</span></code> throws.
</li>
<li class="listitem">
<span class="bold"><strong>Notes:</strong></span> If <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> was initialized, <code class="computeroutput"><span class="identifier">T</span></code>'s
move-assignment operator is used, otherwise, its move-constructor is used.
</li>
<li class="listitem">
<span class="bold"><strong>Exception Safety:</strong></span> In the event of an exception,
the initialization state of <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> is unchanged and its value unspecified
as far as <code class="computeroutput"><span class="identifier">optional</span></code> is concerned
(it is up to <code class="computeroutput"><span class="identifier">T</span></code>'s <code class="computeroutput"><span class="keyword">operator</span><span class="special">=()</span></code>).
If <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>
is initially uninitialized and <code class="computeroutput"><span class="identifier">T</span></code>'s
<span class="emphasis"><em>move constructor</em></span> fails, <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> is left properly uninitialized.
</li>
<li class="listitem">
<span class="bold"><strong>Example:</strong></span>
<pre class="programlisting"><span class="identifier">T</span> <span class="identifier">x</span><span class="special">;</span>
<span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="identifier">def</span> <span class="special">;</span>
<span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="identifier">opt</span><span class="special">(</span><span class="identifier">x</span><span class="special">)</span> <span class="special">;</span>
<span class="identifier">T</span> <span class="identifier">y1</span><span class="special">,</span> <span class="identifier">y2</span><span class="special">,</span> <span class="identifier">yR</span><span class="special">;</span>
<span class="identifier">def</span> <span class="special">=</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">move</span><span class="special">(</span><span class="identifier">y1</span><span class="special">)</span> <span class="special">;</span>
<span class="identifier">assert</span> <span class="special">(</span> <span class="special">*</span><span class="identifier">def</span> <span class="special">==</span> <span class="identifier">yR</span> <span class="special">)</span> <span class="special">;</span>
<span class="identifier">opt</span> <span class="special">=</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">move</span><span class="special">(</span><span class="identifier">y2</span><span class="special">)</span> <span class="special">;</span>
<span class="identifier">assert</span> <span class="special">(</span> <span class="special">*</span><span class="identifier">opt</span> <span class="special">==</span> <span class="identifier">yR</span> <span class="special">)</span> <span class="special">;</span>
</pre>
</li>
</ul></div>
<p>
<span class="inlinemediaobject"><img src="../images/space.png" alt="space"></span>
</p>
<div class="blockquote"><blockquote class="blockquote"><p>
<code class="computeroutput"><span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&amp;&gt;&amp;</span>
<span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&amp;&gt;::</span><span class="keyword">operator</span><span class="special">=</span> <span class="special">(</span> <span class="identifier">T</span><span class="special">&amp;&amp;</span>
<span class="identifier">rhs</span> <span class="special">)</span>
<span class="special">=</span> <span class="keyword">delete</span><span class="special">;</span></code>
</p></blockquote></div>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
<span class="bold"><strong>Notes:</strong></span> This assignment operator is deleted.
</li></ul></div>
<p>
<span class="inlinemediaobject"><img src="../images/space.png" alt="space"></span>
</p>
@ -613,6 +898,75 @@
</pre>
</li>
</ul></div>
<p>
<span class="inlinemediaobject"><img src="../images/space.png" alt="space"></span>
</p>
<a name="reference_optional_operator_move_equal_optional"></a><div class="blockquote"><blockquote class="blockquote"><p>
<code class="computeroutput"><span class="identifier">optional</span><span class="special">&amp;</span>
<span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span></code> <span class="emphasis"><em>(not a ref)</em></span><code class="computeroutput"><span class="special">&gt;::</span><span class="keyword">operator</span><span class="special">=</span> <span class="special">(</span> <span class="identifier">optional</span><span class="special">&amp;&amp;</span> <span class="identifier">rhs</span>
<span class="special">)</span> <span class="keyword">noexcept</span><span class="special">(</span></code><span class="emphasis"><em>see below</em></span><code class="computeroutput"><span class="special">);</span></code>
</p></blockquote></div>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
<span class="bold"><strong>Effect:</strong></span> Move-assigns another <code class="computeroutput"><span class="identifier">optional</span></code> to an <code class="computeroutput"><span class="identifier">optional</span></code>.
</li>
<li class="listitem">
<span class="bold"><strong>Postconditions:</strong></span> If <code class="computeroutput"><span class="identifier">rhs</span></code>
is initialized, <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>
is initialized and its value is moved from <code class="computeroutput"><span class="special">*</span><span class="identifier">rhs</span></code>, <code class="computeroutput"><span class="identifier">rhs</span></code>
remains initialized; else <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> is uninitialized.
</li>
<li class="listitem">
<span class="bold"><strong>Throws:</strong></span> Whatever <code class="computeroutput"><span class="identifier">T</span><span class="special">::</span><span class="keyword">operator</span><span class="special">(</span> <span class="identifier">T</span><span class="special">&amp;&amp;</span>
<span class="special">)</span></code> or <code class="computeroutput"><span class="identifier">T</span><span class="special">::</span><span class="identifier">T</span><span class="special">(</span>
<span class="identifier">T</span> <span class="special">&amp;&amp;</span>
<span class="special">)</span></code> throws.
</li>
<li class="listitem">
<span class="bold"><strong>Notes:</strong></span> If both <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> and <code class="computeroutput"><span class="identifier">rhs</span></code>
are initially initialized, <code class="computeroutput"><span class="identifier">T</span></code>'s
<span class="emphasis"><em>move assignment operator</em></span> is used. If <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> is
initially initialized but <code class="computeroutput"><span class="identifier">rhs</span></code>
is uninitialized, <code class="computeroutput"><span class="identifier">T</span></code>'s [destructor]
is called. If <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>
is initially uninitialized but <code class="computeroutput"><span class="identifier">rhs</span></code>
is initialized, <code class="computeroutput"><span class="identifier">T</span></code>'s <span class="emphasis"><em>move
constructor</em></span> is called. The expression inside <code class="computeroutput"><span class="keyword">noexcept</span></code>
is equivalent to <code class="computeroutput"><span class="identifier">is_nothrow_move_constructible</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</span><span class="identifier">value</span>
<span class="special">&amp;&amp;</span> <span class="identifier">is_nothrow_move_assignable</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</span><span class="identifier">value</span></code>.
</li>
<li class="listitem">
<span class="bold"><strong>Exception Safety:</strong></span> In the event of an exception,
the initialization state of <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> is unchanged and its value unspecified
as far as optional is concerned (it is up to <code class="computeroutput"><span class="identifier">T</span></code>'s
<code class="computeroutput"><span class="keyword">operator</span><span class="special">=()</span></code>).
If <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>
is initially uninitialized and <code class="computeroutput"><span class="identifier">T</span></code>'s
<span class="emphasis"><em>move constructor</em></span> fails, <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> is left properly uninitialized.
</li>
<li class="listitem">
<span class="bold"><strong>Example:</strong></span>
<pre class="programlisting"><span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="identifier">opt</span><span class="special">(</span><span class="identifier">T</span><span class="special">(</span><span class="number">2</span><span class="special">))</span> <span class="special">;</span>
<span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="identifier">def</span> <span class="special">;</span>
<span class="identifier">opt</span> <span class="special">=</span> <span class="identifier">def</span> <span class="special">;</span>
<span class="identifier">assert</span> <span class="special">(</span> <span class="identifier">def</span> <span class="special">)</span> <span class="special">;</span>
<span class="identifier">assert</span> <span class="special">(</span> <span class="identifier">opt</span> <span class="special">)</span> <span class="special">;</span>
<span class="identifier">assert</span> <span class="special">(</span> <span class="special">*</span><span class="identifier">opt</span> <span class="special">==</span> <span class="identifier">T</span><span class="special">(</span><span class="number">2</span><span class="special">)</span> <span class="special">)</span> <span class="special">;</span>
</pre>
</li>
</ul></div>
<p>
<span class="inlinemediaobject"><img src="../images/space.png" alt="space"></span>
</p>
<div class="blockquote"><blockquote class="blockquote"><p>
<code class="computeroutput"><span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&amp;&gt;</span> <span class="special">&amp;</span> <span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&amp;&gt;::</span><span class="keyword">operator</span><span class="special">=</span> <span class="special">(</span> <span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&amp;&gt;&amp;&amp;</span>
<span class="identifier">rhs</span> <span class="special">)</span>
<span class="special">;</span></code>
</p></blockquote></div>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
<span class="bold"><strong>Effect:</strong></span> Same as <code class="computeroutput"><span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&amp;&gt;::</span><span class="keyword">operator</span><span class="special">=</span> <span class="special">(</span> <span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&amp;&gt;</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">rhs</span> <span class="special">)</span></code>.
</li></ul></div>
<p>
<span class="inlinemediaobject"><img src="../images/space.png" alt="space"></span>
</p>
@ -673,6 +1027,59 @@
</pre>
</li>
</ul></div>
<p>
<span class="inlinemediaobject"><img src="../images/space.png" alt="space"></span>
</p>
<a name="reference_optional_operator_move_equal_other_optional"></a><div class="blockquote"><blockquote class="blockquote"><p>
<code class="computeroutput"><span class="keyword">template</span><span class="special">&lt;</span><span class="identifier">U</span><span class="special">&gt;</span> <span class="identifier">optional</span><span class="special">&amp;</span>
<span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span></code> <span class="emphasis"><em>(not a ref)</em></span><code class="computeroutput"><span class="special">&gt;::</span><span class="keyword">operator</span><span class="special">=</span> <span class="special">(</span> <span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">U</span><span class="special">&gt;&amp;&amp;</span>
<span class="identifier">rhs</span> <span class="special">)</span>
<span class="special">;</span></code>
</p></blockquote></div>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
<span class="bold"><strong>Effect:</strong></span> Move-assigns another convertible
optional to an optional.
</li>
<li class="listitem">
<span class="bold"><strong>Postconditions:</strong></span> If <code class="computeroutput"><span class="identifier">rhs</span></code>
is initialized, <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>
is initialized and its value is moved from the value of <code class="computeroutput"><span class="identifier">rhs</span></code>;
else <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>
is uninitialized.
</li>
<li class="listitem">
<span class="bold"><strong>Throws:</strong></span> Whatever <code class="computeroutput"><span class="identifier">T</span><span class="special">::</span><span class="keyword">operator</span><span class="special">=(</span> <span class="identifier">U</span><span class="special">&amp;&amp;</span> <span class="special">)</span></code>
or <code class="computeroutput"><span class="identifier">T</span><span class="special">::</span><span class="identifier">T</span><span class="special">(</span> <span class="identifier">U</span><span class="special">&amp;&amp;</span> <span class="special">)</span></code>
throws.
</li>
<li class="listitem">
<span class="bold"><strong>Notes:</strong></span> If both <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> and <code class="computeroutput"><span class="identifier">rhs</span></code>
are initially initialized, <code class="computeroutput"><span class="identifier">T</span></code>'s
<span class="emphasis"><em>assignment operator</em></span> (from <code class="computeroutput"><span class="identifier">U</span><span class="special">&amp;&amp;</span></code>) is used. If <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> is initially initialized but <code class="computeroutput"><span class="identifier">rhs</span></code> is uninitialized, <code class="computeroutput"><span class="identifier">T</span></code>'s
<span class="emphasis"><em>destructor</em></span> is called. If <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> is initially uninitialized but <code class="computeroutput"><span class="identifier">rhs</span></code> is initialized, <code class="computeroutput"><span class="identifier">T</span></code>'s
<span class="emphasis"><em>converting constructor</em></span> (from <code class="computeroutput"><span class="identifier">U</span><span class="special">&amp;&amp;</span></code>) is called.
</li>
<li class="listitem">
<span class="bold"><strong>Exception Safety:</strong></span> In the event of an exception,
the initialization state of <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> is unchanged and its value unspecified
as far as optional is concerned (it is up to <code class="computeroutput"><span class="identifier">T</span></code>'s
<code class="computeroutput"><span class="keyword">operator</span><span class="special">=()</span></code>).
If <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>
is initially uninitialized and <code class="computeroutput"><span class="identifier">T</span></code>'s
converting constructor fails, <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> is left properly uninitialized.
</li>
<li class="listitem">
<span class="bold"><strong>Example:</strong></span>
<pre class="programlisting"><span class="identifier">T</span> <span class="identifier">v</span><span class="special">;</span>
<span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="identifier">opt0</span><span class="special">(</span><span class="identifier">v</span><span class="special">);</span>
<span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">U</span><span class="special">&gt;</span> <span class="identifier">opt1</span><span class="special">;</span>
<span class="identifier">opt1</span> <span class="special">=</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">move</span><span class="special">(</span><span class="identifier">opt0</span><span class="special">)</span> <span class="special">;</span>
<span class="identifier">assert</span> <span class="special">(</span> <span class="special">*</span><span class="identifier">opt1</span> <span class="special">==</span> <span class="keyword">static_cast</span><span class="special">&lt;</span><span class="identifier">U</span><span class="special">&gt;(</span><span class="identifier">v</span><span class="special">)</span> <span class="special">)</span> <span class="special">;</span>
</pre>
</li>
</ul></div>
<p>
<span class="inlinemediaobject"><img src="../images/space.png" alt="space"></span>
</p>
@ -731,7 +1138,7 @@
<span class="inlinemediaobject"><img src="../images/space.png" alt="space"></span>
</p>
<a name="reference_optional_reset"></a><div class="blockquote"><blockquote class="blockquote"><p>
<code class="computeroutput"><span class="keyword">void</span> <span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</span><span class="identifier">reset</span><span class="special">()</span> <span class="special">;</span></code>
<code class="computeroutput"><span class="keyword">void</span> <span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</span><span class="identifier">reset</span><span class="special">()</span> <span class="keyword">noexcept</span> <span class="special">;</span></code>
</p></blockquote></div>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
<span class="bold"><strong>Deprecated:</strong></span> Same as <code class="computeroutput"><span class="keyword">operator</span><span class="special">=(</span> <span class="identifier">detail</span><span class="special">::</span><span class="identifier">none_t</span> <span class="special">);</span></code>
@ -768,7 +1175,7 @@
</p></blockquote></div>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
<span class="bold"><strong>Requirements:</strong></span> <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> is initialized
<span class="bold"><strong>Requires:</strong></span> <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> is initialized
</li>
<li class="listitem">
<span class="bold"><strong>Returns:</strong></span> A reference to the contained
@ -870,7 +1277,7 @@
</p></blockquote></div>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
<span class="bold"><strong>Requirements: </strong></span> <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> is initialized
<span class="bold"><strong>Requires: </strong></span> <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> is initialized
</li>
<li class="listitem">
<span class="bold"><strong>Returns:</strong></span> <span class="underline">The</span>
@ -956,7 +1363,7 @@
</p></blockquote></div>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
<span class="bold"><strong>Requirements: </strong></span> <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> is initialized.
<span class="bold"><strong>Requires: </strong></span> <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> is initialized.
</li>
<li class="listitem">
<span class="bold"><strong>Returns:</strong></span> A pointer to the contained value.
@ -981,16 +1388,19 @@
<span class="inlinemediaobject"><img src="../images/space.png" alt="space"></span>
</p>
<a name="reference_optional_operator_bool"></a><div class="blockquote"><blockquote class="blockquote"><p>
<code class="computeroutput"><span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</span><span class="keyword">operator</span> </code><span class="emphasis"><em>unspecified-bool-type</em></span><code class="computeroutput"><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span></code>
<code class="computeroutput"><span class="keyword">explicit</span> <span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</span><span class="keyword">operator</span> <span class="keyword">bool</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span></code>
</p></blockquote></div>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
<span class="bold"><strong>Returns:</strong></span> An unspecified value which if
used on a boolean context is equivalent to (<code class="computeroutput"><span class="identifier">get_ptr</span><span class="special">()</span> <span class="special">!=</span> <span class="number">0</span></code>)
<span class="bold"><strong>Returns:</strong></span> <code class="computeroutput"><span class="identifier">get_ptr</span><span class="special">()</span> <span class="special">!=</span> <span class="number">0</span></code>.
</li>
<li class="listitem">
<span class="bold"><strong>Throws:</strong></span> Nothing.
</li>
<li class="listitem">
<span class="bold"><strong>Notes:</strong></span> On compilers that do not support
explicit conversion operators this falls back to safe-bool idiom.
</li>
<li class="listitem">
<span class="bold"><strong>Example:</strong></span>
<pre class="programlisting"><span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="identifier">def</span> <span class="special">;</span>
@ -1005,16 +1415,13 @@
<span class="inlinemediaobject"><img src="../images/space.png" alt="space"></span>
</p>
<a name="reference_optional_operator_not"></a><div class="blockquote"><blockquote class="blockquote"><p>
<code class="computeroutput"><span class="keyword">bool</span> <span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</span><span class="keyword">operator</span><span class="special">!()</span> <span class="special">;</span></code>
<code class="computeroutput"><span class="keyword">bool</span> <span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</span><span class="keyword">operator</span><span class="special">!()</span> <span class="keyword">noexcept</span> <span class="special">;</span></code>
</p></blockquote></div>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
<span class="bold"><strong>Returns:</strong></span> If <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code> is uninitialized, <code class="computeroutput"><span class="keyword">true</span></code>;
else <code class="computeroutput"><span class="keyword">false</span></code>.
</li>
<li class="listitem">
<span class="bold"><strong>Throws:</strong></span> Nothing.
</li>
<li class="listitem">
<span class="bold"><strong>Notes:</strong></span> This operator is provided for those
compilers which can't use the <span class="emphasis"><em>unspecified-bool-type operator</em></span>
@ -1039,9 +1446,9 @@
<span class="keyword">const</span> <span class="special">;</span></code>
</p></blockquote></div>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
<span class="bold"><strong>Deprecated:</strong></span> Same as <code class="computeroutput"><span class="keyword">operator</span>
</code><span class="emphasis"><em>unspecified-bool-type</em></span><code class="computeroutput"><span class="special">()</span>
<span class="special">;</span></code>
<span class="bold"><strong>Deprecated:</strong></span> Same as <code class="computeroutput"><span class="keyword">explicit</span>
<span class="keyword">operator</span> <span class="keyword">bool</span>
<span class="special">()</span> <span class="special">;</span></code>
</li></ul></div>
<p>
<span class="inlinemediaobject"><img src="../images/space.png" alt="space"></span>
@ -1106,6 +1513,10 @@
<span class="identifier">y</span> <span class="special">);</span></code>
</p></blockquote></div>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
<span class="bold"><strong>Requires:</strong></span> <code class="computeroutput"><span class="identifier">T</span></code>
shall meet requirements of <code class="computeroutput"><span class="identifier">EqualityComparable</span></code>.
</li>
<li class="listitem">
<span class="bold"><strong>Returns:</strong></span> If both <code class="computeroutput"><span class="identifier">x</span></code>
and <code class="computeroutput"><span class="identifier">y</span></code> are initialized,
@ -1162,6 +1573,10 @@
<span class="identifier">y</span> <span class="special">);</span></code>
</p></blockquote></div>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
<span class="bold"><strong>Requires:</strong></span> <code class="computeroutput"><span class="identifier">T</span></code>
shall meet requirements of <code class="computeroutput"><span class="identifier">LessThanComparable</span></code>.
</li>
<li class="listitem">
<span class="bold"><strong>Returns:</strong></span> If <code class="computeroutput"><span class="identifier">y</span></code>
is not initialized, <code class="computeroutput"><span class="keyword">false</span></code>.
@ -1257,7 +1672,8 @@
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
<span class="bold"><strong>Returns: </strong></span> <code class="computeroutput"><span class="special">!(</span>
<span class="identifier">y</span><span class="special">&lt;</span><span class="identifier">x</span> <span class="special">);</span></code>
<span class="identifier">y</span> <span class="special">&lt;</span>
<span class="identifier">x</span> <span class="special">);</span></code>
</li>
<li class="listitem">
<span class="bold"><strong>Throws:</strong></span> Nothing.
@ -1282,13 +1698,40 @@
<span class="bold"><strong>Throws:</strong></span> Nothing.
</li>
</ul></div>
<a name="reference_operator_compare_equal_optional_none"></a><div class="blockquote"><blockquote class="blockquote"><p>
<code class="computeroutput"><span class="keyword">bool</span> <span class="keyword">operator</span>
<span class="special">==</span> <span class="special">(</span> <span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">x</span><span class="special">,</span> <span class="identifier">none_t</span>
<span class="special">)</span> <span class="keyword">noexcept</span><span class="special">;</span></code>
</p></blockquote></div>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
<span class="bold"><strong>Returns:</strong></span> <code class="computeroutput"><span class="special">!</span><span class="identifier">x</span></code>.
</li>
<li class="listitem">
<span class="bold"><strong>Notes:</strong></span> <code class="computeroutput"><span class="identifier">T</span></code>
need not meet requirements of <code class="computeroutput"><span class="identifier">EqualityComparable</span></code>.
</li>
</ul></div>
<p>
<span class="inlinemediaobject"><img src="../images/space.png" alt="space"></span>
</p>
<a name="reference_operator_compare_not_equal_optional_none"></a><div class="blockquote"><blockquote class="blockquote"><p>
<code class="computeroutput"><span class="keyword">bool</span> <span class="keyword">operator</span>
<span class="special">!=</span> <span class="special">(</span> <span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">x</span><span class="special">,</span> <span class="identifier">none_t</span>
<span class="special">)</span> <span class="keyword">noexcept</span><span class="special">;</span></code>
</p></blockquote></div>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
<span class="bold"><strong>Returns: </strong></span> <code class="computeroutput"><span class="special">!(</span>
<span class="identifier">x</span> <span class="special">==</span>
<span class="identifier">y</span> <span class="special">);</span></code>
</li></ul></div>
<p>
<span class="inlinemediaobject"><img src="../images/space.png" alt="space"></span>
</p>
<a name="reference_swap_optional_optional"></a><div class="blockquote"><blockquote class="blockquote"><p>
<code class="computeroutput"><span class="keyword">void</span> <span class="identifier">swap</span>
<span class="special">(</span> <span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;&amp;</span>
<span class="identifier">x</span><span class="special">,</span> <span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;&amp;</span> <span class="identifier">y</span> <span class="special">);</span></code>
<span class="identifier">x</span><span class="special">,</span> <span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;&amp;</span> <span class="identifier">y</span> <span class="special">)</span> <span class="special">;</span></code>
</p></blockquote></div>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
@ -1305,19 +1748,21 @@
<li class="listitem">
<span class="bold"><strong>Throws:</strong></span> If both are initialized, whatever
<code class="computeroutput"><span class="identifier">swap</span><span class="special">(</span><span class="identifier">T</span><span class="special">&amp;,</span><span class="identifier">T</span><span class="special">&amp;)</span></code>
throws. If only one is initialized, whatever <code class="computeroutput"><span class="identifier">T</span><span class="special">::</span><span class="identifier">T</span> <span class="special">(</span> <span class="identifier">T</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="special">)</span></code> throws.
throws. If only one is initialized, whatever <code class="computeroutput"><span class="identifier">T</span><span class="special">::</span><span class="identifier">T</span> <span class="special">(</span> <span class="identifier">T</span><span class="special">&amp;&amp;</span>
<span class="special">)</span></code> throws.
</li>
<li class="listitem">
<span class="bold"><strong>Notes:</strong></span> If both are initialized, <code class="computeroutput"><span class="identifier">swap</span><span class="special">(</span><span class="identifier">T</span><span class="special">&amp;,</span><span class="identifier">T</span><span class="special">&amp;)</span></code>
is used unqualified but with <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">swap</span></code>
introduced in scope. If only one is initialized, <code class="computeroutput"><span class="identifier">T</span><span class="special">::~</span><span class="identifier">T</span><span class="special">()</span></code> and <code class="computeroutput"><span class="identifier">T</span><span class="special">::</span><span class="identifier">T</span><span class="special">(</span>
<span class="identifier">T</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="special">)</span></code>
is called.
<span class="identifier">T</span><span class="special">&amp;&amp;</span>
<span class="special">)</span></code> is called.
</li>
<li class="listitem">
<span class="bold"><strong>Exception Safety:</strong></span> If both are initialized,
this operation has the exception safety guarantees of <code class="computeroutput"><span class="identifier">swap</span><span class="special">(</span><span class="identifier">T</span><span class="special">&amp;,</span><span class="identifier">T</span><span class="special">&amp;)</span></code>.
If only one is initialized, it has the same basic guarantee as <code class="computeroutput"><span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</span><span class="identifier">reset</span><span class="special">(</span> <span class="identifier">T</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="special">)</span></code>.
If only one is initialized, it has the same basic guarantee as <code class="computeroutput"><span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</span><span class="keyword">operator</span><span class="special">=</span> <span class="special">(</span> <span class="identifier">T</span><span class="special">&amp;&amp;</span>
<span class="special">)</span></code>.
</li>
<li class="listitem">
<span class="bold"><strong>Example:</strong></span>
@ -1345,7 +1790,7 @@
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2003-2007 Fernando Luis Cacciola Carballal<p>
<td align="right"><div class="copyright-footer">Copyright &#169; 2003-2007 Fernando Luis Cacciola Carballal<br>Copyright &#169; 2014 Andrzej Krzemie&#324;ski<p>
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" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
</p>

View File

@ -2,11 +2,11 @@
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Development</title>
<link rel="stylesheet" href="../boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.77.1">
<link rel="stylesheet" href="../../../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.78.1">
<link rel="home" href="../index.html" title="Chapter&#160;1.&#160;Boost.Optional">
<link rel="up" href="../index.html" title="Chapter&#160;1.&#160;Boost.Optional">
<link rel="prev" href="../index.html" title="Chapter&#160;1.&#160;Boost.Optional">
<link rel="prev" href="motivation.html" title="Motivation">
<link rel="next" href="synopsis.html" title="Synopsis">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
@ -20,13 +20,13 @@
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="../index.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="synopsis.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
<a accesskey="p" href="motivation.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="synopsis.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="boost_optional.development"></a><a class="link" href="development.html" title="Development">Development</a>
</h2></div></div></div>
<div class="toc"><dl>
<div class="toc"><dl class="toc">
<dt><span class="section"><a href="development.html#boost_optional.development.the_models">The models</a></span></dt>
<dt><span class="section"><a href="development.html#boost_optional.development.the_semantics">The semantics</a></span></dt>
<dt><span class="section"><a href="development.html#boost_optional.development.the_interface">The Interface</a></span></dt>
@ -399,7 +399,7 @@
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2003-2007 Fernando Luis Cacciola Carballal<p>
<td align="right"><div class="copyright-footer">Copyright &#169; 2003-2007 Fernando Luis Cacciola Carballal<br>Copyright &#169; 2014 Andrzej Krzemie&#324;ski<p>
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" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
</p>
@ -407,7 +407,7 @@
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="../index.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="synopsis.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
<a accesskey="p" href="motivation.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="synopsis.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>

View File

@ -2,8 +2,8 @@
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Examples</title>
<link rel="stylesheet" href="../boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.77.1">
<link rel="stylesheet" href="../../../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.78.1">
<link rel="home" href="../index.html" title="Chapter&#160;1.&#160;Boost.Optional">
<link rel="up" href="../index.html" title="Chapter&#160;1.&#160;Boost.Optional">
<link rel="prev" href="detailed_semantics.html" title="Detailed Semantics">
@ -26,7 +26,7 @@
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="boost_optional.examples"></a><a class="link" href="examples.html" title="Examples">Examples</a>
</h2></div></div></div>
<div class="toc"><dl>
<div class="toc"><dl class="toc">
<dt><span class="section"><a href="examples.html#boost_optional.examples.optional_return_values">Optional
return values</a></span></dt>
<dt><span class="section"><a href="examples.html#boost_optional.examples.optional_local_variables">Optional
@ -133,7 +133,7 @@
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2003-2007 Fernando Luis Cacciola Carballal<p>
<td align="right"><div class="copyright-footer">Copyright &#169; 2003-2007 Fernando Luis Cacciola Carballal<br>Copyright &#169; 2014 Andrzej Krzemie&#324;ski<p>
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" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
</p>

View File

@ -2,8 +2,8 @@
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Exception Safety Guarantees</title>
<link rel="stylesheet" href="../boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.77.1">
<link rel="stylesheet" href="../../../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.78.1">
<link rel="home" href="../index.html" title="Chapter&#160;1.&#160;Boost.Optional">
<link rel="up" href="../index.html" title="Chapter&#160;1.&#160;Boost.Optional">
<link rel="prev" href="a_note_about_optional_bool_.html" title="A note about optional&lt;bool&gt;">
@ -28,8 +28,36 @@
Guarantees</a>
</h2></div></div></div>
<p>
Because of the current implementation (see <a class="link" href="implementation_notes.html" title="Implementation Notes">Implementation
Notes</a>), all of the assignment methods:
This library assumes that <code class="computeroutput"><span class="identifier">T</span></code>'s
destructor does not throw exceptions. If it does, the behaviour of many operations
on <code class="computeroutput"><span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span></code> is
undefined.
</p>
<p>
The following mutating operations never throw exceptions:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
<code class="computeroutput"><span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</span><span class="keyword">operator</span><span class="special">=</span> <span class="special">(</span> <span class="identifier">none_t</span> <span class="special">)</span> <span class="keyword">noexcept</span></code>
</li>
<li class="listitem">
<code class="computeroutput"><span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</span><span class="identifier">reset</span><span class="special">()</span> <span class="keyword">noexcept</span></code>
</li>
</ul></div>
<p>
In addition, the following constructors and the destructor never throw exceptions:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
<code class="computeroutput"><span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</span><span class="identifier">optional</span><span class="special">()</span>
<span class="keyword">noexcept</span></code>
</li>
<li class="listitem">
<code class="computeroutput"><span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</span><span class="identifier">optional</span><span class="special">(</span> <span class="identifier">none_t</span> <span class="special">)</span> <span class="keyword">noexcept</span></code>
</li>
</ul></div>
<p>
Regarding the following assignment functions:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
@ -52,93 +80,76 @@
<span class="special">)</span> </code>
</li>
<li class="listitem">
<code class="computeroutput"><span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</span><span class="identifier">reset</span> <span class="special">(</span> <span class="identifier">T</span> <span class="keyword">const</span><span class="special">&amp;)</span></code>
<code class="computeroutput"><span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</span><span class="identifier">reset</span><span class="special">(</span> <span class="identifier">T</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="special">)</span></code>
</li>
</ul></div>
<p>
Can only <span class="emphasis"><em>guarantee</em></span> the <span class="underline">basic
exception safety</span>: The lvalue optional is left <span class="underline">uninitialized</span>
if an exception is thrown (any previous value is <span class="emphasis"><em>first</em></span>
destroyed using <code class="computeroutput"><span class="identifier">T</span><span class="special">::~</span><span class="identifier">T</span><span class="special">()</span></code>)
They forward calls to the corresponding <code class="computeroutput"><span class="identifier">T</span></code>'s
constructors or assignments (depending on whether the optional object is initialized
or not); so if both <code class="computeroutput"><span class="identifier">T</span></code>'s constructor
and the assignment provide strong exception safety guarantee, <code class="computeroutput"><span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span></code>'s assignment
also provides strong exception safety guarantee; otherwise we only get the
basic guarantee. Additionally, if both involved <code class="computeroutput"><span class="identifier">T</span></code>'s
constructor and the assignment never throw, <code class="computeroutput"><span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span></code>'s
assignment also never throws.
</p>
<p>
On the other hand, the <span class="emphasis"><em>uninitializing</em></span> methods:
Unless <code class="computeroutput"><span class="identifier">T</span></code>'s constructor or assignment
throws, <code class="computeroutput"><span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span></code> does
not throw anything else on its own. A throw during assignment never changes
the initialization state of any optional object involved:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
<code class="computeroutput"><span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</span><span class="keyword">operator</span><span class="special">=</span> <span class="special">(</span> <span class="identifier">detail</span><span class="special">::</span><span class="identifier">none_t</span> <span class="special">)</span></code>
</li>
<li class="listitem">
<code class="computeroutput"><span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</span><span class="identifier">reset</span><span class="special">()</span></code>
</li>
</ul></div>
<p>
Provide the no-throw guarantee (assuming a no-throw <code class="computeroutput"><span class="identifier">T</span><span class="special">::~</span><span class="identifier">T</span><span class="special">()</span></code>)
</p>
<p>
However, since <code class="computeroutput"><span class="identifier">optional</span><span class="special">&lt;&gt;</span></code>
itself doesn't throw any exceptions, the only source for exceptions here are
<code class="computeroutput"><span class="identifier">T</span></code>'s constructor, so if you
know the exception guarantees for <code class="computeroutput"><span class="identifier">T</span><span class="special">::</span><span class="identifier">T</span> <span class="special">(</span>
<span class="identifier">T</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="special">)</span></code>, you
know that <code class="computeroutput"><span class="identifier">optional</span></code>'s assignment
and reset has the same guarantees.
</p>
<pre class="programlisting"><span class="comment">//</span>
<span class="comment">// Case 1: Exception thrown during assignment.</span>
<span class="comment">//</span>
<span class="identifier">T</span> <span class="identifier">v0</span><span class="special">(</span><span class="number">123</span><span class="special">);</span>
<span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="identifier">opt0</span><span class="special">(</span><span class="identifier">v0</span><span class="special">);</span>
<pre class="programlisting"><span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="identifier">opt1</span><span class="special">(</span><span class="identifier">val1</span><span class="special">);</span>
<span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="identifier">opt2</span><span class="special">(</span><span class="identifier">val2</span><span class="special">);</span>
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">opt1</span><span class="special">);</span>
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">opt2</span><span class="special">);</span>
<span class="keyword">try</span>
<span class="special">{</span>
<span class="identifier">T</span> <span class="identifier">v1</span><span class="special">(</span><span class="number">456</span><span class="special">);</span>
<span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="identifier">opt1</span><span class="special">(</span><span class="identifier">v1</span><span class="special">);</span>
<span class="identifier">opt0</span> <span class="special">=</span> <span class="identifier">opt1</span> <span class="special">;</span>
<span class="comment">// If no exception was thrown, assignment succeeded.</span>
<span class="identifier">assert</span><span class="special">(</span> <span class="special">*</span><span class="identifier">opt0</span> <span class="special">==</span> <span class="identifier">v1</span> <span class="special">)</span> <span class="special">;</span>
<span class="identifier">opt1</span> <span class="special">=</span> <span class="identifier">opt2</span><span class="special">;</span> <span class="comment">// throws</span>
<span class="special">}</span>
<span class="keyword">catch</span><span class="special">(...)</span>
<span class="special">{</span>
<span class="comment">// If any exception was thrown, 'opt0' is reset to uninitialized.</span>
<span class="identifier">assert</span><span class="special">(</span> <span class="special">!</span><span class="identifier">opt0</span> <span class="special">)</span> <span class="special">;</span>
<span class="special">}</span>
<span class="comment">//</span>
<span class="comment">// Case 2: Exception thrown during reset(v)</span>
<span class="comment">//</span>
<span class="identifier">T</span> <span class="identifier">v0</span><span class="special">(</span><span class="number">123</span><span class="special">);</span>
<span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="identifier">opt</span><span class="special">(</span><span class="identifier">v0</span><span class="special">);</span>
<span class="keyword">try</span>
<span class="special">{</span>
<span class="identifier">T</span> <span class="identifier">v1</span><span class="special">(</span><span class="number">456</span><span class="special">);</span>
<span class="identifier">opt</span><span class="special">.</span><span class="identifier">reset</span> <span class="special">(</span> <span class="identifier">v1</span> <span class="special">)</span> <span class="special">;</span>
<span class="comment">// If no exception was thrown, reset succeeded.</span>
<span class="identifier">assert</span><span class="special">(</span> <span class="special">*</span><span class="identifier">opt</span> <span class="special">==</span> <span class="identifier">v1</span> <span class="special">)</span> <span class="special">;</span>
<span class="special">}</span>
<span class="keyword">catch</span><span class="special">(...)</span>
<span class="special">{</span>
<span class="comment">// If any exception was thrown, 'opt' is reset to uninitialized.</span>
<span class="identifier">assert</span><span class="special">(</span> <span class="special">!</span><span class="identifier">opt</span> <span class="special">)</span> <span class="special">;</span>
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">opt1</span><span class="special">);</span>
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">opt2</span><span class="special">);</span>
<span class="special">}</span>
</pre>
<p>
This also applies to move assignments/constructors. However, move operations
are made no-throw more often.
</p>
<h4>
<a name="boost_optional.exception_safety_guarantees.h0"></a>
<span class="phrase"><a name="boost_optional.exception_safety_guarantees.swap"></a></span><a class="link" href="exception_safety_guarantees.html#boost_optional.exception_safety_guarantees.swap">Swap</a>
</h4>
<p>
<code class="computeroutput"><span class="keyword">void</span> <span class="identifier">swap</span><span class="special">(</span> <span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;&amp;,</span>
<span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;&amp;</span> <span class="special">)</span></code> has the same exception guarantee as <code class="computeroutput"><span class="identifier">swap</span><span class="special">(</span><span class="identifier">T</span><span class="special">&amp;,</span><span class="identifier">T</span><span class="special">&amp;)</span></code>
when both optionals are initialized. If only one of the optionals is initialized,
it gives the same <span class="emphasis"><em>basic</em></span> exception guarantee as <code class="computeroutput"><span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</span><span class="identifier">reset</span><span class="special">(</span> <span class="identifier">T</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="special">)</span></code> (since
<code class="computeroutput"><span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</span><span class="identifier">reset</span><span class="special">()</span></code> doesn't throw). If none of the optionals
is initialized, it has no-throw guarantee since it is a no-op.
Unless <code class="computeroutput"><span class="identifier">swap</span></code> on optional is
customized, its primary implementation forwards calls to <code class="computeroutput"><span class="identifier">T</span></code>'s
<code class="computeroutput"><span class="identifier">swap</span></code> or move constructor (depending
on the initialization state of the optional objects). Thus, if both <code class="computeroutput"><span class="identifier">T</span></code>'s <code class="computeroutput"><span class="identifier">swap</span></code>
and move constructor never throw, <code class="computeroutput"><span class="identifier">swap</span></code>
on <code class="computeroutput"><span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span></code> never
throws. similarly, if both <code class="computeroutput"><span class="identifier">T</span></code>'s
<code class="computeroutput"><span class="identifier">swap</span></code> and move constructor offer
strong guarantee, <code class="computeroutput"><span class="identifier">swap</span></code> on
<code class="computeroutput"><span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span></code> also
offers a strong guarantee.
</p>
<p>
In case <code class="computeroutput"><span class="identifier">swap</span></code> on optional is
customized, the call to <code class="computeroutput"><span class="identifier">T</span></code>'s
move constructor are replaced with the calls to <code class="computeroutput"><span class="identifier">T</span></code>'s
default constructor followed by <code class="computeroutput"><span class="identifier">swap</span></code>.
(This is more useful on older compilers that do not support move semantics,
when one wants to acheive stronger exception safety guarantees.) In this case
the exception safety guarantees for <code class="computeroutput"><span class="identifier">swap</span></code>
are reliant on the guarantees of <code class="computeroutput"><span class="identifier">T</span></code>'s
<code class="computeroutput"><span class="identifier">swap</span></code> and default constructor
</p>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2003-2007 Fernando Luis Cacciola Carballal<p>
<td align="right"><div class="copyright-footer">Copyright &#169; 2003-2007 Fernando Luis Cacciola Carballal<br>Copyright &#169; 2014 Andrzej Krzemie&#324;ski<p>
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" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
</p>

View File

@ -2,8 +2,8 @@
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Implementation Notes</title>
<link rel="stylesheet" href="../boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.77.1">
<link rel="stylesheet" href="../../../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.78.1">
<link rel="home" href="../index.html" title="Chapter&#160;1.&#160;Boost.Optional">
<link rel="up" href="../index.html" title="Chapter&#160;1.&#160;Boost.Optional">
<link rel="prev" href="type_requirements.html" title="Type requirements">
@ -31,17 +31,17 @@
currently implemented using a custom aligned storage facility built from <code class="computeroutput"><span class="identifier">alignment_of</span></code> and <code class="computeroutput"><span class="identifier">type_with_alignment</span></code>
(both from Type Traits). It uses a separate boolean flag to indicate the initialization
state. Placement new with <code class="computeroutput"><span class="identifier">T</span></code>'s
copy constructor and <code class="computeroutput"><span class="identifier">T</span></code>'s destructor
are explicitly used to initialize,copy and destroy optional values. As a result,
<code class="computeroutput"><span class="identifier">T</span></code>'s default constructor is
effectively by-passed, but the exception guarantees are basic. It is planned
to replace the current implementation with another with stronger exception
safety, such as a future <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">variant</span></code>.
copy/move constructor and <code class="computeroutput"><span class="identifier">T</span></code>'s
destructor are explicitly used to initialize, copy, move and destroy optional
values. As a result, <code class="computeroutput"><span class="identifier">T</span></code>'s default
constructor is effectively by-passed, but the exception guarantees are basic.
It is planned to replace the current implementation with another with stronger
exception safety, such as a future <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">variant</span></code>.
</p>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2003-2007 Fernando Luis Cacciola Carballal<p>
<td align="right"><div class="copyright-footer">Copyright &#169; 2003-2007 Fernando Luis Cacciola Carballal<br>Copyright &#169; 2014 Andrzej Krzemie&#324;ski<p>
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" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
</p>

View File

@ -2,8 +2,8 @@
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>In-Place Factories</title>
<link rel="stylesheet" href="../boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.77.1">
<link rel="stylesheet" href="../../../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.78.1">
<link rel="home" href="../index.html" title="Chapter&#160;1.&#160;Boost.Optional">
<link rel="up" href="../index.html" title="Chapter&#160;1.&#160;Boost.Optional">
<link rel="prev" href="rebinding_semantics_for_assignment_of_optional_references.html" title="Rebinding semantics for assignment of optional references">
@ -182,7 +182,7 @@
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2003-2007 Fernando Luis Cacciola Carballal<p>
<td align="right"><div class="copyright-footer">Copyright &#169; 2003-2007 Fernando Luis Cacciola Carballal<br>Copyright &#169; 2014 Andrzej Krzemie&#324;ski<p>
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" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
</p>

View File

@ -0,0 +1,128 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Motivation</title>
<link rel="stylesheet" href="../../../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.78.1">
<link rel="home" href="../index.html" title="Chapter&#160;1.&#160;Boost.Optional">
<link rel="up" href="../index.html" title="Chapter&#160;1.&#160;Boost.Optional">
<link rel="prev" href="../index.html" title="Chapter&#160;1.&#160;Boost.Optional">
<link rel="next" href="development.html" title="Development">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td>
<td align="center"><a href="../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="../index.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="development.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="boost_optional.motivation"></a><a class="link" href="motivation.html" title="Motivation">Motivation</a>
</h2></div></div></div>
<p>
Consider these functions which should return a value but which might not have
a value to return:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
(A) <code class="computeroutput"><span class="keyword">double</span> <span class="identifier">sqrt</span><span class="special">(</span><span class="keyword">double</span> <span class="identifier">n</span> <span class="special">);</span></code>
</li>
<li class="listitem">
(B) <code class="computeroutput"><span class="keyword">char</span> <span class="identifier">get_async_input</span><span class="special">();</span></code>
</li>
<li class="listitem">
(C) <code class="computeroutput"><span class="identifier">point</span> <span class="identifier">polygon</span><span class="special">::</span><span class="identifier">get_any_point_effectively_inside</span><span class="special">();</span></code>
</li>
</ul></div>
<p>
There are different approaches to the issue of not having a value to return.
</p>
<p>
A typical approach is to consider the existence of a valid return value as
a postcondition, so that if the function cannot compute the value to return,
it has either undefined behavior (and can use assert in a debug build) or uses
a runtime check and throws an exception if the postcondition is violated. This
is a reasonable choice for example, for function (A), because the lack of a
proper return value is directly related to an invalid parameter (out of domain
argument), so it is appropriate to require the callee to supply only parameters
in a valid domain for execution to continue normally.
</p>
<p>
However, function (B), because of its asynchronous nature, does not fail just
because it can't find a value to return; so it is incorrect to consider such
a situation an error and assert or throw an exception. This function must return,
and somehow, must tell the callee that it is not returning a meaningful value.
</p>
<p>
A similar situation occurs with function (C): it is conceptually an error to
ask a <span class="emphasis"><em>null-area</em></span> polygon to return a point inside itself,
but in many applications, it is just impractical for performance reasons to
treat this as an error (because detecting that the polygon has no area might
be too expensive to be required to be tested previously), and either an arbitrary
point (typically at infinity) is returned, or some efficient way to tell the
callee that there is no such point is used.
</p>
<p>
There are various mechanisms to let functions communicate that the returned
value is not valid. One such mechanism, which is quite common since it has
zero or negligible overhead, is to use a special value which is reserved to
communicate this. Classical examples of such special values are <code class="computeroutput"><span class="identifier">EOF</span></code>, <code class="computeroutput"><span class="identifier">string</span><span class="special">::</span><span class="identifier">npos</span></code>, points
at infinity, etc...
</p>
<p>
When those values exist, i.e. the return type can hold all meaningful values
<span class="emphasis"><em>plus</em></span> the <span class="emphasis"><em>signal</em></span> value, this mechanism
is quite appropriate and well known. Unfortunately, there are cases when such
values do not exist. In these cases, the usual alternative is either to use
a wider type, such as <code class="computeroutput"><span class="keyword">int</span></code> in place
of <code class="computeroutput"><span class="keyword">char</span></code>; or a compound type, such
as <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">pair</span><span class="special">&lt;</span><span class="identifier">point</span><span class="special">,</span><span class="keyword">bool</span><span class="special">&gt;</span></code>.
</p>
<p>
Returning a <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">pair</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">,</span><span class="keyword">bool</span><span class="special">&gt;</span></code>, thus attaching a boolean flag to the result
which indicates if the result is meaningful, has the advantage that can be
turned into a consistent idiom since the first element of the pair can be whatever
the function would conceptually return. For example, the last two functions
could have the following interface:
</p>
<pre class="programlisting"><span class="identifier">std</span><span class="special">::</span><span class="identifier">pair</span><span class="special">&lt;</span><span class="keyword">char</span><span class="special">,</span><span class="keyword">bool</span><span class="special">&gt;</span> <span class="identifier">get_async_input</span><span class="special">();</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">pair</span><span class="special">&lt;</span><span class="identifier">point</span><span class="special">,</span><span class="keyword">bool</span><span class="special">&gt;</span> <span class="identifier">polygon</span><span class="special">::</span><span class="identifier">get_any_point_effectively_inside</span><span class="special">();</span>
</pre>
<p>
These functions use a consistent interface for dealing with possibly nonexistent
results:
</p>
<pre class="programlisting"><span class="identifier">std</span><span class="special">::</span><span class="identifier">pair</span><span class="special">&lt;</span><span class="identifier">point</span><span class="special">,</span><span class="keyword">bool</span><span class="special">&gt;</span> <span class="identifier">p</span> <span class="special">=</span> <span class="identifier">poly</span><span class="special">.</span><span class="identifier">get_any_point_effectively_inside</span><span class="special">();</span>
<span class="keyword">if</span> <span class="special">(</span> <span class="identifier">p</span><span class="special">.</span><span class="identifier">second</span> <span class="special">)</span>
<span class="identifier">flood_fill</span><span class="special">(</span><span class="identifier">p</span><span class="special">.</span><span class="identifier">first</span><span class="special">);</span>
</pre>
<p>
However, not only is this quite a burden syntactically, it is also error prone
since the user can easily use the function result (first element of the pair)
without ever checking if it has a valid value.
</p>
<p>
Clearly, we need a better idiom.
</p>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2003-2007 Fernando Luis Cacciola Carballal<br>Copyright &#169; 2014 Andrzej Krzemie&#324;ski<p>
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" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
</p>
</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="../index.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="development.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>

View File

@ -2,8 +2,8 @@
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Optional references</title>
<link rel="stylesheet" href="../boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.77.1">
<link rel="stylesheet" href="../../../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.78.1">
<link rel="home" href="../index.html" title="Chapter&#160;1.&#160;Boost.Optional">
<link rel="up" href="../index.html" title="Chapter&#160;1.&#160;Boost.Optional">
<link rel="prev" href="examples.html" title="Examples">
@ -60,7 +60,7 @@
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
Copies of <code class="computeroutput"><span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&amp;&gt;</span></code>
will copy the references but all these references will nonetheless reefer
will copy the references but all these references will nonetheless refer
to the same object.
</li>
<li class="listitem">
@ -68,10 +68,39 @@
than the reference itself.
</li>
</ul></div>
<div class="warning"><table border="0" summary="Warning">
<tr>
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Warning]" src="../../../../../doc/src/images/warning.png"></td>
<th align="left">Warning</th>
</tr>
<tr><td align="left" valign="top"><p>
On compilers that do not conform to Standard C++ rules of reference binding,
operations on optional references might give adverse results: rather than
binding a reference to a designated object they may create an unexpected
temporary and bind to it. For more details see <a class="link" href="dependencies_and_portability.html#boost_optional.dependencies_and_portability.optional_reference_binding" title="Optional Reference Binding">Dependencies
and Portability section</a>.
</p></td></tr>
</table></div>
<h4>
<a name="boost_optional.optional_references.h0"></a>
<span class="phrase"><a name="boost_optional.optional_references.rvalue_references"></a></span><a class="link" href="optional_references.html#boost_optional.optional_references.rvalue_references">Rvalue
references</a>
</h4>
<p>
Rvalue references and lvalue references to const have the ability in C++ to
extend the life time of a temporary they bind to. Optional references do not
have this capability, therefore to avoid surprising effects it is not possible
to initialize an optional references from a temporary. Optional rvalue references
are disabled altogether. Also, the initialization and assignment of an optional
reference to const from rvalue reference is disabled.
</p>
<pre class="programlisting"><span class="keyword">const</span> <span class="keyword">int</span><span class="special">&amp;</span> <span class="identifier">i</span> <span class="special">=</span> <span class="number">1</span><span class="special">;</span> <span class="comment">// legal</span>
<span class="identifier">optional</span><span class="special">&lt;</span><span class="keyword">const</span> <span class="keyword">int</span><span class="special">&amp;&gt;</span> <span class="identifier">oi</span> <span class="special">=</span> <span class="number">1</span><span class="special">;</span> <span class="comment">// illegal</span>
</pre>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2003-2007 Fernando Luis Cacciola Carballal<p>
<td align="right"><div class="copyright-footer">Copyright &#169; 2003-2007 Fernando Luis Cacciola Carballal<br>Copyright &#169; 2014 Andrzej Krzemie&#324;ski<p>
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" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
</p>

View File

@ -2,8 +2,8 @@
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Rebinding semantics for assignment of optional references</title>
<link rel="stylesheet" href="../boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.77.1">
<link rel="stylesheet" href="../../../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.78.1">
<link rel="home" href="../index.html" title="Chapter&#160;1.&#160;Boost.Optional">
<link rel="up" href="../index.html" title="Chapter&#160;1.&#160;Boost.Optional">
<link rel="prev" href="optional_references.html" title="Optional references">
@ -134,7 +134,7 @@
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2003-2007 Fernando Luis Cacciola Carballal<p>
<td align="right"><div class="copyright-footer">Copyright &#169; 2003-2007 Fernando Luis Cacciola Carballal<br>Copyright &#169; 2014 Andrzej Krzemie&#324;ski<p>
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" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
</p>

View File

@ -2,8 +2,8 @@
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Synopsis</title>
<link rel="stylesheet" href="../boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.77.1">
<link rel="stylesheet" href="../../../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.78.1">
<link rel="home" href="../index.html" title="Chapter&#160;1.&#160;Boost.Optional">
<link rel="up" href="../index.html" title="Chapter&#160;1.&#160;Boost.Optional">
<link rel="prev" href="development.html" title="Development">
@ -37,31 +37,43 @@
<span class="comment">// (If T is of reference type, the parameters and results by reference are by value)</span>
<span class="identifier">optional</span> <span class="special">()</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_optional_constructor"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
<span class="identifier">optional</span> <span class="special">()</span> <span class="keyword">noexcept</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_optional_constructor"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
<span class="identifier">optional</span> <span class="special">(</span> <span class="identifier">none_t</span> <span class="special">)</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_optional_constructor_none_t"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
<span class="identifier">optional</span> <span class="special">(</span> <span class="identifier">none_t</span> <span class="special">)</span> <span class="keyword">noexcept</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_optional_constructor_none_t"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
<span class="identifier">optional</span> <span class="special">(</span> <span class="identifier">T</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">v</span> <span class="special">)</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_optional_constructor_value"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
<span class="identifier">optional</span> <span class="special">(</span> <span class="identifier">T</span><span class="special">&amp;&amp;</span> <span class="identifier">v</span> <span class="special">)</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_optional_constructor_move_value"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
<span class="comment">// [new in 1.34]</span>
<span class="identifier">optional</span> <span class="special">(</span> <span class="keyword">bool</span> <span class="identifier">condition</span><span class="special">,</span> <span class="identifier">T</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">v</span> <span class="special">)</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_optional_constructor_bool_value"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
<span class="identifier">optional</span> <span class="special">(</span> <span class="identifier">optional</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">rhs</span> <span class="special">)</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_optional_constructor_optional"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
<span class="identifier">optional</span> <span class="special">(</span> <span class="identifier">optional</span><span class="special">&amp;&amp;</span> <span class="identifier">rhs</span> <span class="special">)</span> <span class="keyword">noexcept</span><span class="special">(</span><span class="emphasis"><em>see below</em></span><span class="special">)</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_optional_move_constructor_optional"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">U</span><span class="special">&gt;</span> <span class="keyword">explicit</span> <span class="identifier">optional</span> <span class="special">(</span> <span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">U</span><span class="special">&gt;</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">rhs</span> <span class="special">)</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_optional_constructor_other_optional"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">U</span><span class="special">&gt;</span> <span class="keyword">explicit</span> <span class="identifier">optional</span> <span class="special">(</span> <span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">U</span><span class="special">&gt;&amp;&amp;</span> <span class="identifier">rhs</span> <span class="special">)</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_optional_move_constructor_other_optional"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">InPlaceFactory</span><span class="special">&gt;</span> <span class="keyword">explicit</span> <span class="identifier">optional</span> <span class="special">(</span> <span class="identifier">InPlaceFactory</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">f</span> <span class="special">)</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_optional_constructor_factory"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">TypedInPlaceFactory</span><span class="special">&gt;</span> <span class="keyword">explicit</span> <span class="identifier">optional</span> <span class="special">(</span> <span class="identifier">TypedInPlaceFactory</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">f</span> <span class="special">)</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_optional_constructor_factory"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
<span class="identifier">optional</span><span class="special">&amp;</span> <span class="keyword">operator</span> <span class="special">=</span> <span class="special">(</span> <span class="identifier">none_t</span> <span class="special">)</span> <span class="special">;</span>
<span class="identifier">optional</span><span class="special">&amp;</span> <span class="keyword">operator</span> <span class="special">=</span> <span class="special">(</span> <span class="identifier">none_t</span> <span class="special">)</span> <span class="keyword">noexcept</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_optional_operator_equal_none_t"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
<span class="identifier">optional</span><span class="special">&amp;</span> <span class="keyword">operator</span> <span class="special">=</span> <span class="special">(</span> <span class="identifier">T</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">v</span> <span class="special">)</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_optional_operator_equal_value"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
<span class="identifier">optional</span><span class="special">&amp;</span> <span class="keyword">operator</span> <span class="special">=</span> <span class="special">(</span> <span class="identifier">T</span><span class="special">&amp;&amp;</span> <span class="identifier">v</span> <span class="special">)</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_optional_operator_move_equal_value"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
<span class="identifier">optional</span><span class="special">&amp;</span> <span class="keyword">operator</span> <span class="special">=</span> <span class="special">(</span> <span class="identifier">optional</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">rhs</span> <span class="special">)</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_optional_operator_equal_optional"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
<span class="identifier">optional</span><span class="special">&amp;</span> <span class="keyword">operator</span> <span class="special">=</span> <span class="special">(</span> <span class="identifier">optional</span><span class="special">&amp;&amp;</span> <span class="identifier">rhs</span> <span class="special">)</span> <span class="keyword">noexcept</span><span class="special">(</span><span class="emphasis"><em>see below</em></span><span class="special">)</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_optional_operator_move_equal_optional"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">U</span><span class="special">&gt;</span> <span class="identifier">optional</span><span class="special">&amp;</span> <span class="keyword">operator</span> <span class="special">=</span> <span class="special">(</span> <span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">U</span><span class="special">&gt;</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">rhs</span> <span class="special">)</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_optional_operator_equal_other_optional"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">U</span><span class="special">&gt;</span> <span class="identifier">optional</span><span class="special">&amp;</span> <span class="keyword">operator</span> <span class="special">=</span> <span class="special">(</span> <span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">U</span><span class="special">&gt;&amp;&amp;</span> <span class="identifier">rhs</span> <span class="special">)</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_optional_operator_move_equal_other_optional"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">InPlaceFactory</span><span class="special">&gt;</span> <span class="identifier">optional</span><span class="special">&amp;</span> <span class="keyword">operator</span> <span class="special">=</span> <span class="special">(</span> <span class="identifier">InPlaceFactory</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">f</span> <span class="special">)</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_optional_operator_equal_factory"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">TypedInPlaceFactory</span><span class="special">&gt;</span> <span class="identifier">optional</span><span class="special">&amp;</span> <span class="keyword">operator</span> <span class="special">=</span> <span class="special">(</span> <span class="identifier">TypedInPlaceFactory</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">f</span> <span class="special">)</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_optional_operator_equal_factory"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
@ -81,14 +93,14 @@
<span class="identifier">T</span> <span class="keyword">const</span><span class="special">*</span> <span class="identifier">get_ptr</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_optional_get_ptr"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
<span class="identifier">T</span><span class="special">*</span> <span class="identifier">get_ptr</span><span class="special">()</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_optional_get_ptr"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
<span class="keyword">operator</span> <span class="identifier">unspecified</span><span class="special">-</span><span class="keyword">bool</span><span class="special">-</span><span class="identifier">type</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_optional_operator_bool"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
<span class="keyword">explicit</span> <span class="keyword">operator</span> <span class="keyword">bool</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_optional_operator_bool"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
<span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">!()</span> <span class="keyword">const</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_optional_operator_not"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
<span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">!()</span> <span class="keyword">const</span> <span class="keyword">noexcept</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_optional_operator_not"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
<span class="comment">// deprecated methods</span>
<span class="comment">// (deprecated)</span>
<span class="keyword">void</span> <span class="identifier">reset</span><span class="special">()</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_optional_reset"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
<span class="keyword">void</span> <span class="identifier">reset</span><span class="special">()</span> <span class="keyword">noexcept</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_optional_reset"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
<span class="comment">// (deprecated)</span>
<span class="keyword">void</span> <span class="identifier">reset</span> <span class="special">(</span> <span class="identifier">T</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="special">)</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_optional_reset_value"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
@ -110,6 +122,10 @@
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span> <span class="keyword">inline</span> <span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">&gt;=</span> <span class="special">(</span> <span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">x</span><span class="special">,</span> <span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">y</span> <span class="special">)</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_operator_compare_greater_or_equal_optional_optional"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span> <span class="keyword">inline</span> <span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">==</span> <span class="special">(</span> <span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">x</span><span class="special">,</span> <span class="identifier">none_t</span> <span class="special">)</span> <span class="keyword">noexcept</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_operator_compare_equal_optional_none"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span> <span class="keyword">inline</span> <span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">!=</span> <span class="special">(</span> <span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">x</span><span class="special">,</span> <span class="identifier">none_t</span> <span class="special">)</span> <span class="keyword">noexcept</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_operator_compare_not_equal_optional_none"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
<span class="comment">// [new in 1.34]</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span> <span class="keyword">inline</span> <span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="identifier">make_optional</span> <span class="special">(</span> <span class="identifier">T</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">v</span> <span class="special">)</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_make_optional_value"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
@ -138,7 +154,7 @@
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2003-2007 Fernando Luis Cacciola Carballal<p>
<td align="right"><div class="copyright-footer">Copyright &#169; 2003-2007 Fernando Luis Cacciola Carballal<br>Copyright &#169; 2014 Andrzej Krzemie&#324;ski<p>
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" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
</p>

View File

@ -2,12 +2,12 @@
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Type requirements</title>
<link rel="stylesheet" href="../boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.77.1">
<link rel="stylesheet" href="../../../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.78.1">
<link rel="home" href="../index.html" title="Chapter&#160;1.&#160;Boost.Optional">
<link rel="up" href="../index.html" title="Chapter&#160;1.&#160;Boost.Optional">
<link rel="prev" href="exception_safety_guarantees.html" title="Exception Safety Guarantees">
<link rel="next" href="implementation_notes.html" title="Implementation Notes">
<link rel="next" href="dependencies_and_portability.html" title="Dependencies and Portability">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
@ -20,16 +20,16 @@
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="exception_safety_guarantees.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="implementation_notes.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
<a accesskey="p" href="exception_safety_guarantees.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="dependencies_and_portability.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="boost_optional.type_requirements"></a><a class="link" href="type_requirements.html" title="Type requirements">Type requirements</a>
</h2></div></div></div>
<p>
In general, <code class="computeroutput"><span class="identifier">T</span></code> must be <a href="../../../../utility/CopyConstructible.html" target="_top">Copy Constructible</a> and
have a no-throw destructor. The copy-constructible requirement is not needed
if <span class="bold"><strong>InPlaceFactories</strong></span> are used.
In general, <code class="computeroutput"><span class="identifier">T</span></code> must be <code class="computeroutput"><span class="identifier">MoveConstructible</span></code> and have a no-throw destructor.
The <code class="computeroutput"><span class="identifier">MoveConstructible</span></code> requirement
is not needed if <span class="bold"><strong>InPlaceFactories</strong></span> are used.
</p>
<p>
<code class="computeroutput"><span class="identifier">T</span></code> <span class="underline">is
@ -39,7 +39,7 @@
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2003-2007 Fernando Luis Cacciola Carballal<p>
<td align="right"><div class="copyright-footer">Copyright &#169; 2003-2007 Fernando Luis Cacciola Carballal<br>Copyright &#169; 2014 Andrzej Krzemie&#324;ski<p>
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" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
</p>
@ -47,7 +47,7 @@
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="exception_safety_guarantees.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="implementation_notes.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
<a accesskey="p" href="exception_safety_guarantees.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="dependencies_and_portability.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>

View File

@ -1,582 +0,0 @@
/*=============================================================================
Copyright (c) 2004 Joel de Guzman
http://spirit.sourceforge.net/
Use, modification and distribution is subject to the Boost Software
License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
=============================================================================*/
/*=============================================================================
Body defaults
=============================================================================*/
body
{
margin: 1em;
font-family: sans-serif;
}
/*=============================================================================
Paragraphs
=============================================================================*/
p
{
text-align: left;
font-size: 10pt;
line-height: 1.15;
}
/*=============================================================================
Program listings
=============================================================================*/
/* Code on paragraphs */
p tt.computeroutput
{
font-size: 10pt;
}
pre.synopsis
{
font-size: 10pt;
margin: 1pc 4% 0pc 4%;
padding: 0.5pc 0.5pc 0.5pc 0.5pc;
}
.programlisting,
.screen
{
font-size: 10pt;
display: block;
margin: 1pc 4% 0pc 4%;
padding: 0.5pc 0.5pc 0.5pc 0.5pc;
}
/* Program listings in tables don't get borders */
td .programlisting,
td .screen
{
margin: 0pc 0pc 0pc 0pc;
padding: 0pc 0pc 0pc 0pc;
}
/*=============================================================================
Headings
=============================================================================*/
h1, h2, h3, h4, h5, h6
{
text-align: left;
margin: 1em 0em 0.5em 0em;
font-weight: bold;
}
h1 { font: 140% }
h2 { font: bold 140% }
h3 { font: bold 130% }
h4 { font: bold 120% }
h5 { font: italic 110% }
h6 { font: italic 100% }
/* Top page titles */
title,
h1.title,
h2.title
h3.title,
h4.title,
h5.title,
h6.title,
.refentrytitle
{
font-weight: bold;
margin-bottom: 1pc;
}
h1.title { font-size: 140% }
h2.title { font-size: 140% }
h3.title { font-size: 130% }
h4.title { font-size: 120% }
h5.title { font-size: 110% }
h6.title { font-size: 100% }
.section h1
{
margin: 0em 0em 0.5em 0em;
font-size: 140%;
}
.section h2 { font-size: 140% }
.section h3 { font-size: 130% }
.section h4 { font-size: 120% }
.section h5 { font-size: 110% }
.section h6 { font-size: 100% }
/* Code on titles */
h1 tt.computeroutput { font-size: 140% }
h2 tt.computeroutput { font-size: 140% }
h3 tt.computeroutput { font-size: 130% }
h4 tt.computeroutput { font-size: 120% }
h5 tt.computeroutput { font-size: 110% }
h6 tt.computeroutput { font-size: 100% }
/*=============================================================================
Author
=============================================================================*/
h3.author
{
font-size: 100%
}
/*=============================================================================
Lists
=============================================================================*/
li
{
font-size: 10pt;
line-height: 1.3;
}
/* Unordered lists */
ul
{
text-align: left;
}
/* Ordered lists */
ol
{
text-align: left;
}
/*=============================================================================
Links
=============================================================================*/
a
{
text-decoration: none; /* no underline */
}
a:hover
{
text-decoration: underline;
}
/*=============================================================================
Spirit style navigation
=============================================================================*/
.spirit-nav
{
text-align: right;
}
.spirit-nav a
{
color: white;
padding-left: 0.5em;
}
.spirit-nav img
{
border-width: 0px;
}
/*=============================================================================
Table of contents
=============================================================================*/
.toc
{
margin: 1pc 4% 0pc 4%;
padding: 0.1pc 1pc 0.1pc 1pc;
font-size: 10pt;
line-height: 1.15;
}
.toc-main
{
text-align: center;
margin: 3pc 16% 3pc 16%;
padding: 3pc 1pc 3pc 1pc;
line-height: 0.1;
}
.boost-toc
{
float: right;
padding: 0.5pc;
}
/*=============================================================================
Tables
=============================================================================*/
.table-title,
div.table p.title
{
margin-left: 4%;
padding-right: 0.5em;
padding-left: 0.5em;
}
.informaltable table,
.table table
{
width: 92%;
margin-left: 4%;
margin-right: 4%;
}
div.informaltable table,
div.table table
{
padding: 4px;
}
/* Table Cells */
div.informaltable table tr td,
div.table table tr td
{
padding: 0.5em;
text-align: left;
}
div.informaltable table tr th,
div.table table tr th
{
padding: 0.5em 0.5em 0.5em 0.5em;
border: 1pt solid white;
font-size: 120%;
}
/*=============================================================================
Blurbs
=============================================================================*/
div.note,
div.tip,
div.important,
div.caution,
div.warning,
div.sidebar
{
font-size: 10pt;
line-height: 1.2;
display: block;
margin: 1pc 4% 0pc 4%;
padding: 0.5pc 0.5pc 0.5pc 0.5pc;
}
div.sidebar img
{
padding: 1pt;
}
/*=============================================================================
Callouts
=============================================================================*/
.line_callout_bug img
{
float: left;
position:relative;
left: 4px;
top: -12px;
clear: left;
margin-left:-22px;
}
.callout_bug img
{
}
/*=============================================================================
Variable Lists
=============================================================================*/
/* Make the terms in definition lists bold */
div.variablelist dl dt,
span.term
{
font-weight: bold;
font-size: 10pt;
}
div.variablelist table tbody tr td
{
text-align: left;
vertical-align: top;
padding: 0em 2em 0em 0em;
font-size: 10pt;
margin: 0em 0em 0.5em 0em;
line-height: 1;
}
/* Make the terms in definition lists bold */
div.variablelist dl dt
{
margin-bottom: 0.2em;
}
div.variablelist dl dd
{
margin: 0em 0em 0.5em 2em;
font-size: 10pt;
}
div.variablelist table tbody tr td p
div.variablelist dl dd p
{
margin: 0em 0em 0.5em 0em;
line-height: 1;
}
/*=============================================================================
Misc
=============================================================================*/
/* Title of books and articles in bibliographies */
span.title
{
font-style: italic;
}
span.underline
{
text-decoration: underline;
}
span.strikethrough
{
text-decoration: line-through;
}
/* Copyright, Legal Notice */
div div.legalnotice p
{
text-align: left
}
/*=============================================================================
Colors
=============================================================================*/
@media screen
{
/* Links */
a
{
color: #0C7445;
}
a:visited
{
color: #663974;
}
h1 a, h2 a, h3 a, h4 a, h5 a, h6 a,
h1 a:hover, h2 a:hover, h3 a:hover, h4 a:hover, h5 a:hover, h6 a:hover,
h1 a:visited, h2 a:visited, h3 a:visited, h4 a:visited, h5 a:visited, h6 a:visited
{
text-decoration: none; /* no underline */
color: #000000;
}
/* Syntax Highlighting */
.keyword { color: #0000AA; }
.identifier { color: #000000; }
.special { color: #707070; }
.preprocessor { color: #402080; }
.char { color: teal; }
.comment { color: #800000; }
.string { color: teal; }
.number { color: teal; }
.white_bkd { background-color: #E8FBE9; }
.dk_grey_bkd { background-color: #A0DAAC; }
/* Copyright, Legal Notice */
.copyright
{
color: #666666;
font-size: small;
}
div div.legalnotice p
{
color: #666666;
}
/* Program listing */
pre.synopsis
{
border: 1px solid #DCDCDC;
border-bottom: 3px solid #9D9D9D;
border-right: 3px solid #9D9D9D;
background-color: #FAFFFB;
}
.programlisting,
.screen
{
border: 1px solid #DCDCDC;
border-bottom: 3px solid #9D9D9D;
border-right: 3px solid #9D9D9D;
background-color: #FAFFFB;
}
td .programlisting,
td .screen
{
border: 0px solid #DCDCDC;
}
/* Blurbs */
div.note,
div.tip,
div.important,
div.caution,
div.warning,
div.sidebar
{
border: 1px solid #DCDCDC;
border-bottom: 3px solid #9D9D9D;
border-right: 3px solid #9D9D9D;
background-color: #FAFFFB;
}
/* Table of contents */
.toc
{
border: 1px solid #DCDCDC;
border-bottom: 3px solid #9D9D9D;
border-right: 3px solid #9D9D9D;
background-color: #FAFFFB;
}
/* Table of contents */
.toc-main
{
border: 1px solid #DCDCDC;
border-bottom: 3px solid #9D9D9D;
border-right: 3px solid #9D9D9D;
background-color: #FAFFFB;
}
/* Tables */
div.informaltable table tr td,
div.table table tr td
{
border: 1px solid #DCDCDC;
background-color: #FAFFFB;
}
div.informaltable table tr th,
div.table table tr th
{
background-color: #E3F9E4;
border: 1px solid #DCDCDC;
}
/* Misc */
span.highlight
{
color: #00A000;
}
}
@media print
{
/* Links */
a
{
color: black;
}
a:visited
{
color: black;
}
.spirit-nav
{
display: none;
}
/* Program listing */
pre.synopsis
{
border: 1px solid gray;
background-color: #FAFFFB;
}
.programlisting,
.screen
{
border: 1px solid gray;
background-color: #FAFFFB;
}
td .programlisting,
td .screen
{
border: 0px solid #DCDCDC;
}
/* Table of contents */
.toc
{
border: 1px solid #DCDCDC;
border-bottom: 3px solid #9D9D9D;
border-right: 3px solid #9D9D9D;
background-color: #FAFFFB;
}
/* Table of contents */
.toc-main
{
border: 1px solid #DCDCDC;
border-bottom: 3px solid #9D9D9D;
border-right: 3px solid #9D9D9D;
background-color: #FAFFFB;
}
.informaltable table,
.table table
{
border: 1px solid #DCDCDC;
border-bottom: 3px solid #9D9D9D;
border-right: 3px solid #9D9D9D;
border-collapse: collapse;
background-color: #FAFFFB;
}
/* Tables */
div.informaltable table tr td,
div.table table tr td
{
border: 1px solid #DCDCDC;
background-color: #FAFFFB;
}
div.informaltable table tr th,
div.table table tr th
{
border: 1px solid #DCDCDC;
background-color: #FAFFFB;
}
/* Misc */
span.highlight
{
font-weight: bold;
}
}

View File

@ -2,10 +2,10 @@
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Chapter&#160;1.&#160;Boost.Optional</title>
<link rel="stylesheet" href="boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.77.1">
<link rel="stylesheet" href="../../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.78.1">
<link rel="home" href="index.html" title="Chapter&#160;1.&#160;Boost.Optional">
<link rel="next" href="boost_optional/development.html" title="Development">
<link rel="next" href="boost_optional/motivation.html" title="Motivation">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
@ -17,7 +17,7 @@
<td align="center"><a href="../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav"><a accesskey="n" href="boost_optional/development.html"><img src="../../../../doc/src/images/next.png" alt="Next"></a></div>
<div class="spirit-nav"><a accesskey="n" href="boost_optional/motivation.html"><img src="../../../../doc/src/images/next.png" alt="Next"></a></div>
<div class="chapter">
<div class="titlepage"><div>
<div><h2 class="title">
@ -26,6 +26,7 @@
<span class="firstname">Fernando Luis</span> <span class="surname">Cacciola Carballal</span>
</h3></div></div>
<div><p class="copyright">Copyright &#169; 2003-2007 Fernando Luis Cacciola Carballal</p></div>
<div><p class="copyright">Copyright &#169; 2014 Andrzej Krzemie&#324;ski</p></div>
<div><div class="legalnotice">
<a name="optional.legal"></a><p>
Distributed under the Boost Software License, Version 1.0. (See accompanying
@ -35,8 +36,9 @@
</div></div>
<div class="toc">
<p><b>Table of Contents</b></p>
<dl>
<dt><span class="section"><a href="index.html#optional.motivation">Motivation</a></span></dt>
<dl class="toc">
<dt><span class="section"><a href="index.html#optional.introduction">Introduction</a></span></dt>
<dt><span class="section"><a href="boost_optional/motivation.html">Motivation</a></span></dt>
<dt><span class="section"><a href="boost_optional/development.html">Development</a></span></dt>
<dd><dl>
<dt><span class="section"><a href="boost_optional/development.html#boost_optional.development.the_models">The models</a></span></dt>
@ -65,108 +67,35 @@
<dt><span class="section"><a href="boost_optional/exception_safety_guarantees.html">Exception Safety
Guarantees</a></span></dt>
<dt><span class="section"><a href="boost_optional/type_requirements.html">Type requirements</a></span></dt>
<dt><span class="section"><a href="boost_optional/implementation_notes.html">Implementation Notes</a></span></dt>
<dt><span class="section"><a href="boost_optional/dependencies_and_portability.html">Dependencies
and Portability</a></span></dt>
<dd><dl><dt><span class="section"><a href="boost_optional/dependencies_and_portability.html#boost_optional.dependencies_and_portability.optional_reference_binding">Optional
Reference Binding</a></span></dt></dl></dd>
<dt><span class="section"><a href="boost_optional/acknowledgments.html">Acknowledgments</a></span></dt>
</dl>
</div>
<div class="section">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="optional.motivation"></a><a class="link" href="index.html#optional.motivation" title="Motivation">Motivation</a>
<a name="optional.introduction"></a><a class="link" href="index.html#optional.introduction" title="Introduction">Introduction</a>
</h2></div></div></div>
<p>
Consider these functions which should return a value but which might not have
a value to return:
This library can be used to represent 'optional' (or 'nullable') objects that
can be safely passed by value:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
(A) <code class="computeroutput"><span class="keyword">double</span> <span class="identifier">sqrt</span><span class="special">(</span><span class="keyword">double</span> <span class="identifier">n</span> <span class="special">);</span></code>
</li>
<li class="listitem">
(B) <code class="computeroutput"><span class="keyword">char</span> <span class="identifier">get_async_input</span><span class="special">();</span></code>
</li>
<li class="listitem">
(C) <code class="computeroutput"><span class="identifier">point</span> <span class="identifier">polygon</span><span class="special">::</span><span class="identifier">get_any_point_effectively_inside</span><span class="special">();</span></code>
</li>
</ul></div>
<p>
There are different approaches to the issue of not having a value to return.
</p>
<p>
A typical approach is to consider the existence of a valid return value as
a postcondition, so that if the function cannot compute the value to return,
it has either undefined behavior (and can use assert in a debug build) or uses
a runtime check and throws an exception if the postcondition is violated. This
is a reasonable choice for example, for function (A), because the lack of a
proper return value is directly related to an invalid parameter (out of domain
argument), so it is appropriate to require the callee to supply only parameters
in a valid domain for execution to continue normally.
</p>
<p>
However, function (B), because of its asynchronous nature, does not fail just
because it can't find a value to return; so it is incorrect to consider such
a situation an error and assert or throw an exception. This function must return,
and somehow, must tell the callee that it is not returning a meaningful value.
</p>
<p>
A similar situation occurs with function (C): it is conceptually an error to
ask a <span class="emphasis"><em>null-area</em></span> polygon to return a point inside itself,
but in many applications, it is just impractical for performance reasons to
treat this as an error (because detecting that the polygon has no area might
be too expensive to be required to be tested previously), and either an arbitrary
point (typically at infinity) is returned, or some efficient way to tell the
callee that there is no such point is used.
</p>
<p>
There are various mechanisms to let functions communicate that the returned
value is not valid. One such mechanism, which is quite common since it has
zero or negligible overhead, is to use a special value which is reserved to
communicate this. Classical examples of such special values are <code class="computeroutput"><span class="identifier">EOF</span></code>, <code class="computeroutput"><span class="identifier">string</span><span class="special">::</span><span class="identifier">npos</span></code>, points
at infinity, etc...
</p>
<p>
When those values exist, i.e. the return type can hold all meaningful values
<span class="emphasis"><em>plus</em></span> the <span class="emphasis"><em>signal</em></span> value, this mechanism
is quite appropriate and well known. Unfortunately, there are cases when such
values do not exist. In these cases, the usual alternative is either to use
a wider type, such as <code class="computeroutput"><span class="keyword">int</span></code> in place
of <code class="computeroutput"><span class="keyword">char</span></code>; or a compound type, such
as <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">pair</span><span class="special">&lt;</span><span class="identifier">point</span><span class="special">,</span><span class="keyword">bool</span><span class="special">&gt;</span></code>.
</p>
<p>
Returning a <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">pair</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">,</span><span class="keyword">bool</span><span class="special">&gt;</span></code>, thus attaching a boolean flag to the result
which indicates if the result is meaningful, has the advantage that can be
turned into a consistent idiom since the first element of the pair can be whatever
the function would conceptually return. For example, the last two functions
could have the following interface:
</p>
<pre class="programlisting"><span class="identifier">std</span><span class="special">::</span><span class="identifier">pair</span><span class="special">&lt;</span><span class="keyword">char</span><span class="special">,</span><span class="keyword">bool</span><span class="special">&gt;</span> <span class="identifier">get_async_input</span><span class="special">();</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">pair</span><span class="special">&lt;</span><span class="identifier">point</span><span class="special">,</span><span class="keyword">bool</span><span class="special">&gt;</span> <span class="identifier">polygon</span><span class="special">::</span><span class="identifier">get_any_point_effectively_inside</span><span class="special">();</span>
<pre class="programlisting"><span class="identifier">optional</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;</span> <span class="identifier">readInt</span><span class="special">();</span> <span class="comment">// this function may return either an int or a not-an-int</span>
<span class="keyword">if</span> <span class="special">(</span><span class="identifier">optional</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;</span> <span class="identifier">oi</span> <span class="special">=</span> <span class="identifier">readInt</span><span class="special">())</span> <span class="comment">// did I get a real int</span>
<span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="string">"my int is: "</span> <span class="special">&lt;&lt;</span> <span class="special">*</span><span class="identifier">oi</span><span class="special">;</span> <span class="comment">// use my int</span>
<span class="keyword">else</span>
<span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="string">"I have no int"</span><span class="special">;</span>
</pre>
<p>
These functions use a consistent interface for dealing with possibly nonexistent
results:
</p>
<pre class="programlisting"><span class="identifier">std</span><span class="special">::</span><span class="identifier">pair</span><span class="special">&lt;</span><span class="identifier">point</span><span class="special">,</span><span class="keyword">bool</span><span class="special">&gt;</span> <span class="identifier">p</span> <span class="special">=</span> <span class="identifier">poly</span><span class="special">.</span><span class="identifier">get_any_point_effectively_inside</span><span class="special">();</span>
<span class="keyword">if</span> <span class="special">(</span> <span class="identifier">p</span><span class="special">.</span><span class="identifier">second</span> <span class="special">)</span>
<span class="identifier">flood_fill</span><span class="special">(</span><span class="identifier">p</span><span class="special">.</span><span class="identifier">first</span><span class="special">);</span>
</pre>
<p>
However, not only is this quite a burden syntactically, it is also error prone
since the user can easily use the function result (first element of the pair)
without ever checking if it has a valid value.
</p>
<p>
Clearly, we need a better idiom.
</p>
</div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"><p><small>Last revised: April 11, 2014 at 13:25:26 GMT</small></p></td>
<td align="left"><p><small>Last revised: May 08, 2014 at 12:05:10 GMT</small></p></td>
<td align="right"><div class="copyright-footer"></div></td>
</tr></table>
<hr>
<div class="spirit-nav"><a accesskey="n" href="boost_optional/development.html"><img src="../../../../doc/src/images/next.png" alt="Next"></a></div>
<div class="spirit-nav"><a accesskey="n" href="boost_optional/motivation.html"><img src="../../../../doc/src/images/next.png" alt="Next"></a></div>
</body>
</html>

View File

@ -1,26 +0,0 @@
[/
Boost.Optional
Copyright (c) 2003-2007 Fernando Luis Cacciola Carballal
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 Implementation Notes]
`optional<T>` is currently implemented using a custom aligned storage facility
built from `alignment_of` and `type_with_alignment` (both from Type Traits). It
uses a separate boolean flag to indicate the initialization state.
Placement new with `T`'s copy constructor and `T`'s destructor are explicitly used
to initialize,copy and destroy optional values.
As a result, `T`'s default constructor is effectively by-passed, but the exception
guarantees are basic.
It is planned to replace the current implementation with another with stronger
exception safety, such as a future `boost::variant`.
[endsect]

80
doc/motivation.qbk Normal file
View File

@ -0,0 +1,80 @@
[/
Boost.Optional
Copyright (c) 2003-2007 Fernando Luis Cacciola Carballal
Copyright (c) 2014 Andrzej Krzemienski
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 Motivation]
Consider these functions which should return a value but which might not have
a value to return:
* (A) `double sqrt(double n );`
* (B) `char get_async_input();`
* (C) `point polygon::get_any_point_effectively_inside();`
There are different approaches to the issue of not having a value to return.
A typical approach is to consider the existence of a valid return value as a
postcondition, so that if the function cannot compute the value to return, it
has either undefined behavior (and can use assert in a debug build) or uses a
runtime check and throws an exception if the postcondition is violated. This
is a reasonable choice for example, for function (A), because the lack of a
proper return value is directly related to an invalid parameter (out of domain
argument), so it is appropriate to require the callee to supply only parameters
in a valid domain for execution to continue normally.
However, function (B), because of its asynchronous nature, does not fail just
because it can't find a value to return; so it is incorrect to consider such
a situation an error and assert or throw an exception. This function must
return, and somehow, must tell the callee that it is not returning a meaningful
value.
A similar situation occurs with function (C): it is conceptually an error to
ask a ['null-area] polygon to return a point inside itself, but in many
applications, it is just impractical for performance reasons to treat this as
an error (because detecting that the polygon has no area might be too expensive
to be required to be tested previously), and either an arbitrary point
(typically at infinity) is returned, or some efficient way to tell the callee
that there is no such point is used.
There are various mechanisms to let functions communicate that the returned
value is not valid. One such mechanism, which is quite common since it has
zero or negligible overhead, is to use a special value which is reserved to
communicate this. Classical examples of such special values are `EOF`,
`string::npos`, points at infinity, etc...
When those values exist, i.e. the return type can hold all meaningful values
['plus] the ['signal] value, this mechanism is quite appropriate and well known.
Unfortunately, there are cases when such values do not exist. In these cases,
the usual alternative is either to use a wider type, such as `int` in place of
`char`; or a compound type, such as `std::pair<point,bool>`.
Returning a `std::pair<T,bool>`, thus attaching a boolean flag to the result
which indicates if the result is meaningful, has the advantage that can be
turned into a consistent idiom since the first element of the pair can be
whatever the function would conceptually return. For example, the last two
functions could have the following interface:
std::pair<char,bool> get_async_input();
std::pair<point,bool> polygon::get_any_point_effectively_inside();
These functions use a consistent interface for dealing with possibly nonexistent
results:
std::pair<point,bool> p = poly.get_any_point_effectively_inside();
if ( p.second )
flood_fill(p.first);
However, not only is this quite a burden syntactically, it is also error prone
since the user can easily use the function result (first element of the pair)
without ever checking if it has a valid value.
Clearly, we need a better idiom.
[endsect]

View File

@ -2,6 +2,7 @@
[quickbook 1.4]
[authors [Cacciola Carballal, Fernando Luis]]
[copyright 2003-2007 Fernando Luis Cacciola Carballal]
[copyright 2014 Andrzej Krzemie&#324;ski]
[category miscellaneous]
[id optional]
[dirname optional]
@ -44,82 +45,23 @@ Distributed under the Boost Software License, Version 1.0.
[def __GO_TO__ [$images/callouts/R.png]]
[section Motivation]
[section Introduction]
This library can be used to represent 'optional' (or 'nullable') objects that can be safely passed by value:
Consider these functions which should return a value but which might not have
a value to return:
* (A) `double sqrt(double n );`
* (B) `char get_async_input();`
* (C) `point polygon::get_any_point_effectively_inside();`
There are different approaches to the issue of not having a value to return.
A typical approach is to consider the existence of a valid return value as a
postcondition, so that if the function cannot compute the value to return, it
has either undefined behavior (and can use assert in a debug build) or uses a
runtime check and throws an exception if the postcondition is violated. This
is a reasonable choice for example, for function (A), because the lack of a
proper return value is directly related to an invalid parameter (out of domain
argument), so it is appropriate to require the callee to supply only parameters
in a valid domain for execution to continue normally.
However, function (B), because of its asynchronous nature, does not fail just
because it can't find a value to return; so it is incorrect to consider such
a situation an error and assert or throw an exception. This function must
return, and somehow, must tell the callee that it is not returning a meaningful
value.
A similar situation occurs with function (C): it is conceptually an error to
ask a ['null-area] polygon to return a point inside itself, but in many
applications, it is just impractical for performance reasons to treat this as
an error (because detecting that the polygon has no area might be too expensive
to be required to be tested previously), and either an arbitrary point
(typically at infinity) is returned, or some efficient way to tell the callee
that there is no such point is used.
There are various mechanisms to let functions communicate that the returned
value is not valid. One such mechanism, which is quite common since it has
zero or negligible overhead, is to use a special value which is reserved to
communicate this. Classical examples of such special values are `EOF`,
`string::npos`, points at infinity, etc...
When those values exist, i.e. the return type can hold all meaningful values
['plus] the ['signal] value, this mechanism is quite appropriate and well known.
Unfortunately, there are cases when such values do not exist. In these cases,
the usual alternative is either to use a wider type, such as `int` in place of
`char`; or a compound type, such as `std::pair<point,bool>`.
Returning a `std::pair<T,bool>`, thus attaching a boolean flag to the result
which indicates if the result is meaningful, has the advantage that can be
turned into a consistent idiom since the first element of the pair can be
whatever the function would conceptually return. For example, the last two
functions could have the following interface:
std::pair<char,bool> get_async_input();
std::pair<point,bool> polygon::get_any_point_effectively_inside();
These functions use a consistent interface for dealing with possibly nonexistent
results:
std::pair<point,bool> p = poly.get_any_point_effectively_inside();
if ( p.second )
flood_fill(p.first);
However, not only is this quite a burden syntactically, it is also error prone
since the user can easily use the function result (first element of the pair)
without ever checking if it has a valid value.
Clearly, we need a better idiom.
optional<int> readInt(); // this function may return either an int or a not-an-int
if (optional<int> oi = readInt()) // did I get a real int
cout << "my int is: " << *oi; // use my int
else
cout << "I have no int";
[endsect]
[include motivation.qbk]
[include development.qbk]
[include reference.qbk]
[include examples.qbk]
[include special_cases.qbk]
[include implementation_notes.qbk]
[include dependencies.qbk]
[include acknowledgments.qbk]

View File

@ -22,30 +22,42 @@
// (If T is of reference type, the parameters and results by reference are by value)
optional () ; ``[link reference_optional_constructor __GO_TO__]``
optional () noexcept ; ``[link reference_optional_constructor __GO_TO__]``
optional ( none_t ) ; ``[link reference_optional_constructor_none_t __GO_TO__]``
optional ( none_t ) noexcept ; ``[link reference_optional_constructor_none_t __GO_TO__]``
optional ( T const& v ) ; ``[link reference_optional_constructor_value __GO_TO__]``
optional ( T&& v ) ; ``[link reference_optional_constructor_move_value __GO_TO__]``
// [new in 1.34]
optional ( bool condition, T const& v ) ; ``[link reference_optional_constructor_bool_value __GO_TO__]``
optional ( optional const& rhs ) ; ``[link reference_optional_constructor_optional __GO_TO__]``
optional ( optional&& rhs ) noexcept(``['see below]``) ; ``[link reference_optional_move_constructor_optional __GO_TO__]``
template<class U> explicit optional ( optional<U> const& rhs ) ; ``[link reference_optional_constructor_other_optional __GO_TO__]``
template<class U> explicit optional ( optional<U>&& rhs ) ; ``[link reference_optional_move_constructor_other_optional __GO_TO__]``
template<class InPlaceFactory> explicit optional ( InPlaceFactory const& f ) ; ``[link reference_optional_constructor_factory __GO_TO__]``
template<class TypedInPlaceFactory> explicit optional ( TypedInPlaceFactory const& f ) ; ``[link reference_optional_constructor_factory __GO_TO__]``
optional& operator = ( none_t ) ; ``[/[link reference_optional_operator_equal_none_t __GO_TO__]]``
optional& operator = ( none_t ) noexcept ; ``[link reference_optional_operator_equal_none_t __GO_TO__]``
optional& operator = ( T const& v ) ; ``[link reference_optional_operator_equal_value __GO_TO__]``
optional& operator = ( T&& v ) ; ``[link reference_optional_operator_move_equal_value __GO_TO__]``
optional& operator = ( optional const& rhs ) ; ``[link reference_optional_operator_equal_optional __GO_TO__]``
optional& operator = ( optional&& rhs ) noexcept(``['see below]``) ; ``[link reference_optional_operator_move_equal_optional __GO_TO__]``
template<class U> optional& operator = ( optional<U> const& rhs ) ; ``[link reference_optional_operator_equal_other_optional __GO_TO__]``
template<class U> optional& operator = ( optional<U>&& rhs ) ; ``[link reference_optional_operator_move_equal_other_optional __GO_TO__]``
template<class InPlaceFactory> optional& operator = ( InPlaceFactory const& f ) ; ``[link reference_optional_operator_equal_factory __GO_TO__]``
@ -66,14 +78,14 @@
T const* get_ptr() const ; ``[link reference_optional_get_ptr __GO_TO__]``
T* get_ptr() ; ``[link reference_optional_get_ptr __GO_TO__]``
operator unspecified-bool-type() const ; ``[link reference_optional_operator_bool __GO_TO__]``
explicit operator bool() const ; ``[link reference_optional_operator_bool __GO_TO__]``
bool operator!() const ; ``[link reference_optional_operator_not __GO_TO__]``
bool operator!() const noexcept ; ``[link reference_optional_operator_not __GO_TO__]``
// deprecated methods
// (deprecated)
void reset() ; ``[link reference_optional_reset __GO_TO__]``
void reset() noexcept ; ``[link reference_optional_reset __GO_TO__]``
// (deprecated)
void reset ( T const& ) ; ``[link reference_optional_reset_value __GO_TO__]``
@ -94,6 +106,10 @@
template<class T> inline bool operator <= ( optional<T> const& x, optional<T> const& y ) ; ``[link reference_operator_compare_less_or_equal_optional_optional __GO_TO__]``
template<class T> inline bool operator >= ( optional<T> const& x, optional<T> const& y ) ; ``[link reference_operator_compare_greater_or_equal_optional_optional __GO_TO__]``
template<class T> inline bool operator == ( optional<T> const& x, none_t ) noexcept ; ``[link reference_operator_compare_equal_optional_none __GO_TO__]``
template<class T> inline bool operator != ( optional<T> const& x, none_t ) noexcept ; ``[link reference_operator_compare_not_equal_optional_none __GO_TO__]``
// [new in 1.34]
template<class T> inline optional<T> make_optional ( T const& v ) ; ``[link reference_make_optional_value __GO_TO__]``
@ -151,12 +167,11 @@ __SPACE__
[#reference_optional_constructor]
[: `optional<T>::optional();`]
[: `optional<T>::optional() noexcept;`]
* [*Effect:] Default-Constructs an `optional`.
* [*Postconditions:] `*this` is [_uninitialized].
* [*Throws:] Nothing.
* Notes: T's default constructor [_is not] called.
* [*Notes:] T's default constructor [_is not] called.
* [*Example:]
``
optional<T> def ;
@ -167,11 +182,10 @@ __SPACE__
[#reference_optional_constructor_none_t]
[: `optional<T>::optional( none_t );`]
[: `optional<T>::optional( none_t ) noexcept;`]
* [*Effect:] Constructs an `optional` uninitialized.
* [*Postconditions:] `*this` is [_uninitialized].
* [*Throws:] Nothing.
* [*Notes:] `T`'s default constructor [_is not] called. The expression
`boost::none` denotes an instance of `boost::none_t` that can be used as
the parameter.
@ -188,8 +202,9 @@ __SPACE__
[: `optional<T `['(not a ref)]`>::optional( T const& v )`]
* [*Requires:] `is_copy_constructible<T>::value` is `true`.
* [*Effect:] Directly-Constructs an `optional`.
* [*Postconditions:] `*this` is [_initialized] and its value is a['copy]
* [*Postconditions:] `*this` is [_initialized] and its value is a ['copy]
of `v`.
* [*Throws:] Whatever `T::T( T const& )` throws.
* [*Notes: ] `T::T( T const& )` is called.
@ -220,6 +235,33 @@ assert ( *opt == v ) ;
assert (*opt == v);
``
__SPACE__
[#reference_optional_constructor_move_value]
[: `optional<T `['(not a ref)]`>::optional( T&& v )`]
* [*Requires:] `is_move_constructible<T>::value` is `true`.
* [*Effect:] Directly-Move-Constructs an `optional`.
* [*Postconditions:] `*this` is [_initialized] and its value is move-constructed from `v`.
* [*Throws:] Whatever `T::T( T&& )` throws.
* [*Notes: ] `T::T( T&& )` is called.
* [*Exception Safety:] Exceptions can only be thrown during
`T::T( T&& );` in that case, the state of `v` is determined by exception safety guarantees for `T::T(T&&)`.
* [*Example:]
``
T v1, v2;
optional<T> opt(std::move(v1));
assert ( *opt == v2 ) ;
``
__SPACE__
[: `optional<T&>::optional( T&& ref ) = delete`]
* [*Notes:] This constructor is deleted
__SPACE__
[#reference_optional_constructor_bool_value]
@ -243,6 +285,7 @@ __SPACE__
[: `optional<T `['(not a ref)]`>::optional( optional const& rhs );`]
* [*Requires:] `is_copy_constructible<T>::value` is `true`.
* [*Effect:] Copy-Constructs an `optional`.
* [*Postconditions:] If rhs is initialized, `*this` is initialized and
its value is a ['copy] of the value of `rhs`; else `*this` is uninitialized.
@ -299,6 +342,70 @@ assert ( *init2 == 3 ) ;
__SPACE__
[#reference_optional_move_constructor_optional]
[: `optional<T `['(not a ref)]`>::optional( optional&& rhs ) noexcept(`['see below]`);`]
* [*Requires:] `is_move_constructible<T>::value` is `true`.
* [*Effect:] Move-constructs an `optional`.
* [*Postconditions:] If `rhs` is initialized, `*this` is initialized and
its value is move constructed from `rhs`; else `*this` is uninitialized.
* [*Throws:] Whatever `T::T( T&& )` throws.
* [*Notes:] If `rhs` is initialized, `T::T( T && )` is called. The expression inside `noexcept` is equivalent to `is_nothrow_move_constructible<T>::value`.
* [*Exception Safety:] Exceptions can only be thrown during
`T::T( T&& );` in that case, `rhs` remains initialized and the value of `*rhs` is determined by exception safety of `T::T(T&&)`.
* [*Example:]
``
optional<std::unique_ptr<T>> uninit ;
assert (!uninit);
optional<std::unique_ptr<T>> uinit2 ( std::move(uninit) ) ;
assert ( uninit2 == uninit );
optional<std::unique_ptr<T>> init( std::uniqye_ptr<T>(new T(2)) );
assert ( **init == T(2) ) ;
optional<std::unique_ptr<T>> init2 ( std::move(init) ) ;
assert ( init );
assert ( *init == nullptr );
assert ( init2 );
assert ( **init2 == T(2) ) ;
``
__SPACE__
[: `optional<T&>::optional( optional && rhs );`]
* [*Effect:] Move-Constructs an `optional`.
* [*Postconditions:] If `rhs` is initialized, `*this` is initialized and its
value is another reference to the same object referenced by `*rhs`; else
`*this` is uninitialized.
* [*Throws:] Nothing.
* [*Notes:] If `rhs` is initialized, both `*this` and `*rhs` will reefer to the
same object (they alias).
* [*Example:]
``
optional<std::unique_ptr<T>&> uninit ;
assert (!uninit);
optional<std::unique_ptr<T>&> uinit2 ( std::move(uninit) ) ;
assert ( uninit2 == uninit );
std::unique_ptr<T> v(new T(2)) ;
optional<std::unique_ptr<T>&> init(v);
assert ( *init == v ) ;
optional<std::unique_ptr<T>&> init2 ( std::move(init) ) ;
assert ( *init2 == v ) ;
*v = 3 ;
assert ( **init == 3 ) ;
assert ( **init2 == 3 ) ;
``
__SPACE__
[#reference_optional_constructor_other_optional]
[: `template<U> explicit optional<T` ['(not a ref)]`>::optional( optional<U> const& rhs );`]
@ -323,6 +430,30 @@ assert( *y == 123 ) ;
__SPACE__
[#reference_optional_move_constructor_other_optional]
[: `template<U> explicit optional<T` ['(not a ref)]`>::optional( optional<U>&& rhs );`]
* [*Effect:] Move-constructs an `optional`.
* [*Postconditions:] If `rhs` is initialized, `*this` is initialized and its
value is move constructed from `*rhs`; else `*this` is
uninitialized.
* [*Throws:] Whatever `T::T( U&& )` throws.
* [*Notes: ] `T::T( U&& )` is called if `rhs` is initialized, which requires a
valid conversion from `U` to `T`.
* [*Exception Safety:] Exceptions can only be thrown during `T::T( U&& );`
in that case, `rhs` remains initialized and the value of `*rhs` is determined by exception safety guarantee of `T::T( U&& )`.
* [*Example:]
``
optional<double> x(123.4);
assert ( *x == 123.4 ) ;
optional<int> y(std::move(x)) ;
assert( *y == 123 ) ;
``
__SPACE__
[#reference_optional_constructor_factory]
[: `template<InPlaceFactory> explicit optional<T` ['(not a ref)]`>::optional( InPlaceFactory const& f );`]
@ -352,6 +483,15 @@ assert ( *y == v ) ;
__SPACE__
[#reference_optional_operator_equal_none_t]
[: `optional& optional<T>::operator= ( none_t ) noexcept;`]
* [*Effect:] If `*this` is initialized destroys its contained value.
* [*Postconditions: ] `*this` is uninitialized.
__SPACE__
[#reference_optional_operator_equal_value]
[: `optional& optional<T` ['(not a ref)]`>::operator= ( T const& rhs ) ;`]
@ -408,6 +548,42 @@ c = 4 ;
assert ( *opt == 4 ) ;
``
__SPACE__
[#reference_optional_operator_move_equal_value]
[: `optional& optional<T` ['(not a ref)]`>::operator= ( T&& rhs ) ;`]
* [*Effect:] Moves the value `rhs` to an `optional`.
* [*Postconditions: ] `*this` is initialized and its value is moved from `rhs`.
* [*Throws:] Whatever `T::operator=( T&& )` or `T::T(T &&)` throws.
* [*Notes:] If `*this` was initialized, `T`'s move-assignment operator is used,
otherwise, its move-constructor is used.
* [*Exception Safety:] In the event of an exception, the initialization
state of `*this` is unchanged and its value unspecified as far as `optional`
is concerned (it is up to `T`'s `operator=()`). If `*this` is initially
uninitialized and `T`'s ['move constructor] fails, `*this` is left properly
uninitialized.
* [*Example:]
``
T x;
optional<T> def ;
optional<T> opt(x) ;
T y1, y2, yR;
def = std::move(y1) ;
assert ( *def == yR ) ;
opt = std::move(y2) ;
assert ( *opt == yR ) ;
``
__SPACE__
[: `optional<T&>& optional<T&>::operator= ( T&& rhs ) = delete;`]
* [*Notes:] This assignment operator is deleted.
__SPACE__
[#reference_optional_operator_equal_optional]
@ -471,6 +647,42 @@ assert ( *ora == 4 ) ;
__SPACE__
[#reference_optional_operator_move_equal_optional]
[: `optional& optional<T` ['(not a ref)]`>::operator= ( optional&& rhs ) noexcept(`['see below]`);`]
* [*Effect:] Move-assigns another `optional` to an `optional`.
* [*Postconditions:] If `rhs` is initialized, `*this` is initialized and
its value is moved from `*rhs`, `rhs` remains initialized; else `*this` is uninitialized.
* [*Throws:] Whatever `T::operator( T&& )` or `T::T( T && )` throws.
* [*Notes:] If both `*this` and `rhs` are initially initialized, `T`'s
['move assignment operator] is used. If `*this` is initially initialized but `rhs` is
uninitialized, `T`'s [destructor] is called. If `*this` is initially uninitialized
but `rhs` is initialized, `T`'s ['move constructor] is called. The expression inside `noexcept` is equivalent to `is_nothrow_move_constructible<T>::value && is_nothrow_move_assignable<T>::value`.
* [*Exception Safety:] In the event of an exception, the initialization state of
`*this` is unchanged and its value unspecified as far as optional is concerned
(it is up to `T`'s `operator=()`). If `*this` is initially uninitialized and
`T`'s ['move constructor] fails, `*this` is left properly uninitialized.
* [*Example:]
``
optional<T> opt(T(2)) ;
optional<T> def ;
opt = def ;
assert ( def ) ;
assert ( opt ) ;
assert ( *opt == T(2) ) ;
``
__SPACE__
[: `optional<T&> & optional<T&>::operator= ( optional<T&>&& rhs ) ;`]
* [*Effect:] Same as `optional<T&>::operator= ( optional<T&> const& rhs )`.
__SPACE__
[#reference_optional_operator_equal_other_optional]
[: `template<U> optional& optional<T` ['(not a ref)]`>::operator= ( optional<U> const& rhs ) ;`]
@ -502,6 +714,37 @@ assert ( *opt1 == static_cast<U>(v) ) ;
__SPACE__
[#reference_optional_operator_move_equal_other_optional]
[: `template<U> optional& optional<T` ['(not a ref)]`>::operator= ( optional<U>&& rhs ) ;`]
* [*Effect:] Move-assigns another convertible optional to an optional.
* [*Postconditions:] If `rhs` is initialized, `*this` is initialized and
its value is moved from the value of `rhs`; else
`*this` is uninitialized.
* [*Throws:] Whatever `T::operator=( U&& )` or `T::T( U&& )` throws.
* [*Notes:] If both `*this` and `rhs` are initially initialized, `T`'s
[' assignment operator] (from `U&&`) is used. If `*this` is initially initialized
but `rhs` is uninitialized, `T`'s ['destructor] is called. If `*this` is
initially uninitialized but `rhs` is initialized, `T`'s ['converting constructor]
(from `U&&`) is called.
* [*Exception Safety:] In the event of an exception, the initialization state
of `*this` is unchanged and its value unspecified as far as optional is
concerned (it is up to `T`'s `operator=()`). If `*this` is initially
uninitialized and `T`'s converting constructor fails, `*this` is left properly
uninitialized.
* [*Example:]
``
T v;
optional<T> opt0(v);
optional<U> opt1;
opt1 = std::move(opt0) ;
assert ( *opt1 == static_cast<U>(v) ) ;
``
__SPACE__
[#reference_optional_operator_equal_factory]
[: `template<InPlaceFactory> optional<T>& optional<T` ['(not a ref)]`>::operator=( InPlaceFactory const& f );`]
@ -528,7 +771,7 @@ __SPACE__
[#reference_optional_reset]
[: `void optional<T>::reset() ;`]
[: `void optional<T>::reset() noexcept ;`]
* [*Deprecated:] Same as `operator=( detail::none_t );`
__SPACE__
@ -543,7 +786,7 @@ __SPACE__
[: `inline T const& get ( optional<T` ['(not a ref)]`> const& ) ;`]
[: `inline T& get ( optional<T` ['(not a ref)]`> &) ;`]
* [*Requirements:] `*this` is initialized
* [*Requires:] `*this` is initialized
* [*Returns:] A reference to the contained value
* [*Throws:] Nothing.
* [*Notes:] The requirement is asserted via `BOOST_ASSERT()`.
@ -593,7 +836,7 @@ __SPACE__
[: `inline T const& get ( optional<T&> const& ) ;`]
[: `inline T& get ( optional<T&> &) ;`]
* [*Requirements: ] `*this` is initialized
* [*Requires: ] `*this` is initialized
* [*Returns:] [_The] reference contained.
* [*Throws:] Nothing.
* [*Notes:] The requirement is asserted via `BOOST_ASSERT()`.
@ -641,7 +884,7 @@ __SPACE__
[: `T const* optional<T` ['(not a ref)]`>::operator ->() const ;`]
[: `T* optional<T` ['(not a ref)]`>::operator ->() ;`]
* [*Requirements: ] `*this` is initialized.
* [*Requires: ] `*this` is initialized.
* [*Returns:] A pointer to the contained value.
* [*Throws:] Nothing.
* [*Notes:] The requirement is asserted via `BOOST_ASSERT()`.
@ -657,11 +900,11 @@ __SPACE__
[#reference_optional_operator_bool]
[: `optional<T>::operator `['unspecified-bool-type]`() const ;`]
[: `explicit optional<T>::operator bool() const ;`]
* [*Returns:] An unspecified value which if used on a boolean context
is equivalent to (`get_ptr() != 0`)
* [*Returns:] `get_ptr() != 0`.
* [*Throws:] Nothing.
* [*Notes:] On compilers that do not support explicit conversion operators this falls back to safe-bool idiom.
* [*Example:]
``
optional<T> def ;
@ -675,10 +918,9 @@ __SPACE__
[#reference_optional_operator_not]
[: `bool optional<T>::operator!() ;`]
[: `bool optional<T>::operator!() noexcept ;`]
* [*Returns:] If `*this` is uninitialized, `true`; else `false`.
* [*Throws:] Nothing.
* [*Notes:] This operator is provided for those compilers which can't
use the ['unspecified-bool-type operator] in certain boolean contexts.
* [*Example:]
@ -697,7 +939,7 @@ __SPACE__
[: `bool optional<T>::is_initialized() const ;`]
* [*Deprecated:] Same as `operator `['unspecified-bool-type]`() ;`
* [*Deprecated:] Same as `explicit operator bool () ;`
__SPACE__
@ -743,6 +985,7 @@ __SPACE__
[: `bool operator == ( optional<T> const& x, optional<T> const& y );`]
* [*Requires:] `T` shall meet requirements of `EqualityComparable`.
* [*Returns:] If both `x` and `y` are initialized, `(*x == *y)`. If only
`x` or `y` is initialized, `false`. If both are uninitialized, `true`.
* [*Throws:] Nothing.
@ -782,6 +1025,7 @@ __SPACE__
[: `bool operator < ( optional<T> const& x, optional<T> const& y );`]
* [*Requires:] `T` shall meet requirements of `LessThanComparable`.
* [*Returns:] If `y` is not initialized, `false`. If `y` is initialized
and `x` is not initialized, `true`. If both `x` and `y` are initialized,
`(*x < *y)`.
@ -836,7 +1080,7 @@ __SPACE__
[: `bool operator <= ( optional<T> const& x, optional<T> const& y );`]
* [*Returns: ] `!( y<x );`
* [*Returns: ] `!( y < x );`
* [*Throws:] Nothing.
__SPACE__
@ -848,25 +1092,42 @@ __SPACE__
* [*Returns: ] `!( x<y );`
* [*Throws:] Nothing.
[#reference_operator_compare_equal_optional_none]
[: `bool operator == ( optional<T> const& x, none_t ) noexcept;`]
* [*Returns:] `!x`.
* [*Notes:] `T` need not meet requirements of `EqualityComparable`.
__SPACE__
[#reference_operator_compare_not_equal_optional_none]
[: `bool operator != ( optional<T> const& x, none_t ) noexcept;`]
* [*Returns: ] `!( x == y );`
__SPACE__
[#reference_swap_optional_optional]
[: `void swap ( optional<T>& x, optional<T>& y );`]
[: `void swap ( optional<T>& x, optional<T>& y ) ;`]
* [*Effect:] If both `x` and `y` are initialized, calls `swap(*x,*y)`
using `std::swap`. If only one is initialized, say `x`, calls:
`y.reset(*x); x.reset();` If none is initialized, does nothing.
* [*Postconditions:] The states of `x` and `y` interchanged.
* [*Throws:] If both are initialized, whatever `swap(T&,T&)` throws. If only
one is initialized, whatever `T::T ( T const& )` throws.
one is initialized, whatever `T::T ( T&& )` throws.
* [*Notes:] If both are initialized, `swap(T&,T&)` is used unqualified but
with `std::swap` introduced in scope.
If only one is initialized, `T::~T()` and `T::T( T const& )` is called.
If only one is initialized, `T::~T()` and `T::T( T&& )` is called.
* [*Exception Safety:] If both are initialized, this operation has the
exception safety guarantees of `swap(T&,T&)`.
If only one is initialized, it has the same basic guarantee as
`optional<T>::reset( T const& )`.
`optional<T>::operator= ( T&& )`.
* [*Example:]
``
T x(12);

View File

@ -17,10 +17,19 @@ Also, even though `optional<T&>` treats it wrapped pseudo-object much as
a real value, a true real reference is stored so aliasing will ocurr:
* Copies of `optional<T&>` will copy the references but all these references
will nonetheless reefer to the same object.
will nonetheless refer to the same object.
* Value-access will actually provide access to the referenced object
rather than the reference itself.
[warning On compilers that do not conform to Standard C++ rules of reference binding, operations on optional references might give adverse results: rather than binding a reference to a designated object they may create an unexpected temporary and bind to it. For more details see [link boost_optional.dependencies_and_portability.optional_reference_binding Dependencies and Portability section].]
[heading Rvalue references]
Rvalue references and lvalue references to const have the ability in C++ to extend the life time of a temporary they bind to. Optional references do not have this capability, therefore to avoid surprising effects it is not possible to initialize an optional references from a temporary. Optional rvalue references are disabled altogether. Also, the initialization and assignment of an optional reference to const from rvalue reference is disabled.
const int& i = 1; // legal
optional<const int&> oi = 1; // illegal
[endsect]
[section Rebinding semantics for assignment of optional references]
@ -253,17 +262,17 @@ The factories are implemented in the headers: __IN_PLACE_FACTORY_HPP__ and __TYP
`optional<bool>` should be used with special caution and consideration.
First, it is functionally similar to a tristate boolean (false,maybe,true)
First, it is functionally similar to a tristate boolean (false, maybe, true)
—such as __BOOST_TRIBOOL__— except that in a tristate boolean, the maybe state
[_represents a valid value], unlike the corresponding state of an uninitialized
`optional<bool>`.
It should be carefully considered if an `optional<bool>` instead of a `tribool`
is really needed.
Second, `optional<>` provides an implicit conversion to `bool`. This
conversion refers to the initialization state and not to the contained value.
Using `optional<bool>` can lead to subtle errors due to the implicit `bool`
conversion:
Second, although `optional<>` provides a contextual conversion to `bool` in C++11,
this falls back to an implicit conversion on older compilers. This conversion refers
to the initialization state and not to the contained value. Using `optional<bool>`
can lead to subtle errors due to the implicit `bool` conversion:
void foo ( bool v ) ;
void bar()
@ -280,90 +289,84 @@ The only implicit conversion is to `bool`, and it is safe in the sense that
typical integral promotions don't apply (i.e. if `foo()` takes an `int`
instead, it won't compile).
Third, mixed comparisons with `bool` work differently than similar mixed comparisons between pointers and `bool`, so the results might surprise you:
optional<bool> oEmpty(none), oTrue(true), oFalse(false);
if (oEmpty == none); // renders true
if (oEmpty == false); // renders false!
if (oEmpty == true); // renders false!
if (oFalse == none); // renders false
if (oFalse == false); // renders true!
if (oFalse == true); // renders false
if (oTrue == none); // renders false
if (oTrue == false); // renders false
if (oTrue == true); // renders true
In other words, for `optional<>`, the following assertion does not hold:
assert((opt == false) == (!opt));
[endsect]
[section Exception Safety Guarantees]
Because of the current implementation (see [link boost_optional.implementation_notes Implementation Notes]), all of the assignment methods:
This library assumes that `T`'s destructor does not throw exceptions. If it does, the behaviour of many operations on `optional<T>` is undefined.
The following mutating operations never throw exceptions:
* `optional<T>::operator= ( none_t ) noexcept`
* `optional<T>::reset() noexcept`
In addition, the following constructors and the destructor never throw exceptions:
* `optional<T>::optional() noexcept`
* `optional<T>::optional( none_t ) noexcept`
Regarding the following assignment functions:
* `optional<T>::operator= ( optional<T> const& )`
* `optional<T>::operator= ( T const& )`
* `template<class U> optional<T>::operator= ( optional<U> const& )`
* `template<class InPlaceFactory> optional<T>::operator= ( InPlaceFactory const& )`
* `template<class TypedInPlaceFactory> optional<T>::operator= ( TypedInPlaceFactory const& ) `
* `optional<T>::reset ( T const&)`
* `optional<T>::reset( T const& )`
Can only ['guarantee] the [_basic exception safety]: The lvalue optional is
left [_uninitialized] if an exception is thrown (any previous value is ['first]
destroyed using `T::~T()`)
They forward calls to the corresponding `T`'s constructors or assignments (depending on whether the optional object is initialized or not); so if both `T`'s constructor and the assignment provide strong exception safety guarantee, `optional<T>`'s assignment also provides strong exception safety guarantee; otherwise we only get the basic guarantee. Additionally, if both involved `T`'s constructor and the assignment never throw, `optional<T>`'s assignment also never throws.
On the other hand, the ['uninitializing] methods:
Unless `T`'s constructor or assignment throws, `optional<T>` does not throw anything else on its own. A throw during assignment never changes the initialization state of any optional object involved:
* `optional<T>::operator= ( detail::none_t )`
* `optional<T>::reset()`
Provide the no-throw guarantee (assuming a no-throw `T::~T()`)
However, since `optional<>` itself doesn't throw any exceptions, the only
source for exceptions here are `T`'s constructor, so if you know the exception
guarantees for `T::T ( T const& )`, you know that `optional`'s assignment and
reset has the same guarantees.
//
// Case 1: Exception thrown during assignment.
//
T v0(123);
optional<T> opt0(v0);
optional<T> opt1(val1);
optional<T> opt2(val2);
assert(opt1);
assert(opt2);
try
{
T v1(456);
optional<T> opt1(v1);
opt0 = opt1 ;
// If no exception was thrown, assignment succeeded.
assert( *opt0 == v1 ) ;
opt1 = opt2; // throws
}
catch(...)
{
// If any exception was thrown, 'opt0' is reset to uninitialized.
assert( !opt0 ) ;
assert(opt1);
assert(opt2);
}
//
// Case 2: Exception thrown during reset(v)
//
T v0(123);
optional<T> opt(v0);
try
{
T v1(456);
opt.reset ( v1 ) ;
// If no exception was thrown, reset succeeded.
assert( *opt == v1 ) ;
}
catch(...)
{
// If any exception was thrown, 'opt' is reset to uninitialized.
assert( !opt ) ;
}
This also applies to move assignments/constructors. However, move operations are made no-throw more often.
[heading Swap]
`void swap( optional<T>&, optional<T>& )` has the same exception guarantee
as `swap(T&,T&)` when both optionals are initialized.
If only one of the optionals is initialized, it gives the same ['basic]
exception guarantee as `optional<T>::reset( T const& )` (since
`optional<T>::reset()` doesn't throw).
If none of the optionals is initialized, it has no-throw guarantee
since it is a no-op.
Unless `swap` on optional is customized, its primary implementation forwards calls to `T`'s `swap` or move constructor (depending on the initialization state of the optional objects). Thus, if both `T`'s `swap` and move constructor never throw, `swap` on `optional<T>` never throws. similarly, if both `T`'s `swap` and move constructor offer strong guarantee, `swap` on `optional<T>` also offers a strong guarantee.
In case `swap` on optional is customized, the call to `T`'s move constructor are replaced with the calls to `T`'s default constructor followed by `swap`. (This is more useful on older compilers that do not support move semantics, when one wants to acheive stronger exception safety guarantees.) In this case the exception safety guarantees for `swap` are reliant on the guarantees of `T`'s `swap` and default constructor
[endsect]
[section Type requirements]
In general, `T` must be __COPY_CONSTRUCTIBLE__ and have a no-throw destructor.
The copy-constructible requirement is not needed if [*InPlaceFactories] are used.
In general, `T` must be `MoveConstructible` and have a no-throw destructor.
The `MoveConstructible` requirement is not needed if [*InPlaceFactories] are used.
`T` [_is not] required to be __SGI_DEFAULT_CONSTRUCTIBLE__.

View File

@ -1,4 +1,5 @@
// Copyright (C) 2003, 2008 Fernando Luis Cacciola Carballal.
// Copyright (C) 2014 Andrzej Krzemienski.
//
// Use, modification, and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
@ -11,6 +12,7 @@
//
// Revisions:
// 27 Apr 2008 (improved swap) Fernando Cacciola, Niels Dekker, Thorsten Ottosen
// 05 May 2014 (Added move semantics) Andrzej Krzemienski
//
#ifndef BOOST_OPTIONAL_OPTIONAL_FLC_19NOV2002_HPP
#define BOOST_OPTIONAL_OPTIONAL_FLC_19NOV2002_HPP
@ -21,21 +23,35 @@
#include <boost/config.hpp>
#include <boost/assert.hpp>
#include <boost/static_assert.hpp>
#include <boost/type.hpp>
#include <boost/type_traits/alignment_of.hpp>
#include <boost/type_traits/has_nothrow_constructor.hpp>
#include <boost/type_traits/type_with_alignment.hpp>
#include <boost/type_traits/remove_const.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/type_traits/decay.hpp>
#include <boost/type_traits/is_base_of.hpp>
#include <boost/type_traits/is_lvalue_reference.hpp>
#include <boost/type_traits/is_nothrow_move_assignable.hpp>
#include <boost/type_traits/is_nothrow_move_constructible.hpp>
#include <boost/type_traits/is_reference.hpp>
#include <boost/type_traits/is_rvalue_reference.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/not.hpp>
#include <boost/detail/reference_content.hpp>
#include <boost/move/utility.hpp>
#include <boost/none.hpp>
#include <boost/utility/swap.hpp>
#include <boost/utility/addressof.hpp>
#include <boost/utility/compare_pointees.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/utility/explicit_operator_bool.hpp>
#include <boost/utility/in_place_factory.hpp>
#include <boost/utility/swap.hpp>
#include <boost/optional/optional_fwd.hpp>
@ -131,22 +147,41 @@ struct types_when_isnt_ref
{
typedef T const& reference_const_type ;
typedef T & reference_type ;
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
typedef T && rval_reference_type ;
static rval_reference_type move(reference_type r) { return boost::move(r); }
#endif
typedef T const* pointer_const_type ;
typedef T * pointer_type ;
typedef T const& argument_type ;
} ;
template<class T>
struct types_when_is_ref
{
typedef BOOST_DEDUCED_TYPENAME remove_reference<T>::type raw_type ;
typedef raw_type& reference_const_type ;
typedef raw_type& reference_type ;
typedef raw_type* pointer_const_type ;
typedef raw_type* pointer_type ;
typedef raw_type& argument_type ;
typedef raw_type& reference_const_type ;
typedef raw_type& reference_type ;
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
typedef BOOST_DEDUCED_TYPENAME remove_const<raw_type>::type&& rval_reference_type ;
static reference_type move(reference_type r) { return r; }
#endif
typedef raw_type* pointer_const_type ;
typedef raw_type* pointer_type ;
typedef raw_type& argument_type ;
} ;
template <class To, class From>
void prevent_binding_rvalue_ref_to_optional_lvalue_ref()
{
#ifndef BOOST_OPTIONAL_ALLOW_BINDING_TO_RVALUES
BOOST_STATIC_ASSERT_MSG(
!boost::is_lvalue_reference<To>::value || !boost::is_rvalue_reference<From>::value,
"binding rvalue references to optional lvalue references is disallowed");
#endif
}
struct optional_tag {} ;
template<class T>
@ -180,10 +215,11 @@ class optional_base : public optional_tag
typedef BOOST_DEDUCED_TYPENAME mpl::if_<is_reference_predicate,types_when_ref,types_when_not_ref>::type types ;
protected:
typedef bool (this_type::*unspecified_bool_type)() const;
typedef BOOST_DEDUCED_TYPENAME types::reference_type reference_type ;
typedef BOOST_DEDUCED_TYPENAME types::reference_const_type reference_const_type ;
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
typedef BOOST_DEDUCED_TYPENAME types::rval_reference_type rval_reference_type ;
#endif
typedef BOOST_DEDUCED_TYPENAME types::pointer_type pointer_type ;
typedef BOOST_DEDUCED_TYPENAME types::pointer_const_type pointer_const_type ;
typedef BOOST_DEDUCED_TYPENAME types::argument_type argument_type ;
@ -209,6 +245,17 @@ class optional_base : public optional_tag
construct(val);
}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
// move-construct an optional<T> initialized from an rvalue-ref to 'val'.
// Can throw if T::T(T&&) does
optional_base ( rval_reference_type val )
:
m_initialized(false)
{
construct( boost::move(val) );
}
#endif
// Creates an optional<T> initialized with 'val' IFF cond is true, otherwise creates an uninitialzed optional<T>.
// Can throw if T::T(T const&) does
optional_base ( bool cond, argument_type val )
@ -229,7 +276,29 @@ class optional_base : public optional_tag
construct(rhs.get_impl());
}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
// Creates a deep move of another optional<T>
// Can throw if T::T(T&&) does
optional_base ( optional_base&& rhs )
:
m_initialized(false)
{
if ( rhs.is_initialized() )
construct( boost::move(rhs.get_impl()) );
}
#endif
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
template<class Expr, class PtrExpr>
explicit optional_base ( Expr&& expr, PtrExpr const* tag )
:
m_initialized(false)
{
construct(boost::forward<Expr>(expr),tag);
}
#else
// This is used for both converting and in-place constructions.
// Derived classes use the 'tag' to select the appropriate
// implementation (the correct 'construct()' overload)
@ -241,6 +310,7 @@ class optional_base : public optional_tag
construct(expr,tag);
}
#endif
// No-throw (assuming T::~T() doesn't)
@ -261,6 +331,24 @@ class optional_base : public optional_tag
construct(rhs.get_impl());
}
}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
// Assigns from another optional<T> (deep-moves the rhs value)
void assign ( optional_base&& rhs )
{
if (is_initialized())
{
if ( rhs.is_initialized() )
assign_value(boost::move(rhs.get_impl()), is_reference_predicate() );
else destroy();
}
else
{
if ( rhs.is_initialized() )
construct(boost::move(rhs.get_impl()));
}
}
#endif
// Assigns from another _convertible_ optional<U> (deep-copies the rhs value)
template<class U>
@ -279,6 +367,26 @@ class optional_base : public optional_tag
}
}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
// move-assigns from another _convertible_ optional<U> (deep-moves from the rhs value)
template<class U>
void assign ( optional<U>&& rhs )
{
typedef BOOST_DEDUCED_TYPENAME optional<U>::rval_reference_type ref_type;
if (is_initialized())
{
if ( rhs.is_initialized() )
assign_value(static_cast<ref_type>(rhs.get()), is_reference_predicate() );
else destroy();
}
else
{
if ( rhs.is_initialized() )
construct(static_cast<ref_type>(rhs.get()));
}
}
#endif
// Assigns from a T (deep-copies the rhs value)
void assign ( argument_type val )
{
@ -286,26 +394,48 @@ class optional_base : public optional_tag
assign_value(val, is_reference_predicate() );
else construct(val);
}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
// Assigns from a T (deep-moves the rhs value)
void assign ( rval_reference_type val )
{
if (is_initialized())
assign_value( boost::move(val), is_reference_predicate() );
else construct( boost::move(val) );
}
#endif
// Assigns from "none", destroying the current value, if any, leaving this UNINITIALIZED
// No-throw (assuming T::~T() doesn't)
void assign ( none_t ) { destroy(); }
void assign ( none_t ) BOOST_NOEXCEPT { destroy(); }
#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
template<class Expr, class ExprPtr>
void assign_expr ( Expr&& expr, ExprPtr const* tag )
{
if (is_initialized())
assign_expr_to_initialized(boost::forward<Expr>(expr),tag);
else construct(boost::forward<Expr>(expr),tag);
}
#else
template<class Expr>
void assign_expr ( Expr const& expr, Expr const* tag )
{
if (is_initialized())
assign_expr_to_initialized(expr,tag);
else construct(expr,tag);
}
{
if (is_initialized())
assign_expr_to_initialized(expr,tag);
else construct(expr,tag);
}
#endif
#endif
public :
// Destroys the current value, if any, leaving this UNINITIALIZED
// No-throw (assuming T::~T() doesn't)
void reset() { destroy(); }
void reset() BOOST_NOEXCEPT { destroy(); }
// Replaces the current value -if any- with 'val'
void reset ( argument_type val ) { assign(val); }
@ -325,8 +455,51 @@ class optional_base : public optional_tag
new (m_storage.address()) internal_type(val) ;
m_initialized = true ;
}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
void construct ( rval_reference_type val )
{
new (m_storage.address()) internal_type( types::move(val) ) ;
m_initialized = true ;
}
#endif
#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
// Constructs in-place using the given factory
template<class Expr>
void construct ( Expr&& factory, in_place_factory_base const* )
{
BOOST_STATIC_ASSERT ( ::boost::mpl::not_<is_reference_predicate>::value ) ;
boost_optional_detail::construct<value_type>(factory, m_storage.address());
m_initialized = true ;
}
// Constructs in-place using the given typed factory
template<class Expr>
void construct ( Expr&& factory, typed_in_place_factory_base const* )
{
BOOST_STATIC_ASSERT ( ::boost::mpl::not_<is_reference_predicate>::value ) ;
factory.apply(m_storage.address()) ;
m_initialized = true ;
}
template<class Expr>
void assign_expr_to_initialized ( Expr&& factory, in_place_factory_base const* tag )
{
destroy();
construct(factory,tag);
}
// Constructs in-place using the given typed factory
template<class Expr>
void assign_expr_to_initialized ( Expr&& factory, typed_in_place_factory_base const* tag )
{
destroy();
construct(factory,tag);
}
#else
// Constructs in-place using the given factory
template<class Expr>
void construct ( Expr const& factory, in_place_factory_base const* )
@ -361,7 +534,31 @@ class optional_base : public optional_tag
}
#endif
// Constructs using any expression implicitely convertible to the single argument
#endif
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
// Constructs using any expression implicitly convertible to the single argument
// of a one-argument T constructor.
// Converting constructions of optional<T> from optional<U> uses this function with
// 'Expr' being of type 'U' and relying on a converting constructor of T from U.
template<class Expr>
void construct ( Expr&& expr, void const* )
{
new (m_storage.address()) internal_type(boost::forward<Expr>(expr)) ;
m_initialized = true ;
}
// Assigns using a form any expression implicitly convertible to the single argument
// of a T's assignment operator.
// Converting assignments of optional<T> from optional<U> uses this function with
// 'Expr' being of type 'U' and relying on a converting assignment of T from U.
template<class Expr>
void assign_expr_to_initialized ( Expr&& expr, void const* )
{
assign_value(boost::forward<Expr>(expr), is_reference_predicate());
}
#else
// Constructs using any expression implicitly convertible to the single argument
// of a one-argument T constructor.
// Converting constructions of optional<T> from optional<U> uses this function with
// 'Expr' being of type 'U' and relying on a converting constructor of T from U.
@ -372,7 +569,7 @@ class optional_base : public optional_tag
m_initialized = true ;
}
// Assigns using a form any expression implicitely convertible to the single argument
// Assigns using a form any expression implicitly convertible to the single argument
// of a T's assignment operator.
// Converting assignments of optional<T> from optional<U> uses this function with
// 'Expr' being of type 'U' and relying on a converting assignment of T from U.
@ -382,6 +579,8 @@ class optional_base : public optional_tag
assign_value(expr, is_reference_predicate());
}
#endif
#ifdef BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION
// BCB5.64 (and probably lower versions) workaround.
// The in-place factories are supported by means of catch-all constructors
@ -395,6 +594,20 @@ class optional_base : public optional_tag
// For VC<=70 compilers this workaround dosen't work becasue the comnpiler issues and error
// instead of choosing the wrong overload
//
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
// Notice that 'Expr' will be optional<T> or optional<U> (but not optional_base<..>)
template<class Expr>
void construct ( Expr&& expr, optional_tag const* )
{
if ( expr.is_initialized() )
{
// An exception can be thrown here.
// It it happens, THIS will be left uninitialized.
new (m_storage.address()) internal_type(types::move(expr.get())) ;
m_initialized = true ;
}
}
#else
// Notice that 'Expr' will be optional<T> or optional<U> (but not optional_base<..>)
template<class Expr>
void construct ( Expr const& expr, optional_tag const* )
@ -408,9 +621,14 @@ class optional_base : public optional_tag
}
}
#endif
#endif // defined BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION
void assign_value ( argument_type val, is_not_reference_tag ) { get_impl() = val; }
void assign_value ( argument_type val, is_reference_tag ) { construct(val); }
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
void assign_value ( rval_reference_type val, is_not_reference_tag ) { get_impl() = static_cast<rval_reference_type>(val); }
void assign_value ( rval_reference_type val, is_reference_tag ) { construct( static_cast<rval_reference_type>(val) ); }
#endif
void destroy()
{
@ -418,8 +636,6 @@ class optional_base : public optional_tag
destroy_impl(is_reference_predicate()) ;
}
unspecified_bool_type safe_bool() const { return m_initialized ? &this_type::is_initialized : 0 ; }
reference_const_type get_impl() const { return dereference(get_object(), is_reference_predicate() ) ; }
reference_type get_impl() { return dereference(get_object(), is_reference_predicate() ) ; }
@ -479,8 +695,6 @@ class optional : public optional_detail::optional_base<T>
{
typedef optional_detail::optional_base<T> base ;
typedef BOOST_DEDUCED_TYPENAME base::unspecified_bool_type unspecified_bool_type ;
public :
typedef optional<T> this_type ;
@ -488,22 +702,32 @@ class optional : public optional_detail::optional_base<T>
typedef BOOST_DEDUCED_TYPENAME base::value_type value_type ;
typedef BOOST_DEDUCED_TYPENAME base::reference_type reference_type ;
typedef BOOST_DEDUCED_TYPENAME base::reference_const_type reference_const_type ;
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
typedef BOOST_DEDUCED_TYPENAME base::rval_reference_type rval_reference_type ;
#endif
typedef BOOST_DEDUCED_TYPENAME base::pointer_type pointer_type ;
typedef BOOST_DEDUCED_TYPENAME base::pointer_const_type pointer_const_type ;
typedef BOOST_DEDUCED_TYPENAME base::argument_type argument_type ;
// Creates an optional<T> uninitialized.
// No-throw
optional() : base() {}
optional() BOOST_NOEXCEPT : base() {}
// Creates an optional<T> uninitialized.
// No-throw
optional( none_t none_ ) : base(none_) {}
optional( none_t none_ ) BOOST_NOEXCEPT : base(none_) {}
// Creates an optional<T> initialized with 'val'.
// Can throw if T::T(T const&) does
optional ( argument_type val ) : base(val) {}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
// Creates an optional<T> initialized with 'move(val)'.
// Can throw if T::T(T &&) does
optional ( rval_reference_type val ) : base( boost::forward<T>(val) )
{optional_detail::prevent_binding_rvalue_ref_to_optional_lvalue_ref<T, rval_reference_type>();}
#endif
// Creates an optional<T> initialized with 'val' IFF cond is true, otherwise creates an uninitialized optional.
// Can throw if T::T(T const&) does
optional ( bool cond, argument_type val ) : base(cond,val) {}
@ -521,40 +745,94 @@ class optional : public optional_detail::optional_base<T>
if ( rhs.is_initialized() )
this->construct(rhs.get());
}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
// Creates a deep move of another convertible optional<U>
// Requires a valid conversion from U to T.
// Can throw if T::T(U&&) does
template<class U>
explicit optional ( optional<U> && rhs )
:
base()
{
if ( rhs.is_initialized() )
this->construct( boost::move(rhs.get()) );
}
#endif
#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
// Creates an optional<T> with an expression which can be either
// (a) An instance of InPlaceFactory (i.e. in_place(a,b,...,n);
// (b) An instance of TypedInPlaceFactory ( i.e. in_place<T>(a,b,...,n);
// (c) Any expression implicitely convertible to the single type
// (c) Any expression implicitly convertible to the single type
// of a one-argument T's constructor.
// (d*) Weak compilers (BCB) might also resolved Expr as optional<T> and optional<U>
// even though explicit overloads are present for these.
// Depending on the above some T ctor is called.
// Can throw is the resolved T ctor throws.
// Can throw if the resolved T ctor throws.
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
template<class Expr>
explicit optional ( Expr&& expr,
BOOST_DEDUCED_TYPENAME boost::disable_if_c<
(boost::is_base_of<optional_detail::optional_tag, BOOST_DEDUCED_TYPENAME boost::decay<Expr>::type>::value) ||
boost::is_same<BOOST_DEDUCED_TYPENAME boost::decay<Expr>::type, none_t>::value >::type* = 0
)
: base(boost::forward<Expr>(expr),boost::addressof(expr))
{optional_detail::prevent_binding_rvalue_ref_to_optional_lvalue_ref<T, Expr&&>();}
#else
template<class Expr>
explicit optional ( Expr const& expr ) : base(expr,boost::addressof(expr)) {}
#endif
#endif // !defined BOOST_NO_CXX11_RVALUE_REFERENCES
#endif // !defined BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
// Creates a deep copy of another optional<T>
// Can throw if T::T(T const&) does
optional ( optional const& rhs ) : base( static_cast<base const&>(rhs) ) {}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
// Creates a deep move of another optional<T>
// Can throw if T::T(T&&) does
optional ( optional && rhs )
BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value)
: base( boost::move(rhs) )
{}
#endif
// No-throw (assuming T::~T() doesn't)
~optional() {}
#if !defined(BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT) && !defined(BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION)
// Assigns from an expression. See corresponding constructor.
// Basic Guarantee: If the resolved T ctor throws, this is left UNINITIALIZED
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
template<class Expr>
BOOST_DEDUCED_TYPENAME boost::disable_if_c<
boost::is_base_of<optional_detail::optional_tag, BOOST_DEDUCED_TYPENAME boost::decay<Expr>::type>::value ||
boost::is_same<BOOST_DEDUCED_TYPENAME boost::decay<Expr>::type, none_t>::value,
optional&
>::type
operator= ( Expr&& expr )
{
optional_detail::prevent_binding_rvalue_ref_to_optional_lvalue_ref<T, Expr&&>();
this->assign_expr(boost::forward<Expr>(expr),boost::addressof(expr));
return *this ;
}
#else
template<class Expr>
optional& operator= ( Expr const& expr )
{
this->assign_expr(expr,boost::addressof(expr));
return *this ;
}
#endif
#endif // !defined BOOST_NO_CXX11_RVALUE_REFERENCES
#endif // !defined(BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT) && !defined(BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION)
// Assigns from another convertible optional<U> (converts && deep-copies the rhs value)
// Copy-assigns from another convertible optional<U> (converts && deep-copies the rhs value)
// Requires a valid conversion from U to T.
// Basic Guarantee: If T::T( U const& ) throws, this is left UNINITIALIZED
template<class U>
@ -563,6 +841,18 @@ class optional : public optional_detail::optional_base<T>
this->assign(rhs);
return *this ;
}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
// Move-assigns from another convertible optional<U> (converts && deep-moves the rhs value)
// Requires a valid conversion from U to T.
// Basic Guarantee: If T::T( U && ) throws, this is left UNINITIALIZED
template<class U>
optional& operator= ( optional<U> && rhs )
{
this->assign(boost::move(rhs));
return *this ;
}
#endif
// Assigns from another optional<T> (deep-copies the rhs value)
// Basic Guarantee: If T::T( T const& ) throws, this is left UNINITIALIZED
@ -573,6 +863,16 @@ class optional : public optional_detail::optional_base<T>
return *this ;
}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
// Assigns from another optional<T> (deep-moves the rhs value)
optional& operator= ( optional && rhs )
BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value && ::boost::is_nothrow_move_assignable<T>::value)
{
this->assign( static_cast<base &&>(rhs) ) ;
return *this ;
}
#endif
// Assigns from a T (deep-copies the rhs value)
// Basic Guarantee: If T::( T const& ) throws, this is left UNINITIALIZED
optional& operator= ( argument_type val )
@ -581,20 +881,30 @@ class optional : public optional_detail::optional_base<T>
return *this ;
}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
// Assigns from a T (deep-moves the rhs value)
optional& operator= ( rval_reference_type val )
{
optional_detail::prevent_binding_rvalue_ref_to_optional_lvalue_ref<T, rval_reference_type>();
this->assign( boost::move(val) ) ;
return *this ;
}
#endif
// Assigns from a "none"
// Which destroys the current value, if any, leaving this UNINITIALIZED
// No-throw (assuming T::~T() doesn't)
optional& operator= ( none_t none_ )
optional& operator= ( none_t none_ ) BOOST_NOEXCEPT
{
this->assign( none_ ) ;
return *this ;
}
void swap( optional & arg )
BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value && ::boost::is_nothrow_move_assignable<T>::value)
{
// allow for Koenig lookup
using boost::swap;
swap(*this, arg);
boost::swap(*this, arg);
}
@ -620,15 +930,19 @@ class optional : public optional_detail::optional_base<T>
reference_const_type operator *() const { return this->get() ; }
reference_type operator *() { return this->get() ; }
// implicit conversion to "bool"
// No-throw
operator unspecified_bool_type() const { return this->safe_bool() ; }
// This is provided for those compilers which don't like the conversion to bool
// on some contexts.
bool operator!() const { return !this->is_initialized() ; }
bool operator!() const BOOST_NOEXCEPT { return !this->is_initialized() ; }
BOOST_EXPLICIT_OPERATOR_BOOL()
} ;
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
template<class T>
class optional<T&&>
{
BOOST_STATIC_ASSERT_MSG(sizeof(T) == 0, "Optional rvalue references are illegal.");
} ;
#endif
// Returns optional<T>(v)
template<class T>
inline
@ -835,8 +1149,8 @@ bool operator >= ( T const& x, optional<T> const& y )
template<class T>
inline
bool operator == ( optional<T> const& x, none_t )
{ return equal_pointees(x, optional<T>() ); }
bool operator == ( optional<T> const& x, none_t ) BOOST_NOEXCEPT
{ return !x; }
template<class T>
inline
@ -845,8 +1159,8 @@ bool operator < ( optional<T> const& x, none_t )
template<class T>
inline
bool operator != ( optional<T> const& x, none_t y )
{ return !( x == y ) ; }
bool operator != ( optional<T> const& x, none_t ) BOOST_NOEXCEPT
{ return bool(x); }
template<class T>
inline
@ -869,8 +1183,8 @@ bool operator >= ( optional<T> const& x, none_t y )
template<class T>
inline
bool operator == ( none_t , optional<T> const& y )
{ return equal_pointees(optional<T>() ,y); }
bool operator == ( none_t , optional<T> const& y ) BOOST_NOEXCEPT
{ return !y; }
template<class T>
inline
@ -879,8 +1193,8 @@ bool operator < ( none_t , optional<T> const& y )
template<class T>
inline
bool operator != ( none_t x, optional<T> const& y )
{ return !( x == y ) ; }
bool operator != ( none_t, optional<T> const& y ) BOOST_NOEXCEPT
{ return bool(y); }
template<class T>
inline
@ -928,6 +1242,37 @@ struct swap_selector<true>
}
};
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
template<>
struct swap_selector<false>
{
template<class T>
static void optional_swap ( optional<T>& x, optional<T>& y )
//BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value && BOOST_NOEXCEPT_EXPR(boost::swap(*x, *y)))
{
if(x)
{
if (y)
{
boost::swap(*x, *y);
}
else
{
y = boost::move(*x);
x = boost::none;
}
}
else
{
if (y)
{
x = boost::move(*y);
y = boost::none;
}
}
}
};
#else
template<>
struct swap_selector<false>
{
@ -954,6 +1299,7 @@ struct swap_selector<false>
}
}
};
#endif // !defined BOOST_NO_CXX11_RVALUE_REFERENCES
} // namespace optional_detail
@ -961,6 +1307,7 @@ template<class T>
struct optional_swap_should_use_default_constructor : has_nothrow_default_constructor<T> {} ;
template<class T> inline void swap ( optional<T>& x, optional<T>& y )
//BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value && BOOST_NOEXCEPT_EXPR(boost::swap(*x, *y)))
{
optional_detail::swap_selector<optional_swap_should_use_default_constructor<T>::value>::optional_swap(x, y);
}

View File

@ -11,15 +11,18 @@
//
// Revisions:
// 10 May 2008 (added swap related forward declaration) Niels Dekker
//
// 17 Apr 2014 (added noexcept) Andrzej Krzemienski
//
#ifndef BOOST_OPTIONAL_OPTIONAL_FWD_FLC_19NOV2002_HPP
#define BOOST_OPTIONAL_OPTIONAL_FWD_FLC_19NOV2002_HPP
#include <boost/config.hpp>
namespace boost {
template<class T> class optional ;
template<class T> void swap ( optional<T>& , optional<T>& ) ;
template<class T> void swap ( optional<T>& , optional<T>& );
template<class T> struct optional_swap_should_use_default_constructor ;

View File

@ -21,6 +21,8 @@ import testing ;
[ run optional_test_ref.cpp ]
[ run optional_test_inplace.cpp ]
[ run optional_test_io.cpp ]
[ run optional_test_move.cpp ]
[ run optional_test_equals_none.cpp ]
[ compile-fail optional_test_fail1.cpp ]
[ compile-fail optional_test_fail3a.cpp ]
[ compile-fail optional_test_fail3b.cpp ]
@ -29,5 +31,12 @@ import testing ;
[ compile-fail optional_test_ref_fail4.cpp ]
[ compile-fail optional_test_inplace_fail.cpp ]
[ compile-fail optional_test_inplace_fail2.cpp ]
[ compile-fail optional_test_fail_implicit_bool_convert.cpp ]
[ compile-fail optional_test_fail_copying_a_moveable_type.cpp ]
[ compile-fail optional_test_fail_optional_rvalue_ref.cpp ]
[ compile-fail optional_test_ref_fail_init_from_Trefref.cpp ]
[ compile-fail optional_test_ref_fail_init_from_Urefref.cpp ]
[ compile-fail optional_test_ref_fail_assign_from_Trefref.cpp ]
[ compile-fail optional_test_ref_fail_assign_from_Urefref.cpp ]
;
}

View File

@ -1086,8 +1086,8 @@ namespace optional_swap_test
//
void swap(boost::optional<class_whose_explicit_ctor_should_be_used> & x, boost::optional<class_whose_explicit_ctor_should_be_used> & y)
{
bool hasX = x;
bool hasY = y;
bool hasX(x);
bool hasY(y);
if ( !hasX && !hasY )
return;

View File

@ -0,0 +1,68 @@
// Copyright (C) 2014 Andrzej Krzemienski.
//
// Use, modification, and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/lib/optional for documentation.
//
// You are welcome to contact the author at:
// akrzemi1@gmail.com
//
// Revisions:
//
#include<iostream>
#include<stdexcept>
#include<string>
#define BOOST_ENABLE_ASSERT_HANDLER
#include "boost/bind/apply.hpp" // Included just to test proper interaction with boost::apply<> as reported by Daniel Wallin
#include "boost/mpl/bool.hpp"
#include "boost/mpl/bool_fwd.hpp" // For mpl::true_ and mpl::false_
#include "boost/optional/optional.hpp"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#include "boost/none.hpp"
#include "boost/test/minimal.hpp"
#include "optional_test_common.cpp"
struct SemiRegular // no operator==
{
private: void operator==(SemiRegular const&) const {}
private: void operator!=(SemiRegular const&) const {}
};
void test_equal_to_none_of_noncomparable_T()
{
optional<SemiRegular> i = SemiRegular();
optional<SemiRegular> o;
BOOST_CHECK(i != boost::none);
BOOST_CHECK(boost::none != i);
BOOST_CHECK(o == boost::none);
BOOST_CHECK(boost::none == o);
}
int test_main( int, char* [] )
{
try
{
test_equal_to_none_of_noncomparable_T();
}
catch ( ... )
{
BOOST_ERROR("Unexpected Exception caught!");
}
return 0;
}

View File

@ -0,0 +1,36 @@
// Copyright (C) 2014, Andrzej Krzemienski.
//
// Use, modification, and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/lib/optional for documentation.
//
// You are welcome to contact the author at:
// akrzemi1@gmail.com
//
#include "boost/optional.hpp"
class MoveOnly
{
public:
int val;
MoveOnly(int v) : val(v) {}
MoveOnly(MoveOnly&& rhs) : val(rhs.val) { rhs.val = 0; }
void operator=(MoveOnly&& rhs) {val = rhs.val; rhs.val = 0; }
private:
MoveOnly(MoveOnly const&);
void operator=(MoveOnly const&);
};
//
// THIS TEST SHOULD FAIL TO COMPILE
//
void test_copying_optional_with_noncopyable_T()
{
boost::optional<MoveOnly> opt1 ;
boost::optional<MoveOnly> opt2(opt1) ;
}

View File

@ -0,0 +1,28 @@
// Copyright (C) 2014, Andrzej Krzemienski.
//
// Use, modification, and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/lib/optional for documentation.
//
// You are welcome to contact the author at:
// akrzemi1@gmail.com
//
#include "boost/optional.hpp"
//
// THIS TEST SHOULD FAIL TO COMPILE
//
#if !defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
bool test_implicit_conversion_to_bool()
{
boost::optional<int> opt;
return opt;
}
#else
# error "Test skipped: this compiler does not support explicit conversion operators."
#endif

View File

@ -0,0 +1,19 @@
// Copyright (C) 2014, Andrzej Krzemienski.
//
// Use, modification, and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/lib/optional for documentation.
//
// You are welcome to contact the author at:
// akrzemi1@gmail.com
//
#include "boost/optional.hpp"
//
// THIS TEST SHOULD FAIL TO COMPILE
//
boost::optional<int&&> oi;

414
test/optional_test_move.cpp Normal file
View File

@ -0,0 +1,414 @@
// Copyright (C) 2014 Andrzej Krzemienski.
//
// Use, modification, and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/lib/optional for documentation.
//
// You are welcome to contact the author at:
// akrzemi1@gmail.com
//
// Revisions:
//
#include<iostream>
#include<stdexcept>
#include<string>
#define BOOST_ENABLE_ASSERT_HANDLER
#include "boost/bind/apply.hpp" // Included just to test proper interaction with boost::apply<> as reported by Daniel Wallin
#include "boost/mpl/bool.hpp"
#include "boost/mpl/bool_fwd.hpp" // For mpl::true_ and mpl::false_
#include "boost/static_assert.hpp"
#include "boost/optional/optional.hpp"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#include "boost/none.hpp"
#include "boost/test/minimal.hpp"
#include "optional_test_common.cpp"
//#ifndef BOOST_OPTIONAL_NO_CONVERTING_ASSIGNMENT
//#ifndef BOOST_OPTIONAL_NO_CONVERTING_COPY_CTOR
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
enum State
{
sDefaultConstructed,
sValueCopyConstructed,
sValueMoveConstructed,
sCopyConstructed,
sMoveConstructed,
sMoveAssigned,
sCopyAssigned,
sValueCopyAssigned,
sValueMoveAssigned,
sMovedFrom,
sIntConstructed
};
struct OracleVal
{
State s;
int i;
OracleVal(int i = 0) : s(sIntConstructed), i(i) {}
};
struct Oracle
{
State s;
OracleVal val;
Oracle() : s(sDefaultConstructed) {}
Oracle(const OracleVal& v) : s(sValueCopyConstructed), val(v) {}
Oracle(OracleVal&& v) : s(sValueMoveConstructed), val(std::move(v)) {v.s = sMovedFrom;}
Oracle(const Oracle& o) : s(sCopyConstructed), val(o.val) {}
Oracle(Oracle&& o) : s(sMoveConstructed), val(std::move(o.val)) {o.s = sMovedFrom;}
Oracle& operator=(const OracleVal& v) { s = sValueCopyAssigned; val = v; return *this; }
Oracle& operator=(OracleVal&& v) { s = sValueMoveAssigned; val = std::move(v); v.s = sMovedFrom; return *this; }
Oracle& operator=(const Oracle& o) { s = sCopyAssigned; val = o.val; return *this; }
Oracle& operator=(Oracle&& o) { s = sMoveAssigned; val = std::move(o.val); o.s = sMovedFrom; return *this; }
};
bool operator==( Oracle const& a, Oracle const& b ) { return a.val.i == b.val.i; }
bool operator!=( Oracle const& a, Oracle const& b ) { return a.val.i != b.val.i; }
void test_move_ctor_from_U()
{
optional<Oracle> o1 ((OracleVal()));
BOOST_CHECK(o1);
BOOST_CHECK(o1->s == sValueMoveConstructed || o1->s == sMoveConstructed);
OracleVal v1;
optional<Oracle> o2 (v1);
BOOST_CHECK(o2);
BOOST_CHECK(o2->s == sValueCopyConstructed || o2->s == sCopyConstructed || o2->s == sMoveConstructed );
BOOST_CHECK(v1.s == sIntConstructed);
optional<Oracle> o3 (boost::move(v1));
BOOST_CHECK(o3);
BOOST_CHECK(o3->s == sValueMoveConstructed || o3->s == sMoveConstructed);
BOOST_CHECK(v1.s == sMovedFrom);
}
void test_move_ctor_form_T()
{
optional<Oracle> o1 ((Oracle()));
BOOST_CHECK(o1);
BOOST_CHECK(o1->s == sMoveConstructed);
Oracle v1;
optional<Oracle> o2 (v1);
BOOST_CHECK(o2);
BOOST_CHECK(o2->s == sCopyConstructed);
BOOST_CHECK(v1.s == sDefaultConstructed);
optional<Oracle> o3 (boost::move(v1));
BOOST_CHECK(o3);
BOOST_CHECK(o3->s == sMoveConstructed);
BOOST_CHECK(v1.s == sMovedFrom);
}
void test_move_ctor_from_optional_T()
{
optional<Oracle> o1;
optional<Oracle> o2(boost::move(o1));
BOOST_CHECK(!o1);
BOOST_CHECK(!o2);
optional<Oracle> o3((Oracle()));
optional<Oracle> o4(boost::move(o3));
BOOST_CHECK(o3);
BOOST_CHECK(o4);
BOOST_CHECK(o3->s == sMovedFrom);
BOOST_CHECK(o4->s == sMoveConstructed);
optional<Oracle> o5((optional<Oracle>()));
BOOST_CHECK(!o5);
optional<Oracle> o6((optional<Oracle>(Oracle())));
BOOST_CHECK(o6);
BOOST_CHECK(o6->s == sMoveConstructed);
optional<Oracle> o7(o6); // does copy ctor from non-const lvalue compile?
}
void test_move_assign_from_U()
{
optional<Oracle> o1 = boost::none; // test if additional ctors didn't break it
o1 = boost::none; // test if additional assignments didn't break it
o1 = OracleVal();
BOOST_CHECK(o1);
BOOST_CHECK(o1->s == sValueMoveConstructed);
o1 = OracleVal();
BOOST_CHECK(o1);
BOOST_CHECK(o1->s == sMoveAssigned);
OracleVal v1;
optional<Oracle> o2;
o2 = v1;
BOOST_CHECK(o2);
BOOST_CHECK(o2->s == sValueCopyConstructed);
BOOST_CHECK(v1.s == sIntConstructed);
o2 = v1;
BOOST_CHECK(o2);
BOOST_CHECK(o2->s == sCopyAssigned || o2->s == sMoveAssigned);
BOOST_CHECK(v1.s == sIntConstructed);
optional<Oracle> o3;
o3 = boost::move(v1);
BOOST_CHECK(o3);
BOOST_CHECK(o3->s == sValueMoveConstructed);
BOOST_CHECK(v1.s == sMovedFrom);
}
void test_move_assign_from_T()
{
optional<Oracle> o1;
o1 = Oracle();
BOOST_CHECK(o1);
BOOST_CHECK(o1->s == sMoveConstructed);
o1 = Oracle();
BOOST_CHECK(o1);
BOOST_CHECK(o1->s == sMoveAssigned);
Oracle v1;
optional<Oracle> o2;
o2 = v1;
BOOST_CHECK(o2);
BOOST_CHECK(o2->s == sCopyConstructed);
BOOST_CHECK(v1.s == sDefaultConstructed);
o2 = v1;
BOOST_CHECK(o2);
BOOST_CHECK(o2->s == sCopyAssigned);
BOOST_CHECK(v1.s == sDefaultConstructed);
optional<Oracle> o3;
o3 = boost::move(v1);
BOOST_CHECK(o3);
BOOST_CHECK(o3->s == sMoveConstructed);
BOOST_CHECK(v1.s == sMovedFrom);
}
void test_move_assign_from_optional_T()
{
optional<Oracle> o1;
optional<Oracle> o2;
o1 = optional<Oracle>();
BOOST_CHECK(!o1);
optional<Oracle> o3((Oracle()));
o1 = o3;
BOOST_CHECK(o3);
BOOST_CHECK(o3->s == sMoveConstructed);
BOOST_CHECK(o1);
BOOST_CHECK(o1->s == sCopyConstructed);
o2 = boost::move(o3);
BOOST_CHECK(o3);
BOOST_CHECK(o3->s == sMovedFrom);
BOOST_CHECK(o2);
BOOST_CHECK(o2->s == sMoveConstructed);
o2 = optional<Oracle>((Oracle()));
BOOST_CHECK(o2);
BOOST_CHECK(o2->s == sMoveAssigned);
}
class MoveOnly
{
public:
int val;
MoveOnly(int v) : val(v) {}
MoveOnly(MoveOnly&& rhs) : val(rhs.val) { rhs.val = 0; }
void operator=(MoveOnly&& rhs) {val = rhs.val; rhs.val = 0; }
private:
MoveOnly(MoveOnly const&);
void operator=(MoveOnly const&);
friend class MoveOnlyB;
};
void test_with_move_only()
{
optional<MoveOnly> o1;
optional<MoveOnly> o2((MoveOnly(1)));
BOOST_CHECK(o2);
BOOST_CHECK(o2->val == 1);
optional<MoveOnly> o3 (boost::move(o1));
BOOST_CHECK(!o3);
optional<MoveOnly> o4 (boost::move(o2));
BOOST_CHECK(o4);
BOOST_CHECK(o4->val == 1);
BOOST_CHECK(o2);
BOOST_CHECK(o2->val == 0);
o3 = boost::move(o4);
BOOST_CHECK(o3);
BOOST_CHECK(o3->val == 1);
BOOST_CHECK(o4);
BOOST_CHECK(o4->val == 0);
}
class MoveOnlyB
{
public:
int val;
MoveOnlyB(int v) : val(v) {}
MoveOnlyB(MoveOnlyB&& rhs) : val(rhs.val) { rhs.val = 0; }
void operator=(MoveOnlyB&& rhs) {val = rhs.val; rhs.val = 0; }
MoveOnlyB(MoveOnly&& rhs) : val(rhs.val) { rhs.val = 0; }
void operator=(MoveOnly&& rhs) {val = rhs.val; rhs.val = 0; }
private:
MoveOnlyB(MoveOnlyB const&);
void operator=(MoveOnlyB const&);
MoveOnlyB(MoveOnly const&);
void operator=(MoveOnly const&);
};
void test_move_assign_from_optional_U()
{
optional<MoveOnly> a((MoveOnly(2)));
optional<MoveOnlyB> b1;
b1 = boost::move(a);
BOOST_CHECK(b1);
BOOST_CHECK(b1->val == 2);
BOOST_CHECK(a);
BOOST_CHECK(a->val == 0);
b1 = MoveOnly(4);
BOOST_CHECK(b1);
BOOST_CHECK(b1->val == 4);
}
void test_move_ctor_from_optional_U()
{
optional<MoveOnly> a((MoveOnly(2)));
optional<MoveOnlyB> b1(boost::move(a));
BOOST_CHECK(b1);
BOOST_CHECK(b1->val == 2);
BOOST_CHECK(a);
BOOST_CHECK(a->val == 0);
optional<MoveOnlyB> b2(( optional<MoveOnly>(( MoveOnly(4) )) ));
BOOST_CHECK(b2);
BOOST_CHECK(b2->val == 4);
}
void test_swap()
{
optional<MoveOnly> a((MoveOnly(2)));
optional<MoveOnly> b((MoveOnly(3)));
swap(a, b);
BOOST_CHECK(a->val == 3);
BOOST_CHECK(b->val == 2);
}
void test_optional_ref_to_movables()
{
MoveOnly m(3);
optional<MoveOnly&> orm = m;
orm->val = 2;
BOOST_CHECK(m.val == 2);
optional<MoveOnly&> orm2 = orm;
orm2->val = 1;
BOOST_CHECK(m.val == 1);
BOOST_CHECK(orm->val == 1);
optional<MoveOnly&> orm3 = boost::move(orm);
orm3->val = 4;
BOOST_CHECK(m.val == 4);
BOOST_CHECK(orm->val == 4);
BOOST_CHECK(orm2->val == 4);
}
// these 4 classes have different noexcept signatures in move operations
struct NothrowBoth {
NothrowBoth(NothrowBoth&&) BOOST_NOEXCEPT_IF(true) {};
void operator=(NothrowBoth&&) BOOST_NOEXCEPT_IF(true) {};
};
struct NothrowCtor {
NothrowCtor(NothrowCtor&&) BOOST_NOEXCEPT_IF(true) {};
void operator=(NothrowCtor&&) BOOST_NOEXCEPT_IF(false) {};
};
struct NothrowAssign {
NothrowAssign(NothrowAssign&&) BOOST_NOEXCEPT_IF(false) {};
void operator=(NothrowAssign&&) BOOST_NOEXCEPT_IF(true) {};
};
struct NothrowNone {
NothrowNone(NothrowNone&&) BOOST_NOEXCEPT_IF(false) {};
void operator=(NothrowNone&&) BOOST_NOEXCEPT_IF(false) {};
};
#ifndef BOOST_NO_NOEXCEPT
void test_noexcept() // this is a compile-time test
{
BOOST_STATIC_ASSERT(::boost::is_nothrow_move_constructible<optional<NothrowBoth> >::value);
BOOST_STATIC_ASSERT(::boost::is_nothrow_move_assignable<optional<NothrowBoth> >::value);
BOOST_STATIC_ASSERT(BOOST_NOEXCEPT_EXPR(optional<NothrowBoth>()));
BOOST_STATIC_ASSERT(::boost::is_nothrow_move_constructible<optional<NothrowCtor> >::value);
BOOST_STATIC_ASSERT(!::boost::is_nothrow_move_assignable<optional<NothrowCtor> >::value);
BOOST_STATIC_ASSERT(BOOST_NOEXCEPT_EXPR(optional<NothrowCtor>()));
BOOST_STATIC_ASSERT(!::boost::is_nothrow_move_constructible<optional<NothrowAssign> >::value);
BOOST_STATIC_ASSERT(!::boost::is_nothrow_move_assignable<optional<NothrowAssign> >::value);
BOOST_STATIC_ASSERT(BOOST_NOEXCEPT_EXPR(optional<NothrowAssign>()));
BOOST_STATIC_ASSERT(!::boost::is_nothrow_move_constructible<optional<NothrowNone> >::value);
BOOST_STATIC_ASSERT(!::boost::is_nothrow_move_assignable<optional<NothrowNone> >::value);
BOOST_STATIC_ASSERT(BOOST_NOEXCEPT_EXPR(optional<NothrowNone>()));
}
#endif // !defned BOOST_NO_NOEXCEPT
#endif
int test_main( int, char* [] )
{
try
{
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
test_move_ctor_from_U();
test_move_ctor_form_T();
test_move_ctor_from_optional_T();
test_move_ctor_from_optional_U();
test_move_assign_from_U();
test_move_assign_from_T();
test_move_assign_from_optional_T();
test_move_assign_from_optional_U();
test_with_move_only();
test_optional_ref_to_movables();
test_swap();
#endif
}
catch ( ... )
{
BOOST_ERROR("Unexpected Exception caught!");
}
return 0;
}

View File

@ -0,0 +1,26 @@
// Copyright (C) 2014, andrzej Krzemienski.
//
// Use, modification, and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/lib/optional for documentation.
//
// You are welcome to contact the author at:
// akrzemi1@gmail.com
//
#include "boost/optional.hpp"
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
//
// THIS TEST SHOULD FAIL TO COMPILE
//
void optional_reference__test_no_assign_from_Trefref()
{
boost::optional<const int&> opt;
opt = int(3);
}
#else
# error "Test skipped. This cannot be implemented w/o rvalue references."
#endif

View File

@ -0,0 +1,26 @@
// Copyright (C) 2014, andrzej Krzemienski.
//
// Use, modification, and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/lib/optional for documentation.
//
// You are welcome to contact the author at:
// akrzemi1@gmail.com
//
#include "boost/optional.hpp"
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
//
// THIS TEST SHOULD FAIL TO COMPILE
//
void optional_reference__test_no_assign_from_Urefref()
{
boost::optional<const int&> opt;
opt = long(3);
}
#else
# error "Test skipped. This cannot be implemented w/o rvalue references."
#endif

View File

@ -0,0 +1,25 @@
// Copyright (C) 2014, andrzej Krzemienski.
//
// Use, modification, and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/lib/optional for documentation.
//
// You are welcome to contact the author at:
// akrzemi1@gmail.com
//
#include "boost/optional.hpp"
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
//
// THIS TEST SHOULD FAIL TO COMPILE
//
void optional_reference__test_no_init_from_Trefref()
{
boost::optional<const int&> opt = int(3);
}
#else
# error "Test skipped. This cannot be implemented w/o rvalue references."
#endif

View File

@ -0,0 +1,25 @@
// Copyright (C) 2014, andrzej Krzemienski.
//
// Use, modification, and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/lib/optional for documentation.
//
// You are welcome to contact the author at:
// akrzemi1@gmail.com
//
#include "boost/optional.hpp"
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
//
// THIS TEST SHOULD FAIL TO COMPILE
//
void optional_reference__test_no_init_from_Urefref()
{
boost::optional<const int&> opt = long(3);
}
#else
# error "Test skipped. This cannot be implemented w/o rvalue references."
#endif

View File

@ -0,0 +1,108 @@
// Copyright (C) 2014 Andrzej Krzemienski.
//
// Use, modification, and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/lib/optional for documentation.
//
// You are welcome to contact the author at:
// akrzemi1@gmail.com
//
// Revisions:
//
#include<iostream>
#include<stdexcept>
//#include<string>
#define BOOST_ENABLE_ASSERT_HANDLER
//#include "boost/bind/apply.hpp" // Included just to test proper interaction with boost::apply<> as reported by Daniel Wallin
#include "boost/mpl/bool.hpp"
#include "boost/mpl/bool_fwd.hpp" // For mpl::true_ and mpl::false_
#include "boost/static_assert.hpp"
#include "boost/optional/optional.hpp"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#include "boost/test/minimal.hpp"
#include "optional_test_common.cpp"
const int global_i = 0;
class TestingReferenceBinding
{
public:
TestingReferenceBinding(const int& ii)
{
BOOST_CHECK(&ii == &global_i);
}
void operator=(const int& ii)
{
BOOST_CHECK(&ii == &global_i);
}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
void operator=(int&&)
{
BOOST_CHECK(false);
}
#endif
};
class TestingReferenceBinding2 // same definition as above, I need a different type
{
public:
TestingReferenceBinding2(const int& ii)
{
BOOST_CHECK(&ii == &global_i);
}
void operator=(const int& ii)
{
BOOST_CHECK(&ii == &global_i);
}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
void operator=(int&&)
{
BOOST_CHECK(false);
}
#endif
};
void test_broken_compiler()
{
// we are not testing boost::optional here, but the c++ compiler
// if this test fails, optional references will obviously fail too
const int& iref = global_i;
BOOST_CHECK(&iref == &global_i);
TestingReferenceBinding ttt = global_i;
ttt = global_i;
TestingReferenceBinding2 ttt2 = iref;
ttt2 = iref;
}
int test_main( int, char* [] )
{
try
{
test_broken_compiler();
}
catch ( ... )
{
BOOST_ERROR("Unexpected Exception caught!");
}
return 0;
}