forked from boostorg/optional
Optional's Assignment fixed
[SVN r28412]
This commit is contained in:
@ -20,6 +20,7 @@ HREF="../../../boost/optional/optional.hpp">boost/optional/optional.hpp</A>>
|
|||||||
<DT><A HREF="#semantics">Semantics</A></DT>
|
<DT><A HREF="#semantics">Semantics</A></DT>
|
||||||
<DT><A HREF="#examples">Examples</A></DT>
|
<DT><A HREF="#examples">Examples</A></DT>
|
||||||
<DT><A HREF="#ref">Optional references</A></DT>
|
<DT><A HREF="#ref">Optional references</A></DT>
|
||||||
|
<DT><A HREF="#refassign">Rebinding semantics for assignment of optional references</A></DT>
|
||||||
<DT><A HREF="#inplace">In-Place Factories</A></DT>
|
<DT><A HREF="#inplace">In-Place Factories</A></DT>
|
||||||
<DT><A HREF="#bool">A note about optional<bool></A></DT>
|
<DT><A HREF="#bool">A note about optional<bool></A></DT>
|
||||||
<DT><A HREF="#exsafety">Exception Safety Guarantees</A></DT>
|
<DT><A HREF="#exsafety">Exception Safety Guarantees</A></DT>
|
||||||
@ -35,7 +36,7 @@ HREF="../../../boost/optional/optional.hpp">boost/optional/optional.hpp</A>>
|
|||||||
|
|
||||||
<P>Consider these functions which should return a value but which might not have
|
<P>Consider these functions which should return a value but which might not have
|
||||||
a value to return:</P>
|
a value to return:</P>
|
||||||
<pre>(A) double sqrt( double n );
|
<pre>(A) double sqrt(double n );
|
||||||
(B) char get_async_input();
|
(B) char get_async_input();
|
||||||
(C) point polygon::get_any_point_effectively_inside();</pre>
|
(C) point polygon::get_any_point_effectively_inside();</pre>
|
||||||
<P>There are different approaches to the issue of not having a value to return.</P>
|
<P>There are different approaches to the issue of not having a value to return.</P>
|
||||||
@ -100,11 +101,12 @@ if ( p.second )
|
|||||||
and neither default nor value initialization applies, it is said that the object is
|
and neither default nor value initialization applies, it is said that the object is
|
||||||
<i><b>uninitialized</b></i>. Its actual value exist but has an
|
<i><b>uninitialized</b></i>. Its actual value exist but has an
|
||||||
<i>indeterminate inital value</i> (c.f. 8.5.9).<br>
|
<i>indeterminate inital value</i> (c.f. 8.5.9).<br>
|
||||||
<code>optional<T></code> intends to formalize the notion of initialization/no-initialization
|
<code>optional<T></code> intends to formalize the notion of initialization
|
||||||
|
(or loack of it)
|
||||||
allowing a program to test whether an object has been initialized and stating that access to
|
allowing a program to test whether an object has been initialized and stating that access to
|
||||||
the value of an uninitialized object is undefined behaviour. That is,
|
the value of an uninitialized object is undefined behaviour. That is,
|
||||||
when a variable is declared as optional<T> and no initial value is given,
|
when a variable is declared as optional<T> and no initial value is given,
|
||||||
the variable is formally uninitialized. A formally uninitialized optional object has conceptually
|
the variable is <i>formally</i> uninitialized. A formally uninitialized optional object has conceptually
|
||||||
no value at all and this situation can be tested at runtime. It is formally <i>undefined behaviour</i>
|
no value at all and this situation can be tested at runtime. It is formally <i>undefined behaviour</i>
|
||||||
to try to access the value of an uninitialized optional. An uninitialized optional can be <i>assigned</i> a value, in which case its initialization state changes to initialized. Furthermore, given the formal
|
to try to access the value of an uninitialized optional. An uninitialized optional can be <i>assigned</i> a value, in which case its initialization state changes to initialized. Furthermore, given the formal
|
||||||
treatment of initialization states in optional objects, it is even possible to reset an optional to <i>uninitialized</i>.</P>
|
treatment of initialization states in optional objects, it is even possible to reset an optional to <i>uninitialized</i>.</P>
|
||||||
@ -122,8 +124,8 @@ if ( p.second )
|
|||||||
Using the <a href="../../../doc/html/variant.html">Boost.Variant</a> library, this model can be implemented
|
Using the <a href="../../../doc/html/variant.html">Boost.Variant</a> library, this model can be implemented
|
||||||
in terms of <code>boost::variant<T,nil_t></code>.<br>
|
in terms of <code>boost::variant<T,nil_t></code>.<br>
|
||||||
There is precedence for a discriminated union as a model for an optional value: the
|
There is precedence for a discriminated union as a model for an optional value: the
|
||||||
<a href="http://www.haskell.org/"><u>Haskell</u></a> <b>Maybe</b> builtin type constructor,
|
<a href="http://www.haskell.org/"><u>Haskell</u></a> <b>Maybe</b> builtin type constructor.
|
||||||
thus a discriminated union <code>T+nil_t</code> serves as a conceptual foundation.</p>
|
Thus, a discriminated union <code>T+nil_t</code> serves as a conceptual foundation.</p>
|
||||||
<p>A <code>variant<T,nil_t></code> follows naturally from the traditional idiom of extending
|
<p>A <code>variant<T,nil_t></code> follows naturally from the traditional idiom of extending
|
||||||
the range of possible values adding an additional sentinel value with the special meaning of <i>Nothing. </i>
|
the range of possible values adding an additional sentinel value with the special meaning of <i>Nothing. </i>
|
||||||
However, this additional <i>Nothing</i> value is largely irrelevant for our purpose
|
However, this additional <i>Nothing</i> value is largely irrelevant for our purpose
|
||||||
@ -180,33 +182,31 @@ object.</p>
|
|||||||
<p><b>Direct Value Construction via copy:</b> To introduce a formally
|
<p><b>Direct Value Construction via copy:</b> To introduce a formally
|
||||||
initialized wrapped object whose value is obtained as a copy of some object.</p>
|
initialized wrapped object whose value is obtained as a copy of some object.</p>
|
||||||
|
|
||||||
<p><b>Deep Copy Construction:</b> To obtain a different yet equivalent wrapped
|
<p><b>Deep Copy Construction:</b> To obtain a new yet equivalent wrapped
|
||||||
object.</p>
|
object.</p>
|
||||||
|
|
||||||
<p><b>Direct Value Assignment (upon initialized):</b> To assign the wrapped object a value obtained
|
<p><b>Direct Value Assignment (upon initialized):</b> To assign a value to the wrapped object.</p>
|
||||||
as a copy of some object.</p>
|
|
||||||
|
|
||||||
<p><b>Direct Value Assignment (upon uninitialized):</b> To initialize the wrapped object
|
<p><b>Direct Value Assignment (upon uninitialized):</b> To initialize the wrapped object
|
||||||
with a value obtained
|
with a value obtained
|
||||||
as a copy of some object.</p>
|
as a copy of some object.</p>
|
||||||
|
|
||||||
<p><b>Assignnment (upon initialized):</b> To assign the wrapped object a value obtained as a copy
|
<p><b>Assignnment (upon initialized):</b> To assign to the wrapped object the value
|
||||||
of another wrapper's object.</p>
|
of another wrapped object.</p>
|
||||||
|
|
||||||
<p><b>Assignnment (upon uninitialized):</b> To initialize the wrapped object
|
<p><b>Assignnment (upon uninitialized):</b> To initialize the wrapped object
|
||||||
with value obtained as a copy
|
with value of another wrapped object.</p>
|
||||||
of another wrapper's object.</p>
|
|
||||||
|
|
||||||
<p><b>Deep Relational Operations (when supported by the type T):</b> To compare
|
<p><b>Deep Relational Operations (when supported by the type T):</b> To compare
|
||||||
wrapped object values taking into account the presence of uninitialized
|
wrapped object values taking into account the presence of uninitialized
|
||||||
operands.</p>
|
states.</p>
|
||||||
|
|
||||||
<p><b>Value access:</b> To unwrap the wrapped object.</p>
|
<p><b>Value access:</b> To unwrap the wrapped object.</p>
|
||||||
|
|
||||||
<p><b>Initialization state query:</b> To determine if the object is formally
|
<p><b>Initialization state query:</b> To determine if the object is formally
|
||||||
initialized or not.</p>
|
initialized or not.</p>
|
||||||
|
|
||||||
<p><b>Swap:</b> To exchange wrapper's objects. (with whatever exception safety
|
<p><b>Swap:</b> To exchange wrapped objects. (with whatever exception safety
|
||||||
guarantiees are provided by T's swap).</p>
|
guarantiees are provided by T's swap).</p>
|
||||||
|
|
||||||
<p><b>De-initialization:</b> To release the wrapped object (if any) and leave
|
<p><b>De-initialization:</b> To release the wrapped object (if any) and leave
|
||||||
@ -313,7 +313,7 @@ class optional
|
|||||||
|
|
||||||
optional () ;
|
optional () ;
|
||||||
|
|
||||||
optional ( detail::none_t ) ;
|
optional ( none_t ) ;
|
||||||
|
|
||||||
optional ( T const& v ) ;
|
optional ( T const& v ) ;
|
||||||
|
|
||||||
@ -325,7 +325,7 @@ class optional
|
|||||||
|
|
||||||
template<class TypedInPlaceFactory> explicit optional ( TypedInPlaceFactory const& f ) ;
|
template<class TypedInPlaceFactory> explicit optional ( TypedInPlaceFactory const& f ) ;
|
||||||
|
|
||||||
optional& operator = ( detail::none_t ) ;
|
optional& operator = ( none_t ) ;
|
||||||
|
|
||||||
optional& operator = ( T const& v ) ;
|
optional& operator = ( T const& v ) ;
|
||||||
|
|
||||||
@ -427,7 +427,7 @@ assert ( !def ) ;</pre>
|
|||||||
|
|
||||||
<HR>
|
<HR>
|
||||||
|
|
||||||
<pre>optional<T>::optional( detail::none_t );</pre>
|
<pre>optional<T>::optional( none_t );</pre>
|
||||||
<blockquote>
|
<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>Postconditions:</b> <b>*this</b> is <u>uninitialized</u>.</p>
|
||||||
@ -436,11 +436,12 @@ assert ( !def ) ;</pre>
|
|||||||
<blockquote>
|
<blockquote>
|
||||||
<p>T's default constructor <u><i>is not</i></u> called.<br>
|
<p>T's default constructor <u><i>is not</i></u> called.<br>
|
||||||
The
|
The
|
||||||
expression <code>boost::none</code> denotes an instance of <code>boost::detail::none_t</code> that can be
|
expression <code>boost::none</code> denotes an instance of <code>boost::none_t</code> that can be
|
||||||
used as the parameter.</p>
|
used as the parameter.</p>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
<p><b>Example:</b></p>
|
<p><b>Example:</b></p>
|
||||||
<blockquote>
|
<blockquote>
|
||||||
|
<pre>#include <boost/none.hpp></pre>
|
||||||
<pre>optional<T> n(none) ;
|
<pre>optional<T> n(none) ;
|
||||||
assert ( !n ) ;</pre>
|
assert ( !n ) ;</pre>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
@ -468,7 +469,7 @@ assert ( *opt == v ) ;</pre>
|
|||||||
|
|
||||||
<HR>
|
<HR>
|
||||||
|
|
||||||
<pre>optional<T&>::optional( T ref )</pre>
|
<pre>optional<T&>::optional( T& ref )</pre>
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<p><b>Effect:</b> Directly-Constructs an <b>optional</b>.</p>
|
<p><b>Effect:</b> Directly-Constructs an <b>optional</b>.</p>
|
||||||
<p><b>Postconditions:</b> <b>*this</b> is <u>initialized</u> and its value is an
|
<p><b>Postconditions:</b> <b>*this</b> is <u>initialized</u> and its value is an
|
||||||
@ -522,12 +523,11 @@ assert ( init2 == init ) ;
|
|||||||
<blockquote>
|
<blockquote>
|
||||||
<p><b>Effect:</b> Copy-Constructs an <b>optional</b>.</p>
|
<p><b>Effect:</b> Copy-Constructs an <b>optional</b>.</p>
|
||||||
<p><b>Postconditions:</b> If <b>rhs</b> is initialized, <b>*this</b> is initialized
|
<p><b>Postconditions:</b> If <b>rhs</b> is initialized, <b>*this</b> is initialized
|
||||||
and its value is a <i>copy</i> of the internal wrapper holding the references in <b>rhs</b>; else <b>*this</b>
|
and its value is another reference to the same object referenced by <b>*rhs</b>; else <b>*this</b>
|
||||||
is uninitialized.</p>
|
is uninitialized.</p>
|
||||||
<p><b>Throws:</b> Nothing.</p>
|
<p><b>Throws:</b> Nothing.</p>
|
||||||
<p><b>Notes:</b> If <b>rhs</b> is initialized, the internal wrapper will be
|
<p><b>Notes:</b> If <b>rhs</b> is initialized, both <b>*this</b> and <b>*rhs</b> will
|
||||||
copied and just like true references, both <b>*this</b> and <b>rhs</b> will
|
refeer to the same object<b> </b>(they alias).</p>
|
||||||
referr to the same object<b> </b>(will alias).</p>
|
|
||||||
<p><b>Example:</b></p>
|
<p><b>Example:</b></p>
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<pre>optional<T&> uninit ;
|
<pre>optional<T&> uninit ;
|
||||||
@ -542,6 +542,13 @@ assert ( *init == v ) ;
|
|||||||
|
|
||||||
optional<T> init2 ( init ) ;
|
optional<T> init2 ( init ) ;
|
||||||
assert ( *init2 == v ) ;
|
assert ( *init2 == v ) ;
|
||||||
|
|
||||||
|
v = 3 ;
|
||||||
|
|
||||||
|
assert ( *init == 3 ) ;
|
||||||
|
assert ( *init2 == 3 ) ;
|
||||||
|
|
||||||
|
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
</blockquote>
|
</blockquote>
|
||||||
@ -615,22 +622,55 @@ assert ( *y == v ) ;
|
|||||||
<p><b>Effect:</b> Assigns the value 'rhs' to an <b>optional</b>.</p>
|
<p><b>Effect:</b> Assigns the value 'rhs' to an <b>optional</b>.</p>
|
||||||
<p><b>Postconditions:</b> <b>*this</b> is initialized
|
<p><b>Postconditions:</b> <b>*this</b> is initialized
|
||||||
and its value is a <i>copy</i> of <b>rhs.</b></p>
|
and its value is a <i>copy</i> of <b>rhs.</b></p>
|
||||||
<p><b>Throws:</b> Whatever T::T( T const& ) throws.</p>
|
<p><b>Throws:</b> Whatever T::operator=( T const& ) or T::T(T conbst&) throws.</p>
|
||||||
<p><b>Notes:</b> If <b>*this</b> was initialized, it is first reset to uninitialized
|
<p><b>Notes:</b> If <b>*this</b> was initialized, T's assignment operator is
|
||||||
using T::~T(), then T::T(<b>rhs</b>) is called.</p>
|
used, otherwise, its copy-contructor is used.</p>
|
||||||
<p><b>Exception Safety:</b> <u>Basic:</u> Exceptions can only be thrown during T::T( T const& );
|
<p><b>Exception Safety:</b> In the event of an exception, the initialization
|
||||||
in that case, <b>*this</b> is left <u>uninitialized</u>.
|
state of <b>*this</b> is unchanged and its value unspecified as far as optional
|
||||||
</p>
|
is concerned (it is up to T's operator=()) [If <b>*this</b> is initially
|
||||||
|
uninitialized and T's <i>copy constructor</i> fails, <b>*this</b> is left
|
||||||
|
properly uninitialized]</p>
|
||||||
<p><b>Example:</b></p>
|
<p><b>Example:</b></p>
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<pre>T x;
|
<pre>T x;
|
||||||
|
optional<T> def ;
|
||||||
optional<T> opt(x) ;
|
optional<T> opt(x) ;
|
||||||
|
|
||||||
T y;
|
T y;
|
||||||
|
def = y ;
|
||||||
|
assert ( *def == y ) ;
|
||||||
opt = y ;
|
opt = y ;
|
||||||
assert ( *opt == y ) ;
|
assert ( *opt == y ) ;</pre>
|
||||||
// previous value (copy of 'v') destroyed from within 'opt'.
|
</blockquote>
|
||||||
|
</blockquote>
|
||||||
|
|
||||||
|
<HR>
|
||||||
|
|
||||||
|
<pre>optional<T&>& optional<T&>::operator= ( T& const& rhs ) ;</pre>
|
||||||
|
<blockquote>
|
||||||
|
<p><b>Effect:</b> (Re)binds thee wrapped reference.</p>
|
||||||
|
<p><b>Postconditions:</b> <b>*this</b> is initialized
|
||||||
|
and it references the same object referenced by <b>rhs.</b></p>
|
||||||
|
<p><b>Notes:</b> If <b>*this</b> was initialized, is is <i>rebound</i> to the
|
||||||
|
new object. See <A HREF="#refassign">here</a> for details on this behaviour.</p>
|
||||||
|
<p><b>Example:</b></p>
|
||||||
|
<blockquote>
|
||||||
|
<pre>int a = 1 ;
|
||||||
|
int b = 2 ;
|
||||||
|
T& ra = a ;
|
||||||
|
T& rb = b ;
|
||||||
|
optional<int&> def ;
|
||||||
|
optional<int&> opt(ra) ;
|
||||||
|
|
||||||
|
def = rb ; // binds 'def' to 'b' through 'rb'
|
||||||
|
assert ( *def == b ) ;
|
||||||
|
*def = a ; // changes the value of 'b' to a copy of the value of 'a'
|
||||||
|
assert ( b == a ) ;
|
||||||
|
int c = 3;
|
||||||
|
int& rc = c ;
|
||||||
|
opt = rc ; // REBINDS to 'c' through 'rc'
|
||||||
|
c = 4 ;
|
||||||
|
assert ( *opt == 4 ) ;
|
||||||
</pre>
|
</pre>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
@ -644,21 +684,25 @@ assert ( *opt == y ) ;
|
|||||||
and its value is a <i>copy</i> of the value of <b>rhs</b>; else <b>*this</b>
|
and its value is a <i>copy</i> of the value of <b>rhs</b>; else <b>*this</b>
|
||||||
is uninitialized.
|
is uninitialized.
|
||||||
</p>
|
</p>
|
||||||
<p><b>Throws:</b> Whatever T::T( T const& ) throws.</p>
|
<p><b>Throws:</b> Whatever T::operator( T const&) or T::T( T const& ) throws.</p>
|
||||||
<p><b>Notes:</b> If <b>*this</b> was initialized, it is first reset to uninitialized
|
<p><b>Notes:</b> If both<b> *this</b> and <b>rhs</b> are initially initialized,
|
||||||
using T::~T(), then T::T( T const& ) is called if <b>rhs</b> is initialized.
|
T's <i>assignment</i> <i>operator</i> is used. If <b>*this</b> is initially initialized but <b>
|
||||||
</p>
|
rhs</b> is uinitialized, T's <i>destructor</i> is called. If <b>*this</b> is initially
|
||||||
<p><b>Exception Safety:</b> <u>Basic:</u> Exceptions can only be thrown during T::T( T const& );
|
uninitialized but rhs is initialized, T's <i>copy constructor</i> is called.
|
||||||
in that case, <b>*this</b> is left <u>uninitialized</u>.
|
|
||||||
</p>
|
</p>
|
||||||
|
<p><b>Exception Safety:</b> In the event of an exception, the initialization
|
||||||
|
state of <b>*this</b> is unchanged and its value unspecified as far as optional
|
||||||
|
is concerned (it is up to T's operator=()) [If <b>*this</b> is initially
|
||||||
|
uninitialized and T's <i>copy constructor</i> fails, <b>*this</b> is left
|
||||||
|
properly uninitialized]</p>
|
||||||
<p><b>Example:</b></p>
|
<p><b>Example:</b></p>
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<pre>T v;
|
<pre>T v;
|
||||||
optional<T> opt(v);
|
optional<T> opt(v);
|
||||||
optional<T> uninit ;
|
optional<T> def ;
|
||||||
|
|
||||||
opt = uninit ;
|
opt = def ;
|
||||||
assert ( !opt ) ;
|
assert ( !def ) ;
|
||||||
// previous value (copy of 'v') destroyed from within 'opt'.
|
// previous value (copy of 'v') destroyed from within 'opt'.
|
||||||
|
|
||||||
</pre>
|
</pre>
|
||||||
@ -667,6 +711,40 @@ assert ( !opt ) ;
|
|||||||
|
|
||||||
<HR>
|
<HR>
|
||||||
|
|
||||||
|
<pre>optional<T&> & optional<T&>::operator= ( optional<T&> const& rhs ) ;</pre>
|
||||||
|
<blockquote>
|
||||||
|
<p><b>Effect:</b> (Re)binds thee wrapped reference.</p>
|
||||||
|
<p><b>Postconditions:</b> If <b>*rhs</b> is initialized, *<b>this</b> is initialized
|
||||||
|
and it references the same object referenced by <b>*rhs</b>; otherwise, <b>*this</b>
|
||||||
|
is uninitialized (and references no object).</p>
|
||||||
|
<p><b>Notes:</b> If <b>*this</b> was initialized and so is <b>*rhs</b>, <b>this</b>
|
||||||
|
is is <i>rebound</i> to the new object. See <A HREF="#refassign">here</a> for details on this behaviour.</p>
|
||||||
|
<p><b>Example:</b></p>
|
||||||
|
<blockquote>
|
||||||
|
<pre>int a = 1 ;
|
||||||
|
int b = 2 ;
|
||||||
|
T& ra = a ;
|
||||||
|
T& rb = b ;
|
||||||
|
optional<int&> def ;
|
||||||
|
optional<int&> ora(ra) ;
|
||||||
|
optional<int&> orb(rb) ;
|
||||||
|
|
||||||
|
def = orb ; // binds 'def' to 'b' through 'rb' wrapped within 'orb'
|
||||||
|
assert ( *def == b ) ;
|
||||||
|
*def = ora ; // changes the value of 'b' to a copy of the value of 'a'
|
||||||
|
assert ( b == a ) ;
|
||||||
|
int c = 3;
|
||||||
|
int& rc = c ;
|
||||||
|
optional<int&> orc(rc) ;
|
||||||
|
ora = orc ; // REBINDS ora to 'c' through 'rc'
|
||||||
|
c = 4 ;
|
||||||
|
assert ( *ora == 4 ) ;
|
||||||
|
</pre>
|
||||||
|
</blockquote>
|
||||||
|
</blockquote>
|
||||||
|
|
||||||
|
<HR>
|
||||||
|
|
||||||
<pre>template<U> optional& optional<T <i>(not a ref)</i>>::operator= ( optional<U> const& rhs ) ;</pre>
|
<pre>template<U> optional& optional<T <i>(not a ref)</i>>::operator= ( optional<U> const& rhs ) ;</pre>
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<p><b>Effect:</b> Assigns another <i>convertible</i> <b>optional</b> to an <b>optional</b>.</p>
|
<p><b>Effect:</b> Assigns another <i>convertible</i> <b>optional</b> to an <b>optional</b>.</p>
|
||||||
@ -674,14 +752,17 @@ assert ( !opt ) ;
|
|||||||
and its value is a <i>copy</i> of the value of <b>rhs</b> <i>converted</i>
|
and its value is a <i>copy</i> of the value of <b>rhs</b> <i>converted</i>
|
||||||
to type T; else <b>*this</b> is uninitialized.
|
to type T; else <b>*this</b> is uninitialized.
|
||||||
</p>
|
</p>
|
||||||
<p><b>Throws:</b> Whatever T::T( U const& ) throws.</p>
|
<p><b>Throws:</b> Whatever T::operator=( U const& ) or T::T( U const& ) throws.</p>
|
||||||
<p><b>Notes:</b> If <b>*this</b> was initialized, it is first reset to uninitialized
|
<p><b>Notes:</b> If both<b> *this</b> and <b>rhs</b> are initially initialized,
|
||||||
using T::~T(), then T::T( U const& ) is called if <b>rhs</b> is initialized,
|
T's <i>assignment</i> <i>operator</i> (from U) is used. If <b>*this</b> is initially initialized but <b>
|
||||||
which requires a valid conversion from U to T.
|
rhs</b> is uinitialized, T's <i>destructor</i> is called. If <b>*this</b> is initially
|
||||||
</p>
|
uninitialized but rhs is initialized, T's <i>converting constructor</i> (from U) is called.
|
||||||
<p><b>Exception Safety:</b> <u>Basic:</u> Exceptions can only be thrown during T::T( U const& );
|
|
||||||
in that case, <b>*this</b> is left <u>uninitialized</u>.
|
|
||||||
</p>
|
</p>
|
||||||
|
<p><b>Exception Safety:</b> In the event of an exception, the initialization
|
||||||
|
state of <b>*this</b> is unchanged and its value unspecified as far as optional
|
||||||
|
is concerned (it is up to T's operator=()) [If <b>*this</b> is initially
|
||||||
|
uninitialized and T's <i>converting constructor</i> fails, <b>*this</b> is left
|
||||||
|
properly uninitialized]</p>
|
||||||
<p><b>Example:</b></p>
|
<p><b>Example:</b></p>
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<pre>T v;
|
<pre>T v;
|
||||||
@ -1118,7 +1199,7 @@ class Fred
|
|||||||
<HR>
|
<HR>
|
||||||
|
|
||||||
<H2><A NAME="ref">Optional references</A></H2>
|
<H2><A NAME="ref">Optional references</A></H2>
|
||||||
<p>This library allow the template parameter T to be of reference type: T&, and
|
<p>This library allows the template parameter T to be of reference type: T&, and
|
||||||
to some extent, T const&.</p>
|
to some extent, T const&.</p>
|
||||||
|
|
||||||
<p>However, since references are not real objects some restrictions apply and
|
<p>However, since references are not real objects some restrictions apply and
|
||||||
@ -1141,6 +1222,85 @@ value, a true real reference is stored so aliasing will ocurr: </p>
|
|||||||
than the reference itself.</li>
|
than the reference itself.</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
<HR>
|
||||||
|
<h2><A NAME="refassign">Rebinding semantics for assignment of optional
|
||||||
|
references</a></h2>
|
||||||
|
<p>If you assign to an <i>uninitialized</i> optional<T&> the effect is to bind (for the first time) to the object.
|
||||||
|
Clearly, there is no other choice.</p>
|
||||||
|
<pre>int x = 1 ;
|
||||||
|
int& rx = x ;
|
||||||
|
optional<int&> ora ;
|
||||||
|
optional<int&> orb(x) ;
|
||||||
|
ora = orb ; // now 'ora' is bound to 'x' through 'rx'
|
||||||
|
*ora = 2 ; // Changes value of 'x' through 'ora'
|
||||||
|
assert(x==2);
|
||||||
|
</pre>
|
||||||
|
<p>If you assign to a bare C++ reference, the assignment is forwarded to the
|
||||||
|
referenced object; it's value changes but the reference is never rebound.</p>
|
||||||
|
<pre>int a = 1 ;
|
||||||
|
int& ra = a ;
|
||||||
|
int b = 2 ;
|
||||||
|
int& rb = b ;
|
||||||
|
ra = rb ; // Changes the value of 'a' to 'b'
|
||||||
|
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<T&>, 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 ;
|
||||||
|
int& ra = a ;
|
||||||
|
int& rb = b ;
|
||||||
|
optional<int&> ora(ra) ;
|
||||||
|
optional<int&> orb(rb) ;
|
||||||
|
ora = orb ; // 'ora' is <b>rebound</b> to 'b'
|
||||||
|
*ora = 3 ; // Changes value of 'b' (not 'a')
|
||||||
|
assert(a==1);
|
||||||
|
assert(b==3);
|
||||||
|
</pre>
|
||||||
|
<h3>Rationale:</h3>
|
||||||
|
<p>Rebinding semantics for the assignment of <i>initialized</i> optional
|
||||||
|
references has been choosen to provide<b><i> </i>consistency among initialization
|
||||||
|
states<i> </i></b>even at the expense of lack of consistency with the semantics of bare
|
||||||
|
C++ references.<br>
|
||||||
|
It is true that optional<U> strives to behave as much as possible as U does
|
||||||
|
whenever it is initialized; but in the case when U is T&, doing so would result
|
||||||
|
in incosistent behaviour w.r.t to the lvalue initialization state.</p>
|
||||||
|
<p>Imagine optional<T&> fordwarding assignment to the referenced object (thus
|
||||||
|
changing the referenced object value but not rebinding), and consider the
|
||||||
|
following code :</p>
|
||||||
|
<pre> optional<int&> a = get();
|
||||||
|
int x = 1 ;
|
||||||
|
int& rx = x ;
|
||||||
|
optional<int&> b(rx);
|
||||||
|
a = b ;
|
||||||
|
</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>initiliazed? </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 explicitely 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>
|
<HR>
|
||||||
|
|
||||||
<H2><A NAME="inplace">In-Place Factories</A></H2>
|
<H2><A NAME="inplace">In-Place Factories</A></H2>
|
||||||
@ -1152,7 +1312,7 @@ type to be <a href="../../utility/CopyConstructible.html">Copy Constructible</a>
|
|||||||
constructed object, often temporary, just to follow the copy from:</p>
|
constructed object, often temporary, just to follow the copy from:</p>
|
||||||
<pre>struct X
|
<pre>struct X
|
||||||
{
|
{
|
||||||
X ( int, std::string ) ;
|
X ( int, std:::string ) ;
|
||||||
} ;</pre>
|
} ;</pre>
|
||||||
<pre>class W
|
<pre>class W
|
||||||
{
|
{
|
||||||
@ -1222,7 +1382,7 @@ public:
|
|||||||
{
|
{
|
||||||
// Wrapped object constructed in-place via a TypedInPlaceFactory.
|
// Wrapped object constructed in-place via a TypedInPlaceFactory.
|
||||||
// No temporary created.
|
// No temporary created.
|
||||||
W ( TypedInPlaceFactory2<X,int,std::string>(123,"hello")) ;
|
W ( TypedInPlaceFactory2<X,int,std::string&rt;(123,"hello")) ;
|
||||||
}
|
}
|
||||||
</pre>
|
</pre>
|
||||||
<p>The factories are divided in two groups:<ul>
|
<p>The factories are divided in two groups:<ul>
|
||||||
@ -1303,7 +1463,7 @@ of the assignment methods:</p>
|
|||||||
InPlaceFactory const& ) </code></li>
|
InPlaceFactory const& ) </code></li>
|
||||||
<li> <code>template<class TypedInPlaceFactory> optional<T>::operator= (
|
<li> <code>template<class TypedInPlaceFactory> optional<T>::operator= (
|
||||||
TypedInPlaceFactory const& ) </code></li>
|
TypedInPlaceFactory const& ) </code></li>
|
||||||
<li> <code>optional<T>::reset ( T const& )</code></li>
|
<li> <code>optional<T>:::reset ( T const&)</code></li>
|
||||||
</ul>
|
</ul>
|
||||||
<p>Can only <i>guarantee</i> the <u>basic exception safety</u>: The lvalue optional is left <u>uninitialized</u>
|
<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>
|
if an exception is thrown (any previous value is <i>first</i> destroyed using T::~T())</p>
|
||||||
@ -1320,11 +1480,11 @@ for T::T ( T const& ), you know that optional's assignment and reset has the
|
|||||||
// Case 1: Exception thrown during assignment.
|
// Case 1: Exception thrown during assignment.
|
||||||
//
|
//
|
||||||
T v0(123);
|
T v0(123);
|
||||||
optional<T> opt0(v0);
|
optional<T> opt0(v0);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
T v1(456);
|
T v1(456);
|
||||||
optional<T> opt1(v1);
|
optional<T> opt1(v1);
|
||||||
opt0 = opt1 ;
|
opt0 = opt1 ;
|
||||||
|
|
||||||
// If no exception was thrown, assignment succeeded.
|
// If no exception was thrown, assignment succeeded.
|
||||||
@ -1340,7 +1500,7 @@ catch(...)
|
|||||||
// Case 2: Exception thrown during reset(v)
|
// Case 2: Exception thrown during reset(v)
|
||||||
//
|
//
|
||||||
T v0(123);
|
T v0(123);
|
||||||
optional<T> opt(v0);
|
optional<T> opt(v0);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
T v1(456);
|
T v1(456);
|
||||||
@ -1432,8 +1592,8 @@ T <u>is not</u> required to be <a href="http://www.sgi.com/tech/stl/DefaultConst
|
|||||||
</blockquote>
|
</blockquote>
|
||||||
<HR>
|
<HR>
|
||||||
|
|
||||||
<P>Revised Jannuary 30, 2004</P>
|
<P>Revised April 21, 2005</P>
|
||||||
<p><EFBFBD> Copyright Fernando Luis Cacciola Carballal, 2003,2004</p>
|
<p><EFBFBD> Copyright Fernando Luis Cacciola Carballal, 2003,2004,2005</p>
|
||||||
<p> Use, modification, and distribution are subject to the Boost Software
|
<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, 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">
|
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
|
||||||
@ -1443,4 +1603,4 @@ the latest version of this file can be found at <A
|
|||||||
HREF="http://www.boost.org">www.boost.org</A>, and the boost
|
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>
|
<A HREF="http://www.boost.org/more/mailing_lists.htm#main">discussion lists</A></P>
|
||||||
</BODY>
|
</BODY>
|
||||||
</HTML>
|
</HTML>
|
@ -12,7 +12,7 @@
|
|||||||
#ifndef BOOST_NONE_17SEP2003_HPP
|
#ifndef BOOST_NONE_17SEP2003_HPP
|
||||||
#define BOOST_NONE_17SEP2003_HPP
|
#define BOOST_NONE_17SEP2003_HPP
|
||||||
|
|
||||||
#include "boost/detail/none_t.hpp"
|
#include "boost/none_t.hpp"
|
||||||
|
|
||||||
// NOTE: Borland users have to include this header outside any precompiled headers
|
// NOTE: Borland users have to include this header outside any precompiled headers
|
||||||
// (bcc<=5.64 cannot include instance data in a precompiled header)
|
// (bcc<=5.64 cannot include instance data in a precompiled header)
|
||||||
@ -21,7 +21,7 @@ namespace boost {
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
detail::none_t const none = ((detail::none_t)0) ;
|
none_t const none = ((none_t)0) ;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
24
include/boost/none_t.hpp
Normal file
24
include/boost/none_t.hpp
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
// 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
|
||||||
|
//
|
||||||
|
#ifndef BOOST_NONE_T_17SEP2003_HPP
|
||||||
|
#define BOOST_NONE_T_17SEP2003_HPP
|
||||||
|
|
||||||
|
namespace boost {
|
||||||
|
|
||||||
|
namespace detail { struct none_helper{}; }
|
||||||
|
|
||||||
|
typedef int detail::none_helper::*none_t ;
|
||||||
|
|
||||||
|
} // namespace boost
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -26,7 +26,7 @@
|
|||||||
#include "boost/mpl/bool.hpp"
|
#include "boost/mpl/bool.hpp"
|
||||||
#include "boost/mpl/not.hpp"
|
#include "boost/mpl/not.hpp"
|
||||||
#include "boost/detail/reference_content.hpp"
|
#include "boost/detail/reference_content.hpp"
|
||||||
#include "boost/detail/none_t.hpp"
|
#include "boost/none_t.hpp"
|
||||||
#include "boost/utility/compare_pointees.hpp"
|
#include "boost/utility/compare_pointees.hpp"
|
||||||
|
|
||||||
#if BOOST_WORKAROUND(BOOST_MSVC, == 1200)
|
#if BOOST_WORKAROUND(BOOST_MSVC, == 1200)
|
||||||
@ -167,7 +167,7 @@ class optional_base : public optional_tag
|
|||||||
|
|
||||||
// Creates an optional<T> uninitialized.
|
// Creates an optional<T> uninitialized.
|
||||||
// No-throw
|
// No-throw
|
||||||
optional_base ( detail::none_t const& )
|
optional_base ( none_t const& )
|
||||||
:
|
:
|
||||||
m_initialized(false) {}
|
m_initialized(false) {}
|
||||||
|
|
||||||
@ -208,32 +208,40 @@ class optional_base : public optional_tag
|
|||||||
~optional_base() { destroy() ; }
|
~optional_base() { destroy() ; }
|
||||||
|
|
||||||
// Assigns from another optional<T> (deep-copies the rhs value)
|
// Assigns from another optional<T> (deep-copies the rhs value)
|
||||||
// Basic Guarantee: If T::T( T const& ) throws, this is left UNINITIALIZED
|
|
||||||
void assign ( optional_base const& rhs )
|
void assign ( optional_base const& rhs )
|
||||||
|
{
|
||||||
|
if (is_initialized())
|
||||||
|
{
|
||||||
|
if ( rhs.is_initialized() )
|
||||||
|
assign_value(rhs.get_impl(), is_reference_predicate() );
|
||||||
|
else destroy();
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
destroy();
|
|
||||||
if ( rhs.is_initialized() )
|
if ( rhs.is_initialized() )
|
||||||
construct(rhs.get_impl());
|
construct(rhs.get_impl());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Assigns from a T (deep-copies the rhs value)
|
// Assigns from a T (deep-copies the rhs value)
|
||||||
// Basic Guarantee: If T::( T const& ) throws, this is left UNINITIALIZED
|
|
||||||
void assign ( argument_type val )
|
void assign ( argument_type val )
|
||||||
{
|
{
|
||||||
destroy();
|
if (is_initialized())
|
||||||
construct(val);
|
assign_value(val, is_reference_predicate() );
|
||||||
}
|
else construct(val);
|
||||||
|
}
|
||||||
|
|
||||||
// Assigns from "none", destroying the current value, if any, leaving this UNINITIALIZED
|
// Assigns from "none", destroying the current value, if any, leaving this UNINITIALIZED
|
||||||
// No-throw (assuming T::~T() doesn't)
|
// No-throw (assuming T::~T() doesn't)
|
||||||
void assign ( detail::none_t const& ) { destroy(); }
|
void assign ( none_t const& ) { destroy(); }
|
||||||
|
|
||||||
#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
|
#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
|
||||||
template<class Expr>
|
template<class Expr>
|
||||||
void assign_expr ( Expr const& expr, Expr const* tag )
|
void assign_expr ( Expr const& expr, Expr const* tag )
|
||||||
{
|
{
|
||||||
destroy();
|
if (is_initialized())
|
||||||
construct(expr,tag);
|
assign_expr_to_initialized(expr,tag);
|
||||||
|
else construct(expr,tag);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -244,7 +252,6 @@ class optional_base : public optional_tag
|
|||||||
void reset() { destroy(); }
|
void reset() { destroy(); }
|
||||||
|
|
||||||
// Replaces the current value -if any- with 'val'
|
// Replaces the current value -if any- with 'val'
|
||||||
// Basic Guarantee: If T::T( T const& ) throws this is left UNINITIALIZED.
|
|
||||||
void reset ( argument_type val ) { assign(val); }
|
void reset ( argument_type val ) { assign(val); }
|
||||||
|
|
||||||
// Returns a pointer to the value if this is initialized, otherwise,
|
// Returns a pointer to the value if this is initialized, otherwise,
|
||||||
@ -281,6 +288,21 @@ class optional_base : public optional_tag
|
|||||||
factory.apply(m_storage.address()) ;
|
factory.apply(m_storage.address()) ;
|
||||||
m_initialized = true ;
|
m_initialized = true ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class Expr>
|
||||||
|
void assign_expr_to_initialized ( Expr const& factory, in_place_factory_base const* tag )
|
||||||
|
{
|
||||||
|
destroy();
|
||||||
|
construct(factory,tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constructs in-place using the given typed factory
|
||||||
|
template<class Expr>
|
||||||
|
void assign_expr_to_initialized ( Expr const& factory, typed_in_place_factory_base const* tag )
|
||||||
|
{
|
||||||
|
destroy();
|
||||||
|
construct(factory,tag);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Constructs using any expression implicitely convertible to the single argument
|
// Constructs using any expression implicitely convertible to the single argument
|
||||||
@ -294,6 +316,16 @@ class optional_base : public optional_tag
|
|||||||
m_initialized = true ;
|
m_initialized = true ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Assigns using a form any expression implicitely convertible to the single argument
|
||||||
|
// of a T's assignment operator.
|
||||||
|
// Converting assignments of optional<T> from optional<U> uses this function with
|
||||||
|
// 'Expr' being of type 'U' and relying on a converting assignment of T from U.
|
||||||
|
template<class Expr>
|
||||||
|
void assign_expr_to_initialized ( Expr const& expr, void const* )
|
||||||
|
{
|
||||||
|
assign_value(expr, is_reference_predicate());
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION
|
#ifdef BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION
|
||||||
// BCB5.64 (and probably lower versions) workaround.
|
// BCB5.64 (and probably lower versions) workaround.
|
||||||
// The in-place factories are supported by means of catch-all constructors
|
// The in-place factories are supported by means of catch-all constructors
|
||||||
@ -321,11 +353,14 @@ class optional_base : public optional_tag
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void assign_value ( argument_type val, is_not_reference_tag ) { get_impl() = val; }
|
||||||
|
void assign_value ( argument_type val, is_reference_tag ) { construct(val); }
|
||||||
|
|
||||||
void destroy()
|
void destroy()
|
||||||
{
|
{
|
||||||
if ( m_initialized )
|
if ( m_initialized )
|
||||||
destroy_impl(is_reference_predicate()) ;
|
destroy_impl(is_reference_predicate()) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
unspecified_bool_type safe_bool() const { return m_initialized ? &this_type::is_initialized : 0 ; }
|
unspecified_bool_type safe_bool() const { return m_initialized ? &this_type::is_initialized : 0 ; }
|
||||||
|
|
||||||
@ -391,7 +426,7 @@ class optional : public optional_detail::optional_base<T>
|
|||||||
|
|
||||||
// Creates an optional<T> uninitialized.
|
// Creates an optional<T> uninitialized.
|
||||||
// No-throw
|
// No-throw
|
||||||
optional( detail::none_t const& none_ ) : base(none_) {}
|
optional( none_t const& none_ ) : base(none_) {}
|
||||||
|
|
||||||
// Creates an optional<T> initialized with 'val'.
|
// Creates an optional<T> initialized with 'val'.
|
||||||
// Can throw if T::T(T const&) does
|
// Can throw if T::T(T const&) does
|
||||||
@ -453,14 +488,7 @@ class optional : public optional_detail::optional_base<T>
|
|||||||
template<class U>
|
template<class U>
|
||||||
optional& operator= ( optional<U> const& rhs )
|
optional& operator= ( optional<U> const& rhs )
|
||||||
{
|
{
|
||||||
this->destroy(); // no-throw
|
this->assign(rhs.get());
|
||||||
|
|
||||||
if ( rhs.is_initialized() )
|
|
||||||
{
|
|
||||||
// An exception can be thrown here.
|
|
||||||
// It it happens, THIS will be left uninitialized.
|
|
||||||
this->assign(rhs.get());
|
|
||||||
}
|
|
||||||
return *this ;
|
return *this ;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -485,7 +513,7 @@ class optional : public optional_detail::optional_base<T>
|
|||||||
// Assigns from a "none"
|
// Assigns from a "none"
|
||||||
// Which destroys the current value, if any, leaving this UNINITIALIZED
|
// Which destroys the current value, if any, leaving this UNINITIALIZED
|
||||||
// No-throw (assuming T::~T() doesn't)
|
// No-throw (assuming T::~T() doesn't)
|
||||||
optional& operator= ( detail::none_t const& none_ )
|
optional& operator= ( none_t const& none_ )
|
||||||
{
|
{
|
||||||
this->assign( none_ ) ;
|
this->assign( none_ ) ;
|
||||||
return *this ;
|
return *this ;
|
||||||
@ -607,62 +635,62 @@ bool operator >= ( optional<T> const& x, optional<T> const& y )
|
|||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
inline
|
inline
|
||||||
bool operator == ( optional<T> const& x, detail::none_t const& )
|
bool operator == ( optional<T> const& x, none_t const& )
|
||||||
{ return equal_pointees(x, optional<T>() ); }
|
{ return equal_pointees(x, optional<T>() ); }
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
inline
|
inline
|
||||||
bool operator < ( optional<T> const& x, detail::none_t const& )
|
bool operator < ( optional<T> const& x, none_t const& )
|
||||||
{ return less_pointees(x,optional<T>() ); }
|
{ return less_pointees(x,optional<T>() ); }
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
inline
|
inline
|
||||||
bool operator != ( optional<T> const& x, detail::none_t const& y )
|
bool operator != ( optional<T> const& x, none_t const& y )
|
||||||
{ return !( x == y ) ; }
|
{ return !( x == y ) ; }
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
inline
|
inline
|
||||||
bool operator > ( optional<T> const& x, detail::none_t const& y )
|
bool operator > ( optional<T> const& x, none_t const& y )
|
||||||
{ return y < x ; }
|
{ return y < x ; }
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
inline
|
inline
|
||||||
bool operator <= ( optional<T> const& x, detail::none_t const& y )
|
bool operator <= ( optional<T> const& x, none_t const& y )
|
||||||
{ return !( y < x ) ; }
|
{ return !( y < x ) ; }
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
inline
|
inline
|
||||||
bool operator >= ( optional<T> const& x, detail::none_t const& y )
|
bool operator >= ( optional<T> const& x, none_t const& y )
|
||||||
{ return !( x < y ) ; }
|
{ return !( x < y ) ; }
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
inline
|
inline
|
||||||
bool operator == ( detail::none_t const& x, optional<T> const& y )
|
bool operator == ( none_t const& x, optional<T> const& y )
|
||||||
{ return equal_pointees(optional<T>() ,y); }
|
{ return equal_pointees(optional<T>() ,y); }
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
inline
|
inline
|
||||||
bool operator < ( detail::none_t const& x, optional<T> const& y )
|
bool operator < ( none_t const& x, optional<T> const& y )
|
||||||
{ return less_pointees(optional<T>() ,y); }
|
{ return less_pointees(optional<T>() ,y); }
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
inline
|
inline
|
||||||
bool operator != ( detail::none_t const& x, optional<T> const& y )
|
bool operator != ( none_t const& x, optional<T> const& y )
|
||||||
{ return !( x == y ) ; }
|
{ return !( x == y ) ; }
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
inline
|
inline
|
||||||
bool operator > ( detail::none_t const& x, optional<T> const& y )
|
bool operator > ( none_t const& x, optional<T> const& y )
|
||||||
{ return y < x ; }
|
{ return y < x ; }
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
inline
|
inline
|
||||||
bool operator <= ( detail::none_t const& x, optional<T> const& y )
|
bool operator <= ( none_t const& x, optional<T> const& y )
|
||||||
{ return !( y < x ) ; }
|
{ return !( y < x ) ; }
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
inline
|
inline
|
||||||
bool operator >= ( detail::none_t const& x, optional<T> const& y )
|
bool operator >= ( none_t const& x, optional<T> const& y )
|
||||||
{ return !( x < y ) ; }
|
{ return !( x < y ) ; }
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -679,8 +707,9 @@ namespace optional_detail {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// optional's swap:
|
// optional's swap:
|
||||||
// If both are initialized, calls swap(T&, T&), with whatever exception guarantess are given there.
|
// If both are initialized, calls swap(T&, T&). If this swap throws, both will remain initialized but their values are now unspecified.
|
||||||
// If only one is initialized, calls I.reset() and U.reset(*I), with the Basic Guarantee
|
// If only one is initialized, calls U.reset(*I), THEN I.reset().
|
||||||
|
// If U.reset(*I) throws, both are left UNCHANGED (U is kept uinitialized and I is never reset)
|
||||||
// If both are uninitialized, do nothing (no-throw)
|
// If both are uninitialized, do nothing (no-throw)
|
||||||
template<class T>
|
template<class T>
|
||||||
inline
|
inline
|
||||||
@ -688,12 +717,12 @@ void optional_swap ( optional<T>& x, optional<T>& y )
|
|||||||
{
|
{
|
||||||
if ( !x && !!y )
|
if ( !x && !!y )
|
||||||
{
|
{
|
||||||
x.reset(*y); // Basic guarantee.
|
x.reset(*y);
|
||||||
y.reset();
|
y.reset();
|
||||||
}
|
}
|
||||||
else if ( !!x && !y )
|
else if ( !!x && !y )
|
||||||
{
|
{
|
||||||
y.reset(*x); // Basic guarantee.
|
y.reset(*x);
|
||||||
x.reset();
|
x.reset();
|
||||||
}
|
}
|
||||||
else if ( !!x && !!y )
|
else if ( !!x && !!y )
|
||||||
|
@ -70,7 +70,7 @@ void test_basics( T const* )
|
|||||||
// Implicit construction
|
// Implicit construction
|
||||||
// The first parameter is implicitely converted to optional<T>(a);
|
// The first parameter is implicitely converted to optional<T>(a);
|
||||||
test_implicit_construction(a,a,z);
|
test_implicit_construction(a,a,z);
|
||||||
|
|
||||||
// Direct initialization.
|
// Direct initialization.
|
||||||
// 'oa' state is Initialized with 'a'
|
// 'oa' state is Initialized with 'a'
|
||||||
// T::T( T const& x ) is used.
|
// T::T( T const& x ) is used.
|
||||||
@ -85,7 +85,7 @@ void test_basics( T const* )
|
|||||||
optional<T> ob ;
|
optional<T> ob ;
|
||||||
|
|
||||||
// Value-Assignment upon Uninitialized optional.
|
// Value-Assignment upon Uninitialized optional.
|
||||||
// T::T ( T const& x ) is used.
|
// T::T( T const& x ) is used.
|
||||||
set_pending_copy( ARG(T) ) ;
|
set_pending_copy( ARG(T) ) ;
|
||||||
ob = a ;
|
ob = a ;
|
||||||
check_is_not_pending_copy( ARG(T) ) ;
|
check_is_not_pending_copy( ARG(T) ) ;
|
||||||
@ -93,12 +93,14 @@ void test_basics( T const* )
|
|||||||
check_value(ob,a,z);
|
check_value(ob,a,z);
|
||||||
|
|
||||||
// Value-Assignment upon Initialized optional.
|
// Value-Assignment upon Initialized optional.
|
||||||
// T::T ( T const& x ) is used
|
// T::operator=( T const& x ) is used
|
||||||
set_pending_dtor( ARG(T) ) ;
|
set_pending_assign( ARG(T) ) ;
|
||||||
set_pending_copy( ARG(T) ) ;
|
set_pending_copy ( ARG(T) ) ;
|
||||||
|
set_pending_dtor ( ARG(T) ) ;
|
||||||
ob = b ;
|
ob = b ;
|
||||||
check_is_not_pending_dtor( ARG(T) ) ;
|
check_is_not_pending_assign( ARG(T) ) ;
|
||||||
check_is_not_pending_copy( ARG(T) ) ;
|
check_is_pending_copy ( ARG(T) ) ;
|
||||||
|
check_is_pending_dtor ( ARG(T) ) ;
|
||||||
check_initialized(ob);
|
check_initialized(ob);
|
||||||
check_value(ob,b,z);
|
check_value(ob,b,z);
|
||||||
|
|
||||||
@ -111,13 +113,14 @@ void test_basics( T const* )
|
|||||||
check_value_const(oa2,a,z);
|
check_value_const(oa2,a,z);
|
||||||
|
|
||||||
// Assignment
|
// Assignment
|
||||||
// T::~T() is used to destroy previous value in ob.
|
// T::operator= ( T const& x ) is used to copy new value.
|
||||||
// T::T ( T const& x ) is used to copy new value.
|
set_pending_assign( ARG(T) ) ;
|
||||||
set_pending_dtor( ARG(T) ) ;
|
set_pending_copy ( ARG(T) ) ;
|
||||||
set_pending_copy( ARG(T) ) ;
|
set_pending_dtor ( ARG(T) ) ;
|
||||||
oa = ob ;
|
oa = ob ;
|
||||||
check_is_not_pending_dtor( ARG(T) ) ;
|
check_is_not_pending_assign( ARG(T) ) ;
|
||||||
check_is_not_pending_copy( ARG(T) ) ;
|
check_is_pending_copy ( ARG(T) ) ;
|
||||||
|
check_is_pending_dtor ( ARG(T) ) ;
|
||||||
check_initialized(oa);
|
check_initialized(oa);
|
||||||
check_value(oa,b,z);
|
check_value(oa,b,z);
|
||||||
|
|
||||||
@ -161,7 +164,7 @@ template<class T>
|
|||||||
void test_direct_value_manip( T const* )
|
void test_direct_value_manip( T const* )
|
||||||
{
|
{
|
||||||
TRACE( std::endl << BOOST_CURRENT_FUNCTION );
|
TRACE( std::endl << BOOST_CURRENT_FUNCTION );
|
||||||
|
|
||||||
T x(3);
|
T x(3);
|
||||||
|
|
||||||
optional<T> const c_opt0(x) ;
|
optional<T> const c_opt0(x) ;
|
||||||
@ -169,7 +172,7 @@ void test_direct_value_manip( T const* )
|
|||||||
|
|
||||||
BOOST_CHECK( c_opt0.get().V() == x.V() ) ;
|
BOOST_CHECK( c_opt0.get().V() == x.V() ) ;
|
||||||
BOOST_CHECK( opt0.get().V() == x.V() ) ;
|
BOOST_CHECK( opt0.get().V() == x.V() ) ;
|
||||||
|
|
||||||
BOOST_CHECK( c_opt0->V() == x.V() ) ;
|
BOOST_CHECK( c_opt0->V() == x.V() ) ;
|
||||||
BOOST_CHECK( opt0->V() == x.V() ) ;
|
BOOST_CHECK( opt0->V() == x.V() ) ;
|
||||||
|
|
||||||
@ -212,7 +215,7 @@ void test_uninitialized_access( T const* )
|
|||||||
}
|
}
|
||||||
catch (...) {}
|
catch (...) {}
|
||||||
BOOST_CHECK(!passed);
|
BOOST_CHECK(!passed);
|
||||||
|
|
||||||
passed = false ;
|
passed = false ;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -282,6 +285,9 @@ void test_throwing_direct_init( T const* )
|
|||||||
BOOST_CHECK(!passed);
|
BOOST_CHECK(!passed);
|
||||||
check_is_not_pending_copy( ARG(T) );
|
check_is_not_pending_copy( ARG(T) );
|
||||||
check_instance_count(count, ARG(T) );
|
check_instance_count(count, ARG(T) );
|
||||||
|
|
||||||
|
reset_throw_on_copy( ARG(T) ) ;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -317,6 +323,8 @@ void test_throwing_val_assign_on_uninitialized( T const* )
|
|||||||
check_is_not_pending_copy( ARG(T) );
|
check_is_not_pending_copy( ARG(T) );
|
||||||
check_instance_count(count, ARG(T) );
|
check_instance_count(count, ARG(T) );
|
||||||
check_uninitialized(opt);
|
check_uninitialized(opt);
|
||||||
|
|
||||||
|
reset_throw_on_copy( ARG(T) ) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -330,11 +338,10 @@ void test_throwing_val_assign_on_initialized( T const* )
|
|||||||
T z(0);
|
T z(0);
|
||||||
T a(8);
|
T a(8);
|
||||||
T b(9);
|
T b(9);
|
||||||
|
T x(-1);
|
||||||
|
|
||||||
int count = get_instance_count( ARG(T) ) ;
|
int count = get_instance_count( ARG(T) ) ;
|
||||||
|
|
||||||
reset_throw_on_copy( ARG(T) ) ;
|
|
||||||
|
|
||||||
optional<T> opt ( b ) ;
|
optional<T> opt ( b ) ;
|
||||||
++ count ;
|
++ count ;
|
||||||
|
|
||||||
@ -342,16 +349,16 @@ void test_throwing_val_assign_on_initialized( T const* )
|
|||||||
|
|
||||||
check_value(opt,b,z);
|
check_value(opt,b,z);
|
||||||
|
|
||||||
set_throw_on_copy( ARG(T) ) ;
|
set_throw_on_assign( ARG(T) ) ;
|
||||||
|
|
||||||
bool passed = false ;
|
bool passed = false ;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// This should:
|
// This should:
|
||||||
// Attempt to copy construct 'a' and throw.
|
// Attempt to assign 'a' and throw.
|
||||||
// opt should be left uninitialized (even though it was initialized)
|
// opt is kept initialized but its value not neccesarily fully assigned
|
||||||
set_pending_dtor( ARG(T) ) ;
|
// (in this test, incompletely assigned is flaged with the value -1 being set)
|
||||||
set_pending_copy( ARG(T) ) ;
|
set_pending_assign( ARG(T) ) ;
|
||||||
opt.reset ( a ) ;
|
opt.reset ( a ) ;
|
||||||
passed = true ;
|
passed = true ;
|
||||||
}
|
}
|
||||||
@ -359,12 +366,12 @@ void test_throwing_val_assign_on_initialized( T const* )
|
|||||||
|
|
||||||
BOOST_CHECK(!passed);
|
BOOST_CHECK(!passed);
|
||||||
|
|
||||||
-- count ;
|
check_is_not_pending_assign( ARG(T) );
|
||||||
|
|
||||||
check_is_not_pending_dtor( ARG(T) );
|
|
||||||
check_is_not_pending_copy( ARG(T) );
|
|
||||||
check_instance_count(count, ARG(T) );
|
check_instance_count(count, ARG(T) );
|
||||||
check_uninitialized(opt);
|
check_initialized(opt);
|
||||||
|
check_value(opt,x,z);
|
||||||
|
|
||||||
|
reset_throw_on_assign ( ARG(T) ) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -378,8 +385,6 @@ void test_throwing_copy_initialization( T const* )
|
|||||||
T z(0);
|
T z(0);
|
||||||
T a(10);
|
T a(10);
|
||||||
|
|
||||||
reset_throw_on_copy( ARG(T) ) ;
|
|
||||||
|
|
||||||
optional<T> opt (a);
|
optional<T> opt (a);
|
||||||
|
|
||||||
int count = get_instance_count( ARG(T) ) ;
|
int count = get_instance_count( ARG(T) ) ;
|
||||||
@ -406,6 +411,8 @@ void test_throwing_copy_initialization( T const* )
|
|||||||
// Nothing should have happened to the source optional.
|
// Nothing should have happened to the source optional.
|
||||||
check_initialized(opt);
|
check_initialized(opt);
|
||||||
check_value(opt,a,z);
|
check_value(opt,a,z);
|
||||||
|
|
||||||
|
reset_throw_on_copy( ARG(T) ) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -420,8 +427,6 @@ void test_throwing_assign_to_uninitialized( T const* )
|
|||||||
T z(0);
|
T z(0);
|
||||||
T a(11);
|
T a(11);
|
||||||
|
|
||||||
reset_throw_on_copy( ARG(T) ) ;
|
|
||||||
|
|
||||||
optional<T> opt0 ;
|
optional<T> opt0 ;
|
||||||
optional<T> opt1(a) ;
|
optional<T> opt1(a) ;
|
||||||
|
|
||||||
@ -446,6 +451,8 @@ void test_throwing_assign_to_uninitialized( T const* )
|
|||||||
check_is_not_pending_copy( ARG(T) );
|
check_is_not_pending_copy( ARG(T) );
|
||||||
check_instance_count(count, ARG(T) );
|
check_instance_count(count, ARG(T) );
|
||||||
check_uninitialized(opt0);
|
check_uninitialized(opt0);
|
||||||
|
|
||||||
|
reset_throw_on_copy( ARG(T) ) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -460,24 +467,23 @@ void test_throwing_assign_to_initialized( T const* )
|
|||||||
T z(0);
|
T z(0);
|
||||||
T a(12);
|
T a(12);
|
||||||
T b(13);
|
T b(13);
|
||||||
|
T x(-1);
|
||||||
reset_throw_on_copy( ARG(T) ) ;
|
|
||||||
|
|
||||||
optional<T> opt0(a) ;
|
optional<T> opt0(a) ;
|
||||||
optional<T> opt1(b) ;
|
optional<T> opt1(b) ;
|
||||||
|
|
||||||
int count = get_instance_count( ARG(T) ) ;
|
int count = get_instance_count( ARG(T) ) ;
|
||||||
|
|
||||||
set_throw_on_copy( ARG(T) ) ;
|
set_throw_on_assign( ARG(T) ) ;
|
||||||
|
|
||||||
bool passed = false ;
|
bool passed = false ;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// This should:
|
// This should:
|
||||||
// Attempt to copy construct 'opt1.value()' into opt0 and throw.
|
// Attempt to copy construct 'opt1.value()' into opt0 and throw.
|
||||||
// opt0 should be left unmodified or uninitialized
|
// opt0 is kept initialized but its value not neccesarily fully assigned
|
||||||
set_pending_dtor( ARG(T) ) ;
|
// (in this test, incompletely assigned is flaged with the value -1 being set)
|
||||||
set_pending_copy( ARG(T) ) ;
|
set_pending_assign( ARG(T) ) ;
|
||||||
opt0 = opt1 ;
|
opt0 = opt1 ;
|
||||||
passed = true ;
|
passed = true ;
|
||||||
}
|
}
|
||||||
@ -486,11 +492,12 @@ void test_throwing_assign_to_initialized( T const* )
|
|||||||
BOOST_CHECK(!passed);
|
BOOST_CHECK(!passed);
|
||||||
|
|
||||||
// opt0 was left uninitialized
|
// opt0 was left uninitialized
|
||||||
-- count ;
|
check_is_not_pending_assign( ARG(T) );
|
||||||
check_is_not_pending_dtor( ARG(T) );
|
|
||||||
check_is_not_pending_copy( ARG(T) );
|
|
||||||
check_instance_count(count, ARG(T) );
|
check_instance_count(count, ARG(T) );
|
||||||
check_uninitialized(opt0);
|
check_initialized(opt0);
|
||||||
|
check_value(opt0,x,z);
|
||||||
|
|
||||||
|
reset_throw_on_assign( ARG(T) ) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -500,13 +507,11 @@ template<class T>
|
|||||||
void test_no_throwing_swap( T const* )
|
void test_no_throwing_swap( T const* )
|
||||||
{
|
{
|
||||||
TRACE( std::endl << BOOST_CURRENT_FUNCTION );
|
TRACE( std::endl << BOOST_CURRENT_FUNCTION );
|
||||||
|
|
||||||
T z(0);
|
T z(0);
|
||||||
T a(14);
|
T a(14);
|
||||||
T b(15);
|
T b(15);
|
||||||
|
|
||||||
reset_throw_on_copy( ARG(T) ) ;
|
|
||||||
|
|
||||||
optional<T> def0 ;
|
optional<T> def0 ;
|
||||||
optional<T> def1 ;
|
optional<T> def1 ;
|
||||||
optional<T> opt0(a) ;
|
optional<T> opt0(a) ;
|
||||||
@ -541,16 +546,15 @@ template<class T>
|
|||||||
void test_throwing_swap( T const* )
|
void test_throwing_swap( T const* )
|
||||||
{
|
{
|
||||||
TRACE( std::endl << BOOST_CURRENT_FUNCTION );
|
TRACE( std::endl << BOOST_CURRENT_FUNCTION );
|
||||||
|
|
||||||
T a(16);
|
T a(16);
|
||||||
T b(17);
|
T b(17);
|
||||||
|
T x(-1);
|
||||||
reset_throw_on_copy( ARG(T) ) ;
|
|
||||||
|
|
||||||
optional<T> opt0(a) ;
|
optional<T> opt0(a) ;
|
||||||
optional<T> opt1(b) ;
|
optional<T> opt1(b) ;
|
||||||
|
|
||||||
set_throw_on_copy( ARG(T) ) ;
|
set_throw_on_assign( ARG(T) ) ;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Case 1: Both Initialized.
|
// Case 1: Both Initialized.
|
||||||
@ -567,14 +571,18 @@ void test_throwing_swap( T const* )
|
|||||||
|
|
||||||
BOOST_CHECK(!passed);
|
BOOST_CHECK(!passed);
|
||||||
|
|
||||||
// Assuming swap(T&,T&) has at least the basic guarantee, these should hold.
|
// optional's swap doesn't affect the initialized states of the arguments. Therefore,
|
||||||
BOOST_CHECK( ( !opt0 || ( !!opt0 && ( ( *opt0 == a ) || ( *opt0 == b ) ) ) ) ) ;
|
// the following must hold:
|
||||||
BOOST_CHECK( ( !opt1 || ( !!opt1 && ( ( *opt1 == a ) || ( *opt1 == b ) ) ) ) ) ;
|
check_initialized(opt0);
|
||||||
|
check_initialized(opt1);
|
||||||
|
check_value(opt0,x,a);
|
||||||
|
check_value(opt1,b,x);
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Case 2: Only one Initialized.
|
// Case 2: Only one Initialized.
|
||||||
//
|
//
|
||||||
reset_throw_on_copy( ARG(T) ) ;
|
reset_throw_on_assign( ARG(T) ) ;
|
||||||
|
|
||||||
opt0.reset();
|
opt0.reset();
|
||||||
opt1.reset(a);
|
opt1.reset(a);
|
||||||
@ -585,7 +593,7 @@ void test_throwing_swap( T const* )
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
// This should attempt to swap optionals and fail at opt0.reset(*opt1)
|
// This should attempt to swap optionals and fail at opt0.reset(*opt1)
|
||||||
// opt0 should be left uninitialized and opt1 unchanged.
|
// Both opt0 and op1 are left unchanged (unswaped)
|
||||||
swap(opt0,opt1);
|
swap(opt0,opt1);
|
||||||
|
|
||||||
passed = true ;
|
passed = true ;
|
||||||
@ -596,7 +604,9 @@ void test_throwing_swap( T const* )
|
|||||||
|
|
||||||
check_uninitialized(opt0);
|
check_uninitialized(opt0);
|
||||||
check_initialized(opt1);
|
check_initialized(opt1);
|
||||||
check_value(opt1,a,b);
|
check_value(opt1,a,x);
|
||||||
|
|
||||||
|
reset_throw_on_copy( ARG(T) ) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -606,9 +616,7 @@ template<class T>
|
|||||||
void test_relops( T const* )
|
void test_relops( T const* )
|
||||||
{
|
{
|
||||||
TRACE( std::endl << BOOST_CURRENT_FUNCTION );
|
TRACE( std::endl << BOOST_CURRENT_FUNCTION );
|
||||||
|
|
||||||
reset_throw_on_copy( ARG(T) ) ;
|
|
||||||
|
|
||||||
T v0(18);
|
T v0(18);
|
||||||
T v1(19);
|
T v1(19);
|
||||||
T v2(19);
|
T v2(19);
|
||||||
@ -627,11 +635,11 @@ void test_relops( T const* )
|
|||||||
|
|
||||||
// Check when both are uininitalized.
|
// Check when both are uininitalized.
|
||||||
BOOST_CHECK ( def0 == def1 ) ; // both uninitialized compare equal
|
BOOST_CHECK ( def0 == def1 ) ; // both uninitialized compare equal
|
||||||
BOOST_CHECK ( !(def0 < def1) ) ; // uninitialized is never less than uninitialized
|
BOOST_CHECK ( !(def0 < def1) ) ; // uninitialized is never less than uninitialized
|
||||||
BOOST_CHECK ( !(def0 > def1) ) ; // uninitialized is never greater than uninitialized
|
BOOST_CHECK ( !(def0 > def1) ) ; // uninitialized is never greater than uninitialized
|
||||||
BOOST_CHECK ( !(def0 != def1) ) ;
|
BOOST_CHECK ( !(def0 != def1) ) ;
|
||||||
BOOST_CHECK ( def0 <= def1 ) ;
|
BOOST_CHECK ( def0 <= def1 ) ;
|
||||||
BOOST_CHECK ( def0 >= def1 ) ;
|
BOOST_CHECK ( def0 >= def1 ) ;
|
||||||
|
|
||||||
// Check when only lhs is uninitialized.
|
// Check when only lhs is uninitialized.
|
||||||
BOOST_CHECK ( def0 != opt0 ) ; // uninitialized is never equal to initialized
|
BOOST_CHECK ( def0 != opt0 ) ; // uninitialized is never equal to initialized
|
||||||
@ -664,7 +672,7 @@ void test_none( T const* )
|
|||||||
TRACE( std::endl << BOOST_CURRENT_FUNCTION );
|
TRACE( std::endl << BOOST_CURRENT_FUNCTION );
|
||||||
|
|
||||||
using boost::none ;
|
using boost::none ;
|
||||||
|
|
||||||
optional<T> def0 ;
|
optional<T> def0 ;
|
||||||
optional<T> def1(none) ;
|
optional<T> def1(none) ;
|
||||||
optional<T> non_def( T(1234) ) ;
|
optional<T> non_def( T(1234) ) ;
|
||||||
@ -682,7 +690,7 @@ void test_none( T const* )
|
|||||||
void test_with_builtin_types()
|
void test_with_builtin_types()
|
||||||
{
|
{
|
||||||
TRACE( std::endl << BOOST_CURRENT_FUNCTION );
|
TRACE( std::endl << BOOST_CURRENT_FUNCTION );
|
||||||
|
|
||||||
test_basics( ARG(double) );
|
test_basics( ARG(double) );
|
||||||
test_uninitialized_access( ARG(double) );
|
test_uninitialized_access( ARG(double) );
|
||||||
test_no_throwing_swap( ARG(double) );
|
test_no_throwing_swap( ARG(double) );
|
||||||
@ -763,7 +771,7 @@ void test_conversions1()
|
|||||||
optional<double> opt3 ;
|
optional<double> opt3 ;
|
||||||
opt3 = opt2 ;
|
opt3 = opt2 ;
|
||||||
BOOST_CHECK(*opt3 == d);
|
BOOST_CHECK(*opt3 == d);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_conversions2()
|
void test_conversions2()
|
||||||
|
@ -93,10 +93,22 @@ class X
|
|||||||
|
|
||||||
X& operator= ( X const& rhs )
|
X& operator= ( X const& rhs )
|
||||||
{
|
{
|
||||||
v = rhs.v ;
|
pending_assign = false ;
|
||||||
|
|
||||||
TRACE ( "X::operator =( X const& rhs). this=" << this << " rhs.v=" << rhs.v ) ;
|
if ( throw_on_assign )
|
||||||
|
{
|
||||||
|
TRACE ( "throwing exception in X's assignment" ) ;
|
||||||
|
|
||||||
|
v = -1 ;
|
||||||
|
|
||||||
|
throw 0 ;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
v = rhs.v ;
|
||||||
|
|
||||||
|
TRACE ( "X::operator =( X const& rhs). this=" << this << " rhs.v=" << rhs.v ) ;
|
||||||
|
}
|
||||||
return *this ;
|
return *this ;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,7 +127,9 @@ class X
|
|||||||
static int count ;
|
static int count ;
|
||||||
static bool pending_copy ;
|
static bool pending_copy ;
|
||||||
static bool pending_dtor ;
|
static bool pending_dtor ;
|
||||||
|
static bool pending_assign ;
|
||||||
static bool throw_on_copy ;
|
static bool throw_on_copy ;
|
||||||
|
static bool throw_on_assign ;
|
||||||
|
|
||||||
private :
|
private :
|
||||||
|
|
||||||
@ -127,32 +141,44 @@ class X
|
|||||||
} ;
|
} ;
|
||||||
|
|
||||||
|
|
||||||
int X::count = 0 ;
|
int X::count = 0 ;
|
||||||
bool X::pending_copy = false ;
|
bool X::pending_copy = false ;
|
||||||
bool X::pending_dtor = false ;
|
bool X::pending_dtor = false ;
|
||||||
bool X::throw_on_copy = false ;
|
bool X::pending_assign = false ;
|
||||||
|
bool X::throw_on_copy = false ;
|
||||||
|
bool X::throw_on_assign = false ;
|
||||||
|
|
||||||
inline void set_pending_copy ( X const* x ) { X::pending_copy = true ; }
|
inline void set_pending_copy ( X const* x ) { X::pending_copy = true ; }
|
||||||
inline void set_pending_dtor ( X const* x ) { X::pending_dtor = true ; }
|
inline void set_pending_dtor ( X const* x ) { X::pending_dtor = true ; }
|
||||||
inline void set_throw_on_copy ( X const* x ) { X::throw_on_copy = true ; }
|
inline void set_pending_assign ( X const* x ) { X::pending_assign = true ; }
|
||||||
inline void reset_throw_on_copy ( X const* x ) { X::throw_on_copy = false ; }
|
inline void set_throw_on_copy ( X const* x ) { X::throw_on_copy = true ; }
|
||||||
inline void check_is_pending_copy ( X const* x ) { BOOST_CHECK( X::pending_copy ) ; }
|
inline void set_throw_on_assign ( X const* x ) { X::throw_on_assign = true ; }
|
||||||
inline void check_is_pending_dtor ( X const* x ) { BOOST_CHECK( X::pending_dtor ) ; }
|
inline void reset_throw_on_copy ( X const* x ) { X::throw_on_copy = false ; }
|
||||||
inline void check_is_not_pending_copy( X const* x ) { BOOST_CHECK( !X::pending_copy ) ; }
|
inline void reset_throw_on_assign ( X const* x ) { X::throw_on_assign = false ; }
|
||||||
inline void check_is_not_pending_dtor( X const* x ) { BOOST_CHECK( !X::pending_dtor ) ; }
|
inline void check_is_pending_copy ( X const* x ) { BOOST_CHECK( X::pending_copy ) ; }
|
||||||
inline void check_instance_count ( int c, X const* x ) { BOOST_CHECK( X::count == c ) ; }
|
inline void check_is_pending_dtor ( X const* x ) { BOOST_CHECK( X::pending_dtor ) ; }
|
||||||
inline int get_instance_count ( X const* x ) { return X::count ; }
|
inline void check_is_pending_assign ( X const* x ) { BOOST_CHECK( X::pending_assign ) ; }
|
||||||
|
inline void check_is_not_pending_copy ( X const* x ) { BOOST_CHECK( !X::pending_copy ) ; }
|
||||||
|
inline void check_is_not_pending_dtor ( X const* x ) { BOOST_CHECK( !X::pending_dtor ) ; }
|
||||||
|
inline void check_is_not_pending_assign( X const* x ) { BOOST_CHECK( !X::pending_assign ) ; }
|
||||||
|
inline void check_instance_count ( int c, X const* x ) { BOOST_CHECK( X::count == c ) ; }
|
||||||
|
inline int get_instance_count ( X const* x ) { return X::count ; }
|
||||||
|
|
||||||
inline void set_pending_copy (...) {}
|
inline void set_pending_copy (...) {}
|
||||||
inline void set_pending_dtor (...) {}
|
inline void set_pending_dtor (...) {}
|
||||||
inline void set_throw_on_copy (...) {}
|
inline void set_pending_assign (...) {}
|
||||||
inline void reset_throw_on_copy (...) {}
|
inline void set_throw_on_copy (...) {}
|
||||||
inline void check_is_pending_copy (...) {}
|
inline void set_throw_on_assign (...) {}
|
||||||
inline void check_is_pending_dtor (...) {}
|
inline void reset_throw_on_copy (...) {}
|
||||||
inline void check_is_not_pending_copy(...) {}
|
inline void reset_throw_on_assign (...) {}
|
||||||
inline void check_is_not_pending_dtor(...) {}
|
inline void check_is_pending_copy (...) {}
|
||||||
inline void check_instance_count (...) {}
|
inline void check_is_pending_dtor (...) {}
|
||||||
inline int get_instance_count (...) { return 0 ; }
|
inline void check_is_pending_assign (...) {}
|
||||||
|
inline void check_is_not_pending_copy (...) {}
|
||||||
|
inline void check_is_not_pending_dtor (...) {}
|
||||||
|
inline void check_is_not_pending_assign(...) {}
|
||||||
|
inline void check_instance_count (...) {}
|
||||||
|
inline int get_instance_count (...) { return 0 ; }
|
||||||
|
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
@ -160,7 +186,7 @@ inline void check_uninitialized_const ( optional<T> const& opt )
|
|||||||
{
|
{
|
||||||
#ifndef BOOST_OPTIONAL_NO_NULL_COMPARE
|
#ifndef BOOST_OPTIONAL_NO_NULL_COMPARE
|
||||||
BOOST_CHECK( opt == 0 ) ;
|
BOOST_CHECK( opt == 0 ) ;
|
||||||
#endif
|
#endif
|
||||||
BOOST_CHECK( !opt ) ;
|
BOOST_CHECK( !opt ) ;
|
||||||
BOOST_CHECK( !get_pointer(opt) ) ;
|
BOOST_CHECK( !get_pointer(opt) ) ;
|
||||||
BOOST_CHECK( !opt.get_ptr() ) ;
|
BOOST_CHECK( !opt.get_ptr() ) ;
|
||||||
|
@ -32,7 +32,7 @@ inline void check_ref_uninitialized_const ( optional<T&> const& opt )
|
|||||||
{
|
{
|
||||||
#ifndef BOOST_OPTIONAL_NO_NULL_COMPARE
|
#ifndef BOOST_OPTIONAL_NO_NULL_COMPARE
|
||||||
BOOST_CHECK( opt == 0 ) ;
|
BOOST_CHECK( opt == 0 ) ;
|
||||||
#endif
|
#endif
|
||||||
BOOST_CHECK( !opt ) ;
|
BOOST_CHECK( !opt ) ;
|
||||||
}
|
}
|
||||||
template<class T>
|
template<class T>
|
||||||
@ -104,9 +104,16 @@ void test_basics( T const* )
|
|||||||
|
|
||||||
T z(0);
|
T z(0);
|
||||||
|
|
||||||
|
T original_a(1);
|
||||||
|
|
||||||
T a(1);
|
T a(1);
|
||||||
|
|
||||||
|
T b(2);
|
||||||
|
|
||||||
|
T c(10);
|
||||||
|
|
||||||
T& aref = a ;
|
T& aref = a ;
|
||||||
|
T& bref = b ;
|
||||||
|
|
||||||
// Default construction.
|
// Default construction.
|
||||||
// 'def' state is Uninitialized.
|
// 'def' state is Uninitialized.
|
||||||
@ -115,13 +122,16 @@ void test_basics( T const* )
|
|||||||
check_ref_uninitialized(def);
|
check_ref_uninitialized(def);
|
||||||
|
|
||||||
// Direct initialization.
|
// Direct initialization.
|
||||||
// 'oa' state is Initialized with 'a'
|
// 'oa' state is Initialized and binds to 'a'
|
||||||
// T::T( T const& x ) is NOT used becasue the optional holds a reference.
|
// T::T( T const& x ) is NOT used becasue the optional holds a reference.
|
||||||
set_pending_copy( ARG(T) ) ;
|
set_pending_copy( ARG(T) ) ;
|
||||||
optional<T&> oa ( aref ) ;
|
optional<T&> oa ( aref ) ;
|
||||||
check_is_pending_copy( ARG(T) );
|
check_is_pending_copy( ARG(T) );
|
||||||
check_ref_initialized(oa);
|
check_ref_initialized(oa);
|
||||||
check_ref_value(oa,a,z);
|
check_ref_value(oa,a,z);
|
||||||
|
*oa = b ; // changes the value of 'a' through the reference
|
||||||
|
BOOST_CHECK( a == b ) ;
|
||||||
|
|
||||||
|
|
||||||
// Copy initialization.
|
// Copy initialization.
|
||||||
// T::T ( T const& x ) is NOT used becasue the optional holds a reference.
|
// T::T ( T const& x ) is NOT used becasue the optional holds a reference.
|
||||||
@ -130,27 +140,32 @@ void test_basics( T const* )
|
|||||||
check_is_pending_copy( ARG(T) ) ;
|
check_is_pending_copy( ARG(T) ) ;
|
||||||
check_ref_initialized_const(oa2);
|
check_ref_initialized_const(oa2);
|
||||||
check_ref_value_const(oa2,a,z);
|
check_ref_value_const(oa2,a,z);
|
||||||
|
*oa2 = original_a ; // restores the value of 'a' through the reference
|
||||||
|
BOOST_CHECK( a == original_a ) ;
|
||||||
|
|
||||||
T b(2);
|
|
||||||
optional<T&> ob ;
|
optional<T&> ob ;
|
||||||
|
|
||||||
// Value-Assignment upon Uninitialized optional.
|
// Value-Assignment upon Uninitialized optional.
|
||||||
// T::T ( T const& x ) is NOT used becasue the optional holds a reference.
|
// T::T ( T const& x ) is NOT used becasue the optional holds a reference.
|
||||||
set_pending_copy( ARG(T) ) ;
|
set_pending_copy( ARG(T) ) ;
|
||||||
ob = a ;
|
ob = a ; // Binds ob to a temporary non-const refererence to 'a'
|
||||||
check_is_pending_copy( ARG(T) ) ;
|
check_is_pending_copy( ARG(T) ) ;
|
||||||
check_ref_initialized(ob);
|
check_ref_initialized(ob);
|
||||||
check_ref_value(ob,a,z);
|
check_ref_value(ob,a,z);
|
||||||
|
a = c;
|
||||||
|
check_ref_value(ob,a,z);
|
||||||
|
|
||||||
// Value-Assignment upon Initialized optional.
|
// Value-Assignment upon Initialized optional.
|
||||||
// T::T ( T const& x ) is NOT used becasue the optional holds a reference.
|
// T::operator= ( T const& x ) is used.
|
||||||
set_pending_dtor( ARG(T) ) ;
|
set_pending_assign( ARG(T) ) ;
|
||||||
set_pending_copy( ARG(T) ) ;
|
ob = b ; // Rebinds 'ob' to 'b' (without changing 'a')
|
||||||
ob = b ;
|
check_is_pending_assign( ARG(T) ) ;
|
||||||
check_is_pending_dtor( ARG(T) ) ;
|
|
||||||
check_is_pending_copy( ARG(T) ) ;
|
|
||||||
check_ref_initialized(ob);
|
check_ref_initialized(ob);
|
||||||
check_ref_value(ob,b,z);
|
check_ref_value(ob,b,z);
|
||||||
|
BOOST_CHECK(a == c); // From a=c in previous test
|
||||||
|
b = c;
|
||||||
|
check_ref_value(ob,b,z);
|
||||||
|
|
||||||
|
|
||||||
// Assignment initialization.
|
// Assignment initialization.
|
||||||
// T::T ( T const& x ) is NOT used becasue the optional holds a reference.
|
// T::T ( T const& x ) is NOT used becasue the optional holds a reference.
|
||||||
@ -162,14 +177,12 @@ void test_basics( T const* )
|
|||||||
|
|
||||||
|
|
||||||
// Assignment
|
// Assignment
|
||||||
// T::~T() is used to destroy previous value in ob.
|
// T::operator=( T const& x ) is used.
|
||||||
// T::T ( T const& x ) is NOT used becasue the optional holds a reference.
|
set_pending_assign( ARG(T) ) ;
|
||||||
set_pending_dtor( ARG(T) ) ;
|
oa = ob ; // Rebinds 'a' to 'b'
|
||||||
set_pending_copy( ARG(T) ) ;
|
check_is_pending_assign( ARG(T) ) ;
|
||||||
oa = ob ;
|
|
||||||
check_is_pending_dtor( ARG(T) ) ;
|
|
||||||
check_is_pending_copy( ARG(T) ) ;
|
|
||||||
check_ref_initialized(oa);
|
check_ref_initialized(oa);
|
||||||
|
a = original_a ;
|
||||||
check_ref_value(oa,b,z);
|
check_ref_value(oa,b,z);
|
||||||
|
|
||||||
// Uninitializing Assignment upon Initialized Optional
|
// Uninitializing Assignment upon Initialized Optional
|
||||||
@ -190,6 +203,7 @@ void test_basics( T const* )
|
|||||||
check_is_pending_copy( ARG(T) ) ;
|
check_is_pending_copy( ARG(T) ) ;
|
||||||
check_ref_uninitialized(oa);
|
check_ref_uninitialized(oa);
|
||||||
|
|
||||||
|
|
||||||
// Deinitialization of Initialized Optional
|
// Deinitialization of Initialized Optional
|
||||||
// T::~T() is NOT used becasue the optional holds a reference.
|
// T::~T() is NOT used becasue the optional holds a reference.
|
||||||
set_pending_dtor( ARG(T) ) ;
|
set_pending_dtor( ARG(T) ) ;
|
||||||
@ -212,9 +226,9 @@ template<class T>
|
|||||||
void test_relops( T const* )
|
void test_relops( T const* )
|
||||||
{
|
{
|
||||||
TRACE( std::endl << BOOST_CURRENT_FUNCTION );
|
TRACE( std::endl << BOOST_CURRENT_FUNCTION );
|
||||||
|
|
||||||
reset_throw_on_copy( ARG(T) ) ;
|
reset_throw_on_copy( ARG(T) ) ;
|
||||||
|
|
||||||
T v0(18);
|
T v0(18);
|
||||||
T v1(19);
|
T v1(19);
|
||||||
T v2(19);
|
T v2(19);
|
||||||
@ -233,11 +247,11 @@ void test_relops( T const* )
|
|||||||
|
|
||||||
// Check when both are uininitalized.
|
// Check when both are uininitalized.
|
||||||
BOOST_CHECK ( def0 == def1 ) ; // both uninitialized compare equal
|
BOOST_CHECK ( def0 == def1 ) ; // both uninitialized compare equal
|
||||||
BOOST_CHECK ( !(def0 < def1) ) ; // uninitialized is never less than uninitialized
|
BOOST_CHECK ( !(def0 < def1) ) ; // uninitialized is never less than uninitialized
|
||||||
BOOST_CHECK ( !(def0 > def1) ) ; // uninitialized is never greater than uninitialized
|
BOOST_CHECK ( !(def0 > def1) ) ; // uninitialized is never greater than uninitialized
|
||||||
BOOST_CHECK ( !(def0 != def1) ) ;
|
BOOST_CHECK ( !(def0 != def1) ) ;
|
||||||
BOOST_CHECK ( def0 <= def1 ) ;
|
BOOST_CHECK ( def0 <= def1 ) ;
|
||||||
BOOST_CHECK ( def0 >= def1 ) ;
|
BOOST_CHECK ( def0 >= def1 ) ;
|
||||||
|
|
||||||
// Check when only lhs is uninitialized.
|
// Check when only lhs is uninitialized.
|
||||||
BOOST_CHECK ( def0 != opt0 ) ; // uninitialized is never equal to initialized
|
BOOST_CHECK ( def0 != opt0 ) ; // uninitialized is never equal to initialized
|
||||||
@ -254,7 +268,7 @@ void test_relops( T const* )
|
|||||||
BOOST_CHECK ( opt0 > def0 ) ;
|
BOOST_CHECK ( opt0 > def0 ) ;
|
||||||
BOOST_CHECK ( !(opt0 <= def0) ) ;
|
BOOST_CHECK ( !(opt0 <= def0) ) ;
|
||||||
BOOST_CHECK ( opt0 >= opt0 ) ;
|
BOOST_CHECK ( opt0 >= opt0 ) ;
|
||||||
|
|
||||||
// If both are initialized, values are compared
|
// If both are initialized, values are compared
|
||||||
BOOST_CHECK ( opt0 != opt1 ) ;
|
BOOST_CHECK ( opt0 != opt1 ) ;
|
||||||
BOOST_CHECK ( opt1 == opt2 ) ;
|
BOOST_CHECK ( opt1 == opt2 ) ;
|
||||||
@ -270,7 +284,7 @@ void test_none( T const* )
|
|||||||
TRACE( std::endl << BOOST_CURRENT_FUNCTION );
|
TRACE( std::endl << BOOST_CURRENT_FUNCTION );
|
||||||
|
|
||||||
using boost::none ;
|
using boost::none ;
|
||||||
|
|
||||||
T a(1234);
|
T a(1234);
|
||||||
|
|
||||||
optional<T&> def0 ;
|
optional<T&> def0 ;
|
||||||
|
Reference in New Issue
Block a user