Some additional functions added to optional (being new there won't be regressions)

[SVN r34411]
This commit is contained in:
Fernando Cacciola
2006-06-26 18:01:38 +00:00
parent a77dff3e11
commit 734e5b5283
3 changed files with 247 additions and 45 deletions

View File

@ -3,7 +3,6 @@
<HTML>
<HEAD>
<meta http-equiv="Content-Language" content="en-us">
<meta name="GENERATOR" content="Microsoft FrontPage 5.0">
<meta name="ProgId" content="FrontPage.Editor.Document">
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=windows-1252">
@ -324,6 +323,8 @@ class optional
optional ( T const&amp; v ) ;
optional ( bool condition, T const&amp; v ) ; <u><i>[new in 1.34]</u></i>
optional ( optional const&amp; rhs ) ;
template&lt;class U&gt; explicit optional ( optional&lt;U&gt; const&amp; rhs ) ;
@ -347,6 +348,8 @@ class optional
T const& get() const ;
T& get() ;
T<span lang="es"> const&amp;</span> get_value_or( T const&amp; default ) const ; <u><i>[new in 1.34]</u></i>
T const* operator -&gt;() const ;
T* operator -&gt;() ;
@ -380,6 +383,12 @@ template&lt;class T&gt; inline bool operator <= ( optional&lt;T&gt; const& x, op
template&lt;class T&gt; inline bool operator >= ( optional&lt;T&gt; const& x, optional&lt;T&gt; const& y ) ;
template&lt;class T&gt; inline optional&lt;T&gt; make_optional ( T const& v ) ; <u><i>[new in 1.34]</u></i>
template&lt;class T&gt; inline optional&lt;T&gt; make_optional ( bool condition, T const& v ) ; <u><i>[new in 1.34]</u></i>
template&lt;class T&gt; inline T <span lang="es">const&amp; </span>get_<span lang="es">optional_</span>value_or ( optional&lt;T&gt; const& opt, T const& default ) ; <u><i>[new in 1.34]</u></i>
template&lt;class T&gt; inline T const& get ( optional&lt;T&gt; const& opt ) ;
template&lt;class T&gt; inline T& get ( optional&lt;T&gt; & opt ) ;
@ -436,7 +445,7 @@ assert ( !def ) ;</pre>
<pre>optional&lt;T&gt;::optional( none_t );</pre>
<blockquote>
<p><b>Effect:</b> Constructs an <b>optional </b>uninitialized.</p>
<p><b>Effect:</b> Constructs an <b>optional</b> uninitialized.</p>
<p><b>Postconditions:</b> <b>*this</b> is <u>uninitialized</u>.</p>
<p><b>Throws:</b> Nothing.</p>
<p><b>Notes:</b></p>
@ -459,7 +468,6 @@ assert ( !n ) ;</pre>
<pre>optional&lt;T <i>(not a ref)</i>&gt;::optional( T const&amp; v )</pre>
<blockquote>
<p><b>Effect:</b> Directly-Constructs an <b>optional</b>.</p>
<!-- TemplateName: general/sy_footer_inc.isml -->
<p><b>Postconditions:</b> <b>*this</b> is <u>initialized</u> and its value is a <i>copy</i> of 'v'.</p>
<p><b>Throws:</b> Whatever T::T( T const&amp; ) throws.</p>
<p><b>Notes: </b> T::T( T const&amp; ) is called.</p>
@ -495,6 +503,23 @@ assert (*opt == v); </pre>
<HR>
<pre>optional&lt;T <i>(not a ref)</i>&gt;::optional( bool condition, T const&amp; v ) ;
optional&lt;T&amp;&gt; <span lang="es"> </span>::optional( bool condition, T&amp; <span lang="es"> </span> v ) ;
</pre>
<blockquote>
<p>If <i>condition</i> is <code>true</code>, same as:</p>
<pre>optional&lt;T <i>(not a ref)</i>&gt;::optional( T const&amp; v )
optional&lt;T&amp;&gt;<span lang="es"> </span>::optional( T&amp;<span lang="es"> </span> v )
</pre>
<p>otherwise, same as:</p>
<pre>optional&lt;T <i>(not a ref)</i>&gt;::optional()
optional&lt;T&amp;&gt;<span lang="es"> </span>::optional()
</pre>
</blockquote>
<HR>
<pre>optional&lt;T <i>(not a ref)</i>&gt;::optional( optional const&amp; rhs );</pre>
<blockquote>
<p><b>Effect:</b> Copy-Constructs an <b>optional</b>.</p>
@ -797,7 +822,6 @@ assert ( *opt1 == static_cast&lt;U&gt;(v) ) ;
<HR>
<pre>T const&amp; optional&lt;T <i>(not a ref)</i>&gt;::operator*() const ;
T&amp; optional&lt;T<i> (not a ref)</i>&gt;::operator*();</pre>
@ -828,6 +852,32 @@ assert ( *opt == w ) ;
<HR>
<pre>T const&amp; optional&lt;T <i>(not a ref)</i>&gt;::get_value_or( T const&amp; default) const ;
T&amp; optional&lt;T <i>(not a ref)</i>&gt;::get_value_or( T&amp; default ) ;
inline T const&amp; get_optional_value_or ( optional&lt;T<i> (not a ref)</i>&gt; const&amp; o, T const&amp; default ) ;
inline T&amp; get_optional_value_or ( optional&lt;T <i>(not a ref)</i>&gt;&amp; o, T&amp; default ) ;
</pre>
<blockquote>
<p><b>Returns:</b> A reference to the contained value, if any, or <code>default</code></p>
<p><b>Throws:</b> Nothing.</p>
<p><b>Example:</b></p>
<blockquote>
<pre>T v, z ;
optional&lt;T&gt; def;
T const&amp; y = def.get_value_or(z);
assert ( y == z ) ;
optional&lt;T&gt; opt ( v );
T const&amp; u = get_optional_value_or(opt,z);
assert ( u == v ) ;
assert ( u != z ) ;
</pre>
</blockquote>
<pre></pre>
</blockquote>
<HR>
<pre>T const&amp; optional&lt;T&amp;&gt;::operator*() const ;
T &amp; optional&lt;T<i>&amp;</i>&gt;::operator*();</pre>
@ -965,18 +1015,47 @@ assert ( opt.is_initialized() );</pre>
<HR>
<pre>optional&lt;T <i>(not a ref)</i>&gt; make_optional( T const&amp; v )</pre>
<blockquote>
<p><b>Returns:</b> optional&lt;T&gt;(v) for the <i>deduced</i> type <code>T</code> of <code>v</code>.</p>
<p><b>Example:</b></p>
<blockquote>
<pre>template&lt;class T&gt; void foo ( optional&lt;T&gt; const& opt ) ;
foo ( make_optional(1+1) ) ; // Creates an optional&lt;int&gt;
</blockquote>
</blockquote>
<HR>
<pre>optional&lt;T <i>(not a ref)</i>&gt; make_optional( bool condition, T const&amp; v )</pre>
<blockquote>
<p><b>Returns:</b> optional&lt;T&gt;(condition,v) for the <i>deduced</i> type <code>T</code> of <code>v</code>.</p>
<p><b>Example:</b></p>
<blockquote>
<pre>optional&lt;double&gt; calculate_foo()
{
double val = compute_foo();
return make_optional(is_not_nan_and_finite(val),val);
}
optional&lt;double&gt; v = calculate_foo();
if ( !v )
error("foo wasn't computed");
</blockquote>
</blockquote>
<HR>
<pre>bool operator == ( optional&lt;T&gt; const&amp x, optional&lt;T&gt const&amp y );</pre>
<blockquote>
<p><b>Returns:</b> If both <b>x</b> and <b>y</b> are initialied, <code>(*x == *y)</code>.
If only x or y is initialized, <code>false</code>. If both are uninitialized, <code>true</code>.
</p>
If only x or y is initialized, <code>false</code>. If both are uninitialized, <code>true</code>. </p>
<p><b>Throws:</b> Nothing.</p>
<p><b>Notes:</b> Pointers have shallow relational operators while <b>optional</b> has
deep relational operators. Do not use operator == directly in generic code
which expect to be given either an optional&lt;T&gt; or a pointer;
use <a href="../../utility/OptionalPointee.html#equal">equal_pointees()</a> instead
</p>
use <a href="../../utility/OptionalPointee.html#equal">equal_pointees()</a> instead </p>
<p><b>Example:</b></p>
<blockquote>
<pre>T x(12);
@ -1012,14 +1091,12 @@ assert ( optX != optZ ) ;
<blockquote>
<p><b>Returns:</b> If <b>y</b> is not initialized, <code>false</code>.
If <b>y</b> is initialized and <b>x</b> is not initialized, <code>true</code>.
If both <b>x</b> and <b>y</b> are initialized, <code>(*x &lt; *y)</code>.
</p>
If both <b>x</b> and <b>y</b> are initialized, <code>(*x &lt; *y)</code>. </p>
<p><b>Throws:</b> Nothing.</p>
<p><b>Notes:</b> Pointers have shallow relational operators while <b>optional</b> has
deep relational operators. Do not use operator &lt; directly in generic code
which expect to be given either an optional&lt;T&gt; or a pointer;
use <a href="../../utility/OptionalPointee.html#less">less_pointees()</a> instead
</p>
use <a href="../../utility/OptionalPointee.html#less">less_pointees()</a> instead </p>
<p><b>Example:</b></p>
<blockquote>
<pre>T x(12);
@ -1082,23 +1159,17 @@ assert ( optX != optZ ) ;
<pre>void swap ( optional&lt;T&gt;&amp x, optional&lt;T&gt&amp y );</pre>
<blockquote>
<p><b>Effect:</b> If both <b>x</b> and <b>y</b> are initialized, calls <code>swap(*x,*y)</code>
using std::swap.<br>
<p><b>Effect:</b> If both <b>x</b> and <b>y</b> are initialized, calls <code>swap(*x,*y)</code> using std::swap.<br>
If only one is initialized, say x, calls: <code>y.reset(*x); x.reset();</code><br>
If none is initialized, does nothing.
</p>
If none is initialized, does nothing. </p>
<p><b>Postconditions:</b> The states of x and y interchanged.</p>
<p><b>Throws:</b> If both are initialized, whatever swap(T&amp;,T&amp;) throws.
If only one is initialized, whatever T::T ( T const&amp; ) throws.
</p>
<p><b>Notes:</b> If both are initialized, swap(T&amp;,T&amp;) is used <i>unqualified</i>
but with std::swap introduced in scope.<br>
If only one is initialized, T::~T() and T::T( T const& ) is called.
</p>
If only one is initialized, whatever T::T ( T const&amp; ) throws. </p>
<p><b>Notes:</b> If both are initialized, swap(T&amp;,T&amp;) is used <i>unqualified</i> but with std::swap introduced in scope.<br>
If only one is initialized, T::~T() and T::T( T const& ) is called. </p>
<p><b>Exception Safety:</b> If both are initialized, this operation has the exception
safety guarantees of swap(T&,T&).<br>
If only one is initialized, it has the same <b>basic</b> guarantee as optional&lt;T&gt;::reset( T const& ).
</p>
If only one is initialized, it has the same <b>basic</b> guarantee as optional&lt;T&gt;::reset( T const& ). </p>
<p><b>Example:</b></p>
<blockquote>
<pre>T x(12);
@ -1254,8 +1325,7 @@ assert(a==b);
b = 3 ;
assert(ra!=b); // 'ra' is not rebound to 'b'
</pre>
<p>Now, if you assign to an <i>initialized</i> optional&lt;T&amp;&gt;, the effect is to <b>
rebind</b> to the new object instead of assigning the referee. This is unlike
<p>Now, if you assign to an <i>initialized</i> optional&lt;T&amp;&gt;, the effect is to <b>rebind</b> to the new object instead of assigning the referee. This is unlike
bare C++ references.</p>
<pre>int a = 1 ;
int b = 2 ;
@ -1358,8 +1428,7 @@ public:
</pre>
<p>A limitation of this method is that it doesn't scale well to wrapped objects with multiple
constructors nor to generic code were the constructor overloads are unknown.</p>
<p>The solution presented in this library is the family of <b>InPlaceFactories</b> and
<b>TypedInPlaceFactories</b>.<br>
<p>The solution presented in this library is the family of <b>InPlaceFactories</b> and <b>TypedInPlaceFactories</b>.<br>
These factories are a family of classes which encapsulate an increasing number of arbitrary
constructor parameters and supply a method to construct an object of a given type using those
parameters at an address specified by the user via placement new.</p>
@ -1427,10 +1496,7 @@ public:
W ( in_place(123,"hello") ) ;
}
</pre>
<p>The factories are implemented in the headers:
<a href="../../../boost/utility/in_place_factory.hpp">in_place_factory.hpp</a> and
<a href="../../../boost/utility/typed_in_place_factory.hpp">typed_in_place_factory.hpp</a>
</p>
<p>The factories are implemented in the headers: <a href="../../../boost/utility/in_place_factory.hpp">in_place_factory.hpp</a> and <a href="../../../boost/utility/typed_in_place_factory.hpp">typed_in_place_factory.hpp</a> </p>
<HR>
@ -1473,8 +1539,7 @@ of the assignment methods:</p>
TypedInPlaceFactory const&amp; ) </code></li>
<li> <code>optional&lt;T&gt;:::reset ( T const&amp;)</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>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>On the other hand, the <i>uninitializing</i> methods:</p>
<ul>
<li><code>optional&lt;T&gt;::operator= ( detail::none_t ) </code></li>
@ -1603,12 +1668,9 @@ T <u>is not</u> required to be <a href="http://www.sgi.com/tech/stl/DefaultConst
<P>Revised April 21, 2005</P>
<p><EFBFBD> Copyright Fernando Luis Cacciola Carballal, 2003,2004,2005</p>
<p> Use, modification, and distribution are subject to the Boost Software
License, Version 1.0. (See accompanying file <a href="../../../LICENSE_1_0.txt">
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
www.boost.org/LICENSE_1_0.txt</a>)</p>
License, Version 1.0. (See accompanying file <a href="../../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a>)</p>
<P>Developed by <A HREF="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
<A HREF="http://www.boost.org/more/mailing_lists.htm#main">discussion lists</A></P>
</BODY>
HREF="http://www.boost.org">www.boost.org</A>, and the boost <A HREF="http://www.boost.org/more/mailing_lists.htm#main">discussion lists</A></P>
</pre></BODY>
</HTML>

View File

@ -186,6 +186,16 @@ class optional_base : public optional_tag
construct(val);
}
// 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 )
:
m_initialized(false)
{
if ( cond )
construct(val);
}
// Creates a deep copy of another optional<T>
// Can throw if T::T(T const&) does
optional_base ( optional_base const& rhs )
@ -455,6 +465,9 @@ class optional : public optional_detail::optional_base<T>
// Can throw if T::T(T const&) does
optional ( argument_type val ) : base(val) {}
// 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) {}
#ifndef BOOST_OPTIONAL_NO_CONVERTING_COPY_CTOR
// NOTE: MSVC needs templated versions first
@ -549,6 +562,10 @@ class optional : public optional_detail::optional_base<T>
reference_const_type get() const { BOOST_ASSERT(this->is_initialized()) ; return this->get_impl(); }
reference_type get() { BOOST_ASSERT(this->is_initialized()) ; return this->get_impl(); }
// Returns a copy of the value if this is initialized, 'v' otherwise
reference_const_type get_value_or ( reference_const_type v ) const { return this->is_initialized() ? get() : v ; }
reference_type get_value_or ( reference_type v ) { return this->is_initialized() ? get() : v ; }
// Returns a pointer to the value if this is initialized, otherwise,
// the behaviour is UNDEFINED
// No-throw
@ -570,6 +587,22 @@ class optional : public optional_detail::optional_base<T>
bool operator!() const { return !this->is_initialized() ; }
} ;
// Returns optional<T>(v)
template<class T>
inline
optional<T> make_optional ( T const& v )
{
return optional<T>(v);
}
// Returns optional<T>(cond,v)
template<class T>
inline
optional<T> make_optional ( bool cond, T const& v )
{
return optional<T>(cond,v);
}
// Returns a reference to the value if this is initialized, otherwise, the behaviour is UNDEFINED.
// No-throw
template<class T>
@ -606,6 +639,24 @@ get ( optional<T>* opt )
return opt->get_ptr() ;
}
// Returns a reference to the value if this is initialized, otherwise, the behaviour is UNDEFINED.
// No-throw
template<class T>
inline
BOOST_DEDUCED_TYPENAME optional<T>::reference_const_type
get_optional_value_or ( optional<T> const& opt, BOOST_DEDUCED_TYPENAME optional<T>::reference_const_type v )
{
return opt.get_value_or(v) ;
}
template<class T>
inline
BOOST_DEDUCED_TYPENAME optional<T>::reference_type
get_optional_value_or ( optional<T>& opt, BOOST_DEDUCED_TYPENAME optional<T>::reference_type v )
{
return opt.get_value_or(v) ;
}
// Returns a pointer to the value if this is initialized, otherwise, returns NULL.
// No-throw
template<class T>
@ -767,10 +818,6 @@ template<class T> inline void swap ( optional<T>& x, optional<T>& y )
optional_detail::optional_swap(x,y);
}
template<class T> inline optional<T> make_optional ( T const& v )
{
return optional<T>(v);
}
} // namespace boost

View File

@ -15,7 +15,9 @@
#define BOOST_ENABLE_ASSERT_HANDLER
#include "boost/optional.hpp"
#include "boost/bind/apply.hpp" // Included just to test proper interaction with boost::apply<> as reported by Daniel Wallin
#include "boost/optional/optional.hpp"
#ifdef __BORLANDC__
#pragma hdrstop
@ -151,6 +153,95 @@ void test_basics( T const* )
ob.reset();
check_is_pending_dtor( ARG(T) ) ;
check_uninitialized(ob);
}
template<class T>
void test_conditional_ctor_and_get_valur_or ( T const* )
{
TRACE( std::endl << BOOST_CURRENT_FUNCTION );
T a(321);
T z(123);
optional<T> const cdef0(false,a);
optional<T> def0(false,a);
optional<T> def1 = boost::make_optional(false,a); // T is not within boost so ADL won't find make_optional unqualified
check_uninitialized(def0);
check_uninitialized(def1);
optional<T> const co0(true,a);
optional<T> o0(true,a);
optional<T> o1 = boost::make_optional(true,a); // T is not within boost so ADL won't find make_optional unqualified
check_initialized(o0);
check_initialized(o1);
check_value(o0,a,z);
check_value(o1,a,z);
T b = def0.get_value_or(z);
BOOST_CHECK( b == z ) ;
b = get_optional_value_or(def0,z);
BOOST_CHECK( b == z ) ;
b = o0.get_value_or(z);
BOOST_CHECK( b == a ) ;
b = get_optional_value_or(o0,z);
BOOST_CHECK( b == a ) ;
T const& crz = z ;
T& rz = z ;
T const& crzz = def0.get_value_or(crz);
BOOST_CHECK( crzz == crz ) ;
T& rzz = def0.get_value_or(rz);
BOOST_CHECK( rzz == rz ) ;
T const& crzzz = get_optional_value_or(cdef0,crz);
BOOST_CHECK( crzzz == crz ) ;
T& rzzz = get_optional_value_or(def0,rz);
BOOST_CHECK( rzzz == rz ) ;
T const& crb = o0.get_value_or(crz);
BOOST_CHECK( crb == a ) ;
T& rb = o0.get_value_or(rz);
BOOST_CHECK( rb == b ) ;
T const& crbb = get_optional_value_or(co0,crz);
BOOST_CHECK( crbb == b ) ;
T const& crbbb = get_optional_value_or(o0,crz);
BOOST_CHECK( crbbb == b ) ;
T& rbb = get_optional_value_or(o0,rz);
BOOST_CHECK( rbb == b ) ;
T& ra = a ;
optional<T&> defref(false,ra);
BOOST_CHECK(!defref);
optional<T&> ref(true,ra);
BOOST_CHECK(!!ref);
a = T(432);
BOOST_CHECK( *ref == a ) ;
T& r1 = defref.get_value_or(z);
BOOST_CHECK( r1 == z ) ;
T& r2 = ref.get_value_or(z);
BOOST_CHECK( r2 == a ) ;
}
//
@ -688,6 +779,7 @@ void test_with_builtin_types()
TRACE( std::endl << BOOST_CURRENT_FUNCTION );
test_basics( ARG(double) );
test_conditional_ctor_and_get_valur_or( ARG(double) );
test_uninitialized_access( ARG(double) );
test_no_throwing_swap( ARG(double) );
test_relops( ARG(double) ) ;
@ -699,6 +791,7 @@ void test_with_class_type()
TRACE( std::endl << BOOST_CURRENT_FUNCTION );
test_basics( ARG(X) );
test_conditional_ctor_and_get_valur_or( ARG(X) );
test_direct_value_manip( ARG(X) );
test_uninitialized_access( ARG(X) );
test_throwing_direct_init( ARG(X) );