Member fun value() that throws on uninitialized

This commit is contained in:
Andrzej Krzemienski
2014-05-22 23:32:49 +02:00
parent 5e59e10f93
commit 75271b73a8
11 changed files with 226 additions and 6 deletions

View File

@ -1200,6 +1200,43 @@
</pre>
</li>
</ul></div>
<p>
<span class="inlinemediaobject"><img src="../images/space.png" alt="space"></span>
</p>
<a name="reference_optional_value"></a><div class="blockquote"><blockquote class="blockquote"><p>
<code class="computeroutput"><span class="identifier">T</span> <span class="keyword">const</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="identifier">value</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span></code>
</p></blockquote></div>
<div class="blockquote"><blockquote class="blockquote"><p>
<code class="computeroutput"><span class="identifier">T</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="identifier">value</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> A reference to the contained
value, if <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>
is initialized.
</li>
<li class="listitem">
<span class="bold"><strong>Throws:</strong></span> An instance of <code class="computeroutput"><span class="identifier">bad_optional_access</span></code>,
if <code class="computeroutput"><span class="special">*</span><span class="keyword">this</span></code>
is not initialized.
</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">o0</span><span class="special">,</span> <span class="identifier">o1</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="identifier">o1</span><span class="special">.</span><span class="identifier">value</span><span class="special">()</span> <span class="special">==</span> <span class="identifier">v</span> <span class="special">);</span>
<span class="keyword">try</span> <span class="special">{</span>
<span class="identifier">o0</span><span class="special">.</span><span class="identifier">value</span><span class="special">();</span> <span class="comment">// throws</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="keyword">catch</span><span class="special">(</span><span class="identifier">bad_optional_access</span><span class="special">&amp;)</span> <span class="special">{</span>
<span class="identifier">asert</span> <span class="special">(</span> <span class="keyword">true</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>

View File

@ -95,8 +95,8 @@
</p>
<p>
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
throws, assignments to <code class="computeroutput"><span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span></code>
do not throw anything else on its own. A throw during assignment never changes
the initialization state of any optional object involved:
</p>
<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>

View File

@ -90,6 +90,9 @@
<span class="identifier">T</span> <span class="keyword">const</span><span class="special">&amp;</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_get"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
<span class="identifier">T</span><span class="special">&amp;</span> <span class="keyword">operator</span> <span class="special">*()</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_optional_get"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
<span class="identifier">T</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">value</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_optional_value"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
<span class="identifier">T</span><span class="special">&amp;</span> <span class="identifier">value</span><span class="special">()</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_optional_value"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
<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>

View File

@ -92,7 +92,7 @@
</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: May 08, 2014 at 12:05:10 GMT</small></p></td>
<td align="left"><p><small>Last revised: May 22, 2014 at 21:28:38 GMT</small></p></td>
<td align="right"><div class="copyright-footer"></div></td>
</tr></table>
<hr>

View File

@ -75,6 +75,9 @@
T const& operator *() const ; ``[link reference_optional_get __GO_TO__]``
T& operator *() ; ``[link reference_optional_get __GO_TO__]``
T const& value() const ; ``[link reference_optional_value __GO_TO__]``
T& value() ; ``[link reference_optional_value __GO_TO__]``
T const* get_ptr() const ; ``[link reference_optional_get_ptr __GO_TO__]``
T* get_ptr() ; ``[link reference_optional_get_ptr __GO_TO__]``
@ -803,6 +806,31 @@ assert ( *opt == w ) ;
__SPACE__
[#reference_optional_value]
[: `T const& optional<T>::value() const ;`]
[: `T& optional<T>::value();`]
* [*Returns:] A reference to the contained value, if `*this` is initialized.
* [*Throws:] An instance of `bad_optional_access`, if `*this` is not initialized.
* [*Example:]
``
T v ;
optional<T> o0, o1 ( v );
assert ( o1.value() == v );
try {
o0.value(); // throws
assert ( false );
}
catch(bad_optional_access&) {
asert ( true );
}
``
__SPACE__
[#reference_optional_get_value_or_value]
[: `T const& optional<T` ['(not a ref)]`>::get_value_or( T const& default) const ;`]

View File

@ -336,7 +336,7 @@ Regarding the following assignment functions:
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.
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:
Unless `T`'s constructor or assignment throws, assignments to `optional<T>` do not throw anything else on its own. A throw during assignment never changes the initialization state of any optional object involved:
optional<T> opt1(val1);

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/libs/optional for documentation.
//
// You are welcome to contact the author at:
// akrzemi1@gmail.com
//
#ifndef BOOST_BAD_OPTIONAL_ACCESS_22MAY2014_HPP
#define BOOST_BAD_OPTIONAL_ACCESS_22MAY2014_HPP
#include <stdexcept>
namespace boost {
class bad_optional_access : public std::logic_error
{
public:
explicit bad_optional_access(const std::string& what_arg) : std::logic_error(what_arg) {}
explicit bad_optional_access(const char* what_arg) : std::logic_error(what_arg) {}
};
} // namespace boost
#endif

View File

@ -23,7 +23,9 @@
#include <boost/config.hpp>
#include <boost/assert.hpp>
#include <boost/bad_optional_access.hpp>
#include <boost/static_assert.hpp>
#include <boost/throw_exception.hpp>
#include <boost/type.hpp>
#include <boost/type_traits/alignment_of.hpp>
#include <boost/type_traits/has_nothrow_constructor.hpp>
@ -936,6 +938,22 @@ class optional : public optional_detail::optional_base<T>
reference_const_type operator *() const { return this->get() ; }
reference_type operator *() { return this->get() ; }
reference_const_type value() const
{
if (this->is_initialized())
return this->get() ;
else
throw_exception(bad_optional_access("Attempted to access the value of an uninitialized optional object."));
}
reference_type value()
{
if (this->is_initialized())
return this->get() ;
else
throw_exception(bad_optional_access("Attempted to access the value of an uninitialized optional object."));
}
bool operator!() const BOOST_NOEXCEPT { return !this->is_initialized() ; }
BOOST_EXPLICIT_OPERATOR_BOOL()

View File

@ -11,11 +11,9 @@
//
// 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 {

View File

@ -23,6 +23,7 @@ import testing ;
[ run optional_test_io.cpp ]
[ run optional_test_move.cpp ]
[ run optional_test_equals_none.cpp ]
[ run optional_test_value_access.cpp ]
[ compile-fail optional_test_fail1.cpp ]
[ compile-fail optional_test_fail3a.cpp ]
[ compile-fail optional_test_fail3b.cpp ]

View File

@ -0,0 +1,107 @@
// 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 IntWrapper
{
int _i;
IntWrapper(int i) : _i(i) {}
bool operator==(IntWrapper const& rhs) const { return _i == rhs._i; }
};
template <typename T>
void test_function_value_for()
{
optional<T> o0;
optional<T> o1(1);
const optional<T> oC(2);
try
{
T& v = o1.value();
BOOST_CHECK(v == 1);
}
catch(...)
{
BOOST_CHECK(false);
}
try
{
T const& v = oC.value();
BOOST_CHECK(v == 2);
}
catch(...)
{
BOOST_CHECK(false);
}
try
{
T& v = o0.value();
BOOST_CHECK(false);
unused_variable(v);
}
catch(boost::bad_optional_access const&)
{
}
catch(...)
{
BOOST_CHECK(false);
}
}
void test_function_value()
{
test_function_value_for<int>();
test_function_value_for<float>();
test_function_value_for<IntWrapper>();
}
int test_main( int, char* [] )
{
try
{
test_function_value();
}
catch ( ... )
{
BOOST_ERROR("Unexpected Exception caught!");
}
return 0;
}