Files
optional/doc/html/boost_optional/tutorial.html

240 lines
23 KiB
HTML
Raw Normal View History

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Tutorial</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="discussion.html" title="Discussion">
</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="discussion.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.tutorial"></a><a class="link" href="tutorial.html" title="Tutorial">Tutorial</a>
</h2></div></div></div>
<div class="toc"><dl class="toc">
<dt><span class="section"><a href="tutorial.html#boost_optional.tutorial.optional_return_values">Optional
return values</a></span></dt>
<dt><span class="section"><a href="tutorial.html#boost_optional.tutorial.optional_data_members">Optional
data members</a></span></dt>
<dt><span class="section"><a href="tutorial.html#boost_optional.tutorial.bypassing_unnecessary_default_construction">Bypassing
unnecessary default construction</a></span></dt>
</dl></div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="boost_optional.tutorial.optional_return_values"></a><a class="link" href="tutorial.html#boost_optional.tutorial.optional_return_values" title="Optional return values">Optional
return values</a>
</h3></div></div></div>
<p>
Let's write and use a converter function that converts an a <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code>
to an <code class="computeroutput"><span class="keyword">int</span></code>. It is possible that
for a given string (e.g. <code class="computeroutput"><span class="string">"cat"</span></code>)
there exist no value of type <code class="computeroutput"><span class="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:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">optional</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">optionl</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;</span> <span class="identifier">convert</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">&amp;</span> <span class="identifier">text</span><span class="special">);</span>
</pre>
<p>
All necessary functionality can be included with one header <code class="computeroutput"><span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">optional</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span></code>.
The above function signature means that the function can either return a
value of type <code class="computeroutput"><span class="keyword">int</span></code> or a flag
indicating that no value of <code class="computeroutput"><span class="keyword">int</span></code>
is available. This does not indicate an error. It is like one additional
value of <code class="computeroutput"><span class="keyword">int</span></code>. This is how we
can use our function:
</p>
<pre class="programlisting"><span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">&amp;</span> <span class="identifier">text</span> <span class="special">=</span> <span class="comment">/*... */</span><span class="special">;</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">optionl</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">convert</span><span class="special">(</span><span class="identifier">text</span><span class="special">);</span> <span class="comment">// move-construct</span>
<span class="keyword">if</span> <span class="special">(</span><span class="identifier">oi</span><span class="special">)</span> <span class="comment">// contextual conversion to bool</span>
<span class="keyword">int</span> <span class="identifier">i</span> <span class="special">=</span> <span class="special">*</span><span class="identifier">oi</span><span class="special">;</span> <span class="comment">// operator*</span>
</pre>
<p>
In order to test if <code class="computeroutput"><span class="identifier">optional</span></code>
contains a value, we use the contextual conversion to type <code class="computeroutput"><span class="keyword">bool</span></code>. Because of this we can combine the initialization
of the optional object and the test into one instruction:
</p>
<pre class="programlisting"><span class="keyword">if</span> <span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">optionl</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">convert</span><span class="special">(</span><span class="identifier">text</span><span class="special">))</span>
<span class="keyword">int</span> <span class="identifier">i</span> <span class="special">=</span> <span class="special">*</span><span class="identifier">oi</span><span class="special">;</span>
</pre>
<p>
We extract the contained value with <code class="computeroutput"><span class="keyword">operator</span><span class="special">*</span></code> (and with <code class="computeroutput"><span class="keyword">operator</span><span class="special">-&gt;</span></code> where it makes sense). An attempt to
extract the contained value of an uninitialized optional object is an <span class="emphasis"><em>undefined
behaviour</em></span> (UB). This implementation guards the call with <code class="computeroutput"><span class="identifier">BOOST_ASSERT</span></code>. Therefore you should be sure
that the contained value is there before extracting. For instance, the following
code is reasonably UB-safe:
</p>
<pre class="programlisting"><span class="keyword">int</span> <span class="identifier">i</span> <span class="special">=</span> <span class="special">*</span><span class="identifier">convert</span><span class="special">(</span><span class="string">"100"</span><span class="special">);</span>
</pre>
<p>
This is because we know that string value <code class="computeroutput"><span class="string">"100"</span></code>
converts to a valid value of <code class="computeroutput"><span class="keyword">int</span></code>.
If you do not like this potential UB, you can use an alternative way of extracting
the contained value:
</p>
<pre class="programlisting"><span class="keyword">try</span> <span class="special">{</span>
<span class="keyword">int</span> <span class="identifier">j</span> <span class="special">=</span> <span class="identifier">convert</span><span class="special">(</span><span class="identifier">text</span><span class="special">).</span><span class="identifier">value</span><span class="special">();</span>
<span class="special">}</span>
<span class="keyword">catch</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">bad_optional_access</span><span class="special">&amp;)</span> <span class="special">{</span>
<span class="comment">// deal with it</span>
<span class="special">}</span>
</pre>
<p>
This version throws an exception upon an attempt to access a non-existent
contained value. If your way of dealing with the missing value is to use
some default, like <code class="computeroutput"><span class="number">0</span></code>, there exists
a yet another alternative:
</p>
<pre class="programlisting"><span class="keyword">int</span> <span class="identifier">k</span> <span class="special">=</span> <span class="identifier">convert</span><span class="special">(</span><span class="identifier">text</span><span class="special">).</span><span class="identifier">value_or</span><span class="special">(</span><span class="number">0</span><span class="special">);</span>
</pre>
<p>
This uses the <code class="computeroutput"><span class="identifier">atoi</span></code>-like approach
to conversions: if <code class="computeroutput"><span class="identifier">text</span></code> does
not represent an integral number just return <code class="computeroutput"><span class="number">0</span></code>.
Now, let's consider how function <code class="computeroutput"><span class="identifier">convert</span></code>
can be implemented.
</p>
<pre class="programlisting"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">optionl</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;</span> <span class="identifier">convert</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">&amp;</span> <span class="identifier">text</span><span class="special">)</span>
<span class="special">{</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">stringstream</span> <span class="identifier">s</span><span class="special">(</span><span class="identifier">text</span><span class="special">);</span>
<span class="keyword">int</span> <span class="identifier">i</span><span class="special">;</span>
<span class="keyword">if</span> <span class="special">((</span><span class="identifier">s</span> <span class="special">&gt;&gt;</span> <span class="identifier">i</span><span class="special">)</span> <span class="special">&amp;&amp;</span> <span class="identifier">s</span><span class="special">.</span><span class="identifier">get</span><span class="special">()</span> <span class="special">==</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">char_traits</span><span class="special">&lt;</span><span class="keyword">char</span><span class="special">&gt;::</span><span class="identifier">eof</span><span class="special">())</span>
<span class="keyword">return</span> <span class="identifier">i</span><span class="special">;</span>
<span class="keyword">else</span>
<span class="keyword">return</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">none</span><span class="special">;</span>
<span class="special">}</span>
</pre>
<p>
Observe the two return statements. <code class="computeroutput"><span class="keyword">return</span>
<span class="identifier">i</span></code> uses the converting constructor
that can create <code class="computeroutput"><span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span></code>
from <code class="computeroutput"><span class="identifier">T</span></code>. Thus constructed
optional object is initialized and its value is a copy of <code class="computeroutput"><span class="identifier">i</span></code>.
The other return statement uses another converting constructor from a special
tag <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">none</span></code>. It is used to indicate that we want
to create an uninitialized optional object.
</p>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="boost_optional.tutorial.optional_data_members"></a><a class="link" href="tutorial.html#boost_optional.tutorial.optional_data_members" title="Optional data members">Optional
data members</a>
</h3></div></div></div>
<p>
Suppose we want to implement a <span class="emphasis"><em>lazy load</em></span> optimization.
This is because we do not want to perform an expensive initialization of
our <code class="computeroutput"><span class="identifier">Resource</span></code> until (if at
all) it is really used. We can do it this way:
</p>
<pre class="programlisting"><span class="keyword">class</span> <span class="identifier">Widget</span>
<span class="special">{</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">Resource</span><span class="special">&gt;</span> <span class="identifier">resource_</span><span class="special">;</span>
<span class="keyword">public</span><span class="special">:</span>
<span class="identifier">Widget</span><span class="special">()</span> <span class="special">{}</span>
<span class="identifier">Resource</span><span class="special">&amp;</span> <span class="identifier">getResource</span><span class="special">()</span> <span class="comment">// not thread-safe</span>
<span class="special">{</span>
<span class="keyword">if</span> <span class="special">(</span><span class="identifier">resource_</span> <span class="special">==</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">none</span><span class="special">)</span>
<span class="identifier">resource_</span><span class="special">.</span><span class="identifier">emplace</span><span class="special">(</span><span class="string">"resource"</span><span class="special">,</span> <span class="string">"arguments"</span><span class="special">);</span>
<span class="keyword">return</span> <span class="special">*</span><span class="identifier">resource_</span><span class="special">;</span>
<span class="special">}</span>
<span class="special">};</span>
</pre>
<p>
<code class="computeroutput"><span class="identifier">optional</span></code>'s default constructor
creates an uninitialized optional. No call to <code class="computeroutput"><span class="identifier">Resource</span></code>'s
default constructor is attempted. <code class="computeroutput"><span class="identifier">Resource</span></code>
doesn't have to be <a href="http://www.sgi.com/tech/stl/DefaultConstructible.html" target="_top">Default
Constructible</a>. In function <code class="computeroutput"><span class="identifier">getResource</span></code>
we first check if <code class="computeroutput"><span class="identifier">resource_</span></code>
is initialized. This time we do not use the contextual conversion to <code class="computeroutput"><span class="keyword">bool</span></code>, but a comparison with <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">none</span></code>. These two ways are equivalent. Function
<code class="computeroutput"><span class="identifier">emplace</span></code> initializes the optional
in-place by perfect-forwarding the arguments to the constructor of <code class="computeroutput"><span class="identifier">Resource</span></code>. No copy- or move-construction
is involved here. <code class="computeroutput"><span class="identifier">Resource</span></code>
doesn't even have to be <code class="computeroutput"><span class="identifier">MoveConstructible</span></code>.
</p>
<div class="note"><table border="0" summary="Note">
<tr>
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../doc/src/images/note.png"></td>
<th align="left">Note</th>
</tr>
<tr><td align="left" valign="top"><p>
Function <code class="computeroutput"><span class="identifier">emplace</span></code> is only
available on compilers that support rvalue references and variadic templates.
If your compiler does not support these features and you still need to
avoid any move-constructions, use <a class="link" href="in_place_factories.html" title="In-Place Factories">In-Place
Factories</a>.
</p></td></tr>
</table></div>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="boost_optional.tutorial.bypassing_unnecessary_default_construction"></a><a class="link" href="tutorial.html#boost_optional.tutorial.bypassing_unnecessary_default_construction" title="Bypassing unnecessary default construction">Bypassing
unnecessary default construction</a>
</h3></div></div></div>
<p>
Suppose we have class <code class="computeroutput"><span class="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 <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">tuple</span></code>:
</p>
<pre class="programlisting"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">tuple</span><span class="special">&lt;</span><span class="identifier">Date</span><span class="special">,</span> <span class="identifier">Date</span><span class="special">&gt;</span> <span class="identifier">getPeriod</span><span class="special">();</span>
</pre>
<p>
In other place we want to use the result of <code class="computeroutput"><span class="identifier">getPeriod</span></code>,
but want the two dates to be named: <code class="computeroutput"><span class="identifier">begin</span></code>
and <code class="computeroutput"><span class="identifier">end</span></code>. We want to implement
something like 'multiple return values':
</p>
<pre class="programlisting"><span class="identifier">Date</span> <span class="identifier">begin</span><span class="special">,</span> <span class="identifier">end</span><span class="special">;</span> <span class="comment">// Error: no default ctor!</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">tie</span><span class="special">(</span><span class="identifier">begin</span><span class="special">,</span> <span class="identifier">end</span><span class="special">)</span> <span class="special">=</span> <span class="identifier">getPeriod</span><span class="special">();</span>
</pre>
<p>
The second line works already, this is the capability of Boost.Tuple library,
but the first line won't work. We could set some initial invented dates,
but it is confusing and may be an unacceptable cost, given that these values
will be overwritten in the next line anyway. This is where <code class="computeroutput"><span class="identifier">optional</span></code> can help:
</p>
<pre class="programlisting"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">Date</span><span class="special">&gt;</span> <span class="identifier">begin</span><span class="special">,</span> <span class="identifier">end</span><span class="special">;</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">tie</span><span class="special">(</span><span class="identifier">begin</span><span class="special">,</span> <span class="identifier">end</span><span class="special">)</span> <span class="special">=</span> <span class="identifier">getPeriod</span><span class="special">();</span>
</pre>
<p>
It works because inside <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">tie</span></code> a
move-assignment from <code class="computeroutput"><span class="identifier">T</span></code> is
invoked 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>,
which internally calls a move-constructor of <code class="computeroutput"><span class="identifier">T</span></code>.
</p>
</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<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="discussion.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>