// NOTE: in real code you can just use this: make_optional(some_condition(a), a )
}
boost::optional<int> opt = boost::none ;
if ( opt == boost::none )
opt = foo(123);
opt = boost::none ;
</pre>
<p>What does the assignment do?<br>
If 'a' is <i>uninitialized</i>, the answer is clear: it binds to 'x' (we now have
another reference to 'x').<br>
But what if 'a' is already <i>initialized? </i>it would change the value of the
referenced object (whatever that is); which is inconsistent with the other
possible case.</p>
<p>If optional<T&> would assign just like T& does, you would never be able to
use Optional's assignment without explicitly handling the previous
initialization state unless your code is capable of functioning whether after
the assignment, 'a'
aliases the same object as 'b' or not.</p>
<p>That is, you would have to discriminate in order to be consistency.<br>
<br>
If in your code rebinding to another object is not an option, then is very
likely that binding for the fist time isn't either. In such case, assignment to
an <i>uninitialized</i> optional<T&> shall be prohibited. It is quite
possible that in such scenario the precondition that the lvalue must be already
initialized exist. If it doesn't, then binding for the first time is OK while
rebinding is not which is IMO
very unlikely.<br>
In such scenario, you can assign the value itself directly, as in:</p>
<pre>assert(!!opt);
*opt=value; </pre>
<HR>
@ -1506,9 +1678,8 @@ public:
the <i>maybe</i> state <u>represents a valid value</u>, unlike the corresponding state
of an uninitialized optional<bool>.<br>
It should be carefully considered if an optional<bool> instead of a tribool is really needed</p>
<p>Second, optional<> provides an implicit conversion to bool. This conversion
refers to the initialization state and not to the contained value.<br>
Using optional<bool> can lead to subtle errors due to the implicit bool conversion:</p>
<p>Second, optional<> provides a simple way to test initialization state: an implicit conversion to a type that evaluates as a 'bool' in a boolean context.<br>
Using optional<bool> can lead to subtle errors due to this implicit conversion:</p>
<pre>void foo ( bool v ) ;
void bar()
{
@ -1524,7 +1695,9 @@ void bar()
integral promotions don't apply (i.e. if foo() takes an 'int' instead, it won't compile). <HR>
<li><code>optional<T>:::reset ( T const&)</code></li>
</ul>
<p>Can only <i>guarantee</i> the <u>basic exception safety</u>: The lvalue optional is left <u>uninitialized</u>if an exception is thrown (any previous value is<i>first</i> destroyed using T::~T())</p>
<p>cannot offer any <i>exception safety guarantee</i>beyond that provided by<code>T::operator=( T const& )</code></p>
<p>On the other hand, the <i>uninitializing</i> methods:</p>
<p>Provide the no-throw guarantee (assuming a no-throw T::~T())</p>
<p>However, since <code>optional<></code> 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.</p>
<pre>//
// Case 1: Exception thrown during assignment.
//
T v0(123);
optional<T> opt0(v0);
try
{
T v1(456);
optional<T> opt1(v1);
opt0 = opt1 ;
<p>Provides the no-throw guarantee (assuming a no-throw T::~T()) becuse it only destroys the stored object.</p>
// If no exception was thrown, assignment succeeded.
assert( *opt0 == v1 ) ;
}
catch(...)
{
// If any exception was thrown, 'opt0' is reset to uninitialized.
assert( !opt0 ) ;
}
//
// 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 ) ;
}
</pre>
<H3><u>Swap:</u></H3>
<p><code>void swap( optional<T>&, optional<T>& )</code> has the same exception guarantee as <code>swap(T&,T&)</code> when both optionals are initialized.<br>
If only one of the optionals is initialized, it gives the same<i>basic</i> exception guarantee as <code>optional<T>::reset( T const& )</code> (since <code>optional<T>::reset()</code> doesn't throw).<br>
If only one of the optionals is initialized, it gives the same exception guarantee as <code>T::operator=( T const& )</code> (since <code>optional<T>::operator=( none_t )</code> doesn't throw).<br>
If none of the optionals is initialized, it has no-throw guarantee since it is a no-op. </p>
<HR>
@ -1604,14 +1734,11 @@ T <u>is not</u> required to be <a href="http://www.sgi.com/tech/stl/DefaultConst
<H2><ANAME="impl">Implementation Notes</A></H2>
<p>optional<T> is currently implemented
using a custom aligned storage facility built from <code>alignment_of</code> and <code>type_with_alignment</code> (both from Type Traits).
It uses a separate boolean flag to indicate the initialization state.<br>
Placement new with T's copy constructor and T's destructor
are explicitly used to initialize,copy and destroy optional values.<br>
As a result, T's default constructor is effectively by-passed, but the exception
guarantees are basic.<br>
It is planned to replace the current implementation with another with
stronger exception safety, such as a future boost::variant<T,nil_t>. </p>
using a custom aligned storage facility built from <code>alignment_of</code> and <code>type_with_alignment</code> (both from Type Traits).
It uses a separate boolean flag to indicate the initialization state.</p>
<p>Placement new with T's copy constructor and T's destructor
is explicitly used to initialize and destroy optional values. This allows T's default constructor to be effectively by-passed.</p>
<p>If assignment is used and the lvalue optional is uninitialized, T's copy constructor is used. However, if it is already initialized, T's assignment operator is used. This prevents optional from offering any exception guarantee stronger than the one offered by the type T itself</p>
<HR>
@ -1665,12 +1792,12 @@ T <u>is not</u> required to be <a href="http://www.sgi.com/tech/stl/DefaultConst
</blockquote>
<HR>
<P>Revised April 21, 2005</P>
<p><EFBFBD> Copyright Fernando Luis Cacciola Carballal, 2003,2004,2005</p>
<P>Revised March 27, 2007</P>
<p><EFBFBD> Copyright Fernando Luis Cacciola Carballal, 2003-2007</p>
<p> Use, modification, and distribution are subject to the Boost Software
License, Version 1.0. (See accompanying file <ahref="../../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or copy at <ahref="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a>)</p>
<P>Developed by <AHREF="mailto:fernando_cacciola@hotmail.com">Fernando Cacciola</A>,
the latest version of this file can be found at <A
HREF="http://www.boost.org">www.boost.org</A>, and the boost <AHREF="http://www.boost.org/more/mailing_lists.htm#main">discussion lists</A></P>
// Copyright (C) 2003, Fernando Luis Cacciola Carballal.
//
// 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:
// fernando_cacciola@hotmail.com
//
#include"boost/optional.hpp"
//
// THIS TEST SHOULD FAIL TO COMPILE
//
voidoptional_reference__test_no_ptr_access()
{
boost::optional<int&>opt;
opt.get_ptr();
}
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.