Let's write and use a converter function that converts an a <codeclass="computeroutput"><spanclass="identifier">std</span><spanclass="special">::</span><spanclass="identifier">string</span></code>
to an <codeclass="computeroutput"><spanclass="keyword">int</span></code>. It is possible that
for a given string (e.g. <codeclass="computeroutput"><spanclass="string">"cat"</span></code>)
there exist no value of type <codeclass="computeroutput"><spanclass="keyword">int</span></code>
capable of representing the conversion result. We do not consider such situation
an error. We expect that the converter can be used only to check if the conversion
is possible. A natural signature for this function can be:
All necessary functionality can be included with one header <codeclass="computeroutput"><spanclass="special"><</span><spanclass="identifier">boost</span><spanclass="special">/</span><spanclass="identifier">optional</span><spanclass="special">.</span><spanclass="identifier">hpp</span><spanclass="special">></span></code>.
The above function signature means that the function can either return a value
of type <codeclass="computeroutput"><spanclass="keyword">int</span></code> or a flag indicating
that no value of <codeclass="computeroutput"><spanclass="keyword">int</span></code> is available.
This does not indicate an error. It is like one additional value of <codeclass="computeroutput"><spanclass="keyword">int</span></code>. This is how we can use our function:
<spanclass="keyword">if</span><spanclass="special">(</span><spanclass="identifier">oi</span><spanclass="special">)</span><spanclass="comment">// contextual conversion to bool</span>
We extract the contained value with <codeclass="computeroutput"><spanclass="keyword">operator</span><spanclass="special">*</span></code> (and with <codeclass="computeroutput"><spanclass="keyword">operator</span><spanclass="special">-></span></code> where it makes sense). An attempt to extract
the contained value of an uninitialized optional object is an <spanclass="emphasis"><em>undefined
behaviour</em></span> (UB). This implementation guards the call with <codeclass="computeroutput"><spanclass="identifier">BOOST_ASSERT</span></code>. Therefore you should be sure
that the contained value is there before extracting. For instance, the following
Observe the two return statements. <codeclass="computeroutput"><spanclass="keyword">return</span>
<spanclass="identifier">i</span></code> uses the converting constructor
that can create <codeclass="computeroutput"><spanclass="identifier">optional</span><spanclass="special"><</span><spanclass="identifier">T</span><spanclass="special">></span></code> from
object is initialized and its value is a copy of <codeclass="computeroutput"><spanclass="identifier">i</span></code>.
The other return statement uses another converting constructor from a special
tag <codeclass="computeroutput"><spanclass="identifier">boost</span><spanclass="special">::</span><spanclass="identifier">none</span></code>. It is used to indicate that we want
The default constructor of <codeclass="computeroutput"><spanclass="identifier">optional</span></code>
creates an unitialized optional object. Unlike with <codeclass="computeroutput"><spanclass="keyword">int</span></code>s
you cannot have an <codeclass="computeroutput"><spanclass="identifier">optional</span><spanclass="special"><</span><spanclass="keyword">int</span><spanclass="special">></span></code>
in an indeterminate state. Its state is always well defined. Instruction <codeclass="computeroutput"><spanclass="identifier">ans</span><spanclass="special">=</span><spanclass="identifier">i</span></code>
initializes the optional object. It uses the assignment from <codeclass="computeroutput"><spanclass="keyword">int</span></code>. In general, for <codeclass="computeroutput"><spanclass="identifier">optional</span><spanclass="special"><</span><spanclass="identifier">T</span><spanclass="special">></span></code>,
when an assignment from <codeclass="computeroutput"><spanclass="identifier">T</span></code> is
invoked, it can do two things. If the optional object is not initialized our
case here), it initializes it with <codeclass="computeroutput"><spanclass="identifier">T</span></code>'s
copy constructor. If the optional object is already initialized, it assigns
the new value to it using <codeclass="computeroutput"><spanclass="identifier">T</span></code>'s
<spanclass="identifier">Resource</span><spanclass="special">&</span><spanclass="identifier">getResource</span><spanclass="special">()</span><spanclass="comment">// not thread-safe</span>
creates an uninitialized optional. No call to <codeclass="computeroutput"><spanclass="identifier">Resource</span></code>'s
default constructor is attempted. <codeclass="computeroutput"><spanclass="identifier">Resource</span></code>
doesn't have to be <ahref="http://www.sgi.com/tech/stl/DefaultConstructible.html"target="_top">Default
Constructible</a>. In function <codeclass="computeroutput"><spanclass="identifier">getResource</span></code>
we first check if <codeclass="computeroutput"><spanclass="identifier">resource_</span></code>
is initialized. This time we do not use the contextual conversion to <codeclass="computeroutput"><spanclass="keyword">bool</span></code>, but a comparison with <codeclass="computeroutput"><spanclass="identifier">boost</span><spanclass="special">::</span><spanclass="identifier">none</span></code>. These
two ways are equivalent. Function <codeclass="computeroutput"><spanclass="identifier">emplace</span></code>
initializes the optional in-place by perfect-forwarding the arguments to the
constructor of <codeclass="computeroutput"><spanclass="identifier">Resource</span></code>. No
copy- or move-construction is involved here. <codeclass="computeroutput"><spanclass="identifier">Resource</span></code>
doesn't even have to be <codeclass="computeroutput"><spanclass="identifier">MoveConstructible</span></code>.
Suppose we have class <codeclass="computeroutput"><spanclass="identifier">Date</span></code>,
which does not have a default constructor: there is no good candidate for a
default date. We have a function that returns two dates in form of a <codeclass="computeroutput"><spanclass="identifier">boost</span><spanclass="special">::</span><spanclass="identifier">tuple</span></code>:
In other place we want to use the result of <codeclass="computeroutput"><spanclass="identifier">getPeriod</span></code>,
but want the two dates to be named: <codeclass="computeroutput"><spanclass="identifier">begin</span></code>
and <codeclass="computeroutput"><spanclass="identifier">end</span></code>. We want to implement
something like 'multiple return values':
</p>
<preclass="programlisting"><spanclass="identifier">Date</span><spanclass="identifier">begin</span><spanclass="special">,</span><spanclass="identifier">end</span><spanclass="special">;</span><spanclass="comment">// Error: no default ctor!</span>
It works because inside <codeclass="computeroutput"><spanclass="identifier">boost</span><spanclass="special">::</span><spanclass="identifier">tie</span></code> a move-assignment
from <codeclass="computeroutput"><spanclass="identifier">T</span></code> is invoked on <codeclass="computeroutput"><spanclass="identifier">optional</span><spanclass="special"><</span><spanclass="identifier">T</span><spanclass="special">></span></code>, which
internally calls a move-constructor of <codeclass="computeroutput"><spanclass="identifier">T</span></code>.
Suppose you want to ask users to choose some number (an <codeclass="computeroutput"><spanclass="keyword">int</span></code>).
One of the valid responses is to choose nothing, which is represented by an
uninitialized <codeclass="computeroutput"><spanclass="identifier">optional</span><spanclass="special"><</span><spanclass="keyword">int</span><spanclass="special">></span></code>. You
want to make a histogram showing how many times each choice was made. You can
use an <codeclass="computeroutput"><spanclass="identifier">std</span><spanclass="special">::</span><spanclass="identifier">map</span></code>:
This works because <codeclass="computeroutput"><spanclass="identifier">optional</span><spanclass="special"><</span><spanclass="identifier">T</span><spanclass="special">></span></code>
is <codeclass="computeroutput"><spanclass="identifier">LessThanComparable</span></code> whenever
<codeclass="computeroutput"><spanclass="identifier">T</span></code> is <codeclass="computeroutput"><spanclass="identifier">LessThanComparable</span></code>.
In this case the state of being uninitialized is treated as a yet another value
of <codeclass="computeroutput"><spanclass="identifier">T</span></code>, which is compared less
than any value of <codeclass="computeroutput"><spanclass="identifier">T</span></code>. So the
set of values that type <codeclass="computeroutput"><spanclass="identifier">optional</span><spanclass="special"><</span><spanclass="identifier">T</span><spanclass="special">></span></code>
can assume is {<codeclass="computeroutput"><spanclass="identifier">boost</span><spanclass="special">::</span><spanclass="identifier">none</span></code>, -2147483648, -2147483647, ..., -1,
0, 1, ..., 2147483647} (assuming a 32-bit <codeclass="computeroutput"><spanclass="keyword">int</span></code>).
<tdalign="right"><divclass="copyright-footer">Copyright © 2003-2007 Fernando Luis Cacciola Carballal<br>Copyright © 2014 Andrzej Krzemieński<p>
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at <ahref="http://www.boost.org/LICENSE_1_0.txt"target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)