none_t/none reimplemented to avoid precompiled header issues (thanks to Joe Gottam)

optional<T> now has direct relational operator
optional<T>::operator-> fixed for reference types


[SVN r37126]
This commit is contained in:
Fernando Cacciola
2007-03-01 23:08:33 +00:00
parent 9bbde2be14
commit b6a1946a60
6 changed files with 391 additions and 186 deletions

View File

@ -24,6 +24,7 @@ HREF="../../../boost/optional/optional.hpp">boost/optional/optional.hpp</A>&gt;
<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="#refassign">Rebinding semantics for assignment of optional references</A></DT>
<DT><A HREF="#none">none_t</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&lt;bool&gt;</A></DT> <DT><A HREF="#bool">A note about optional&lt;bool&gt;</A></DT>
<DT><A HREF="#exsafety">Exception Safety Guarantees</A></DT> <DT><A HREF="#exsafety">Exception Safety Guarantees</A></DT>
@ -139,7 +140,7 @@ necessary in order to do so.</p>
<u>purpose</u> of optional&lt;T&gt; suggests <u>purpose</u> of optional&lt;T&gt; suggests
an alternative model: a <i>container</i> that either has a value of T or nothing. an alternative model: a <i>container</i> that either has a value of T or nothing.
</p> </p>
<p>As of this writing I don't know of any precedence for a variable-size fixed-capacity (of 1) <p>As of this writing I don't know of any precedent for a variable-size fixed-capacity (of 1)
stack-based container model for optional values, yet I believe this is the consequence of stack-based container model for optional values, yet I believe this is the consequence of
the lack of practical implementations of such a container rather than an inherent shortcoming the lack of practical implementations of such a container rather than an inherent shortcoming
of the container model.</p> of the container model.</p>
@ -324,6 +325,8 @@ class optional
optional ( T const&amp; v ) ; 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 ) ; optional ( optional const&amp; rhs ) ;
template&lt;class U&gt; explicit optional ( optional&lt;U&gt; const&amp; rhs ) ; template&lt;class U&gt; explicit optional ( optional&lt;U&gt; const&amp; rhs ) ;
@ -347,6 +350,8 @@ class optional
T const& get() const ; T const& get() const ;
T& get() ; T& get() ;
T const&amp; get_value_or( T const&amp; default ) const ; <u><i>[new in 1.34]</u></i>
T const* operator -&gt;() const ; T const* operator -&gt;() const ;
T* operator -&gt;() ; T* operator -&gt;() ;
@ -380,6 +385,36 @@ 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 bool operator >= ( optional&lt;T&gt; const& x, optional&lt;T&gt; const& y ) ;
template&lt;class T&gt; inline bool operator == ( optional&lt;T&gt; const& x, none_t n ) ; <u><i>[new in 1.34]</u></i>
template&lt;class T&gt; inline bool operator != ( optional&lt;T&gt; const& x, none_t n ) ; <u><i>[new in 1.34]</u></i>
template&lt;class T&gt; inline bool operator < ( optional&lt;T&gt; const& x, none_t n ) ; <u><i>[new in 1.34]</u></i>
template&lt;class T&gt; inline bool operator > ( optional&lt;T&gt; const& x, none_t n ) ; <u><i>[new in 1.34]</u></i>
template&lt;class T&gt; inline bool operator <= ( optional&lt;T&gt; const& x, none_t n ) ; <u><i>[new in 1.34]</u></i>
template&lt;class T&gt; inline bool operator >= ( optional&lt;T&gt; const& x, none_t n ) ; <u><i>[new in 1.34]</u></i>
template&lt;class T&gt; inline bool operator == ( none_t n, optional&lt;T&gt; const& y ) ; <u><i>[new in 1.34]</u></i>
template&lt;class T&gt; inline bool operator != ( none_t n, optional&lt;T&gt; const& y ) ; <u><i>[new in 1.34]</u></i>
template&lt;class T&gt; inline bool operator < ( none_t n, optional&lt;T&gt; const& y ) ; <u><i>[new in 1.34]</u></i>
template&lt;class T&gt; inline bool operator > ( none_t n, optional&lt;T&gt; const& y ) ; <u><i>[new in 1.34]</u></i>
template&lt;class T&gt; inline bool operator <= ( none_t n, optional&lt;T&gt; const& y ) ; <u><i>[new in 1.34]</u></i>
template&lt;class T&gt; inline bool operator >= ( none_t n, optional&lt;T&gt; const& y ) ; <u><i>[new in 1.34]</u></i>
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 const&amp; get_optional_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 const& get ( optional&lt;T&gt; const& opt ) ;
template&lt;class T&gt; inline T& get ( optional&lt;T&gt; & opt ) ; template&lt;class T&gt; inline T& get ( optional&lt;T&gt; & opt ) ;
@ -436,7 +471,7 @@ assert ( !def ) ;</pre>
<pre>optional&lt;T&gt;::optional( none_t );</pre> <pre>optional&lt;T&gt;::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>
<p><b>Throws:</b> Nothing.</p> <p><b>Throws:</b> Nothing.</p>
<p><b>Notes:</b></p> <p><b>Notes:</b></p>
@ -448,9 +483,11 @@ used as the parameter.</p>
</blockquote> </blockquote>
<p><b>Example:</b></p> <p><b>Example:</b></p>
<blockquote> <blockquote>
<pre>#include &lt;boost/none.hpp&gt;</pre> <pre>
<pre>optional&lt;T&gt; n(none) ; #include &lt;boost/none.hpp&gt;
assert ( !n ) ;</pre> optional&lt;int&gt; n(boost::none) ;
assert ( !n ) ;
</pre>
</blockquote> </blockquote>
</blockquote> </blockquote>
@ -459,7 +496,6 @@ assert ( !n ) ;</pre>
<pre>optional&lt;T <i>(not a ref)</i>&gt;::optional( T const&amp; v )</pre> <pre>optional&lt;T <i>(not a ref)</i>&gt;::optional( T const&amp; v )</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>
<!-- 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>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>Throws:</b> Whatever T::T( T const&amp; ) throws.</p>
<p><b>Notes: </b> T::T( T const&amp; ) is called.</p> <p><b>Notes: </b> T::T( T const&amp; ) is called.</p>
@ -468,9 +504,11 @@ in that case, this constructor has no effect.
</p> </p>
<p><b>Example:</b></p> <p><b>Example:</b></p>
<blockquote> <blockquote>
<pre>T v; <pre>
T v;
optional&lt;T&gt; opt(v); optional&lt;T&gt; opt(v);
assert ( *opt == v ) ;</pre> assert ( *opt == v ) ;
</pre>
</blockquote> </blockquote>
</blockquote> </blockquote>
@ -484,17 +522,37 @@ instance of an internal type wrapping the reference 'ref'.</p>
<p><b>Throws:</b> Nothing.</p> <p><b>Throws:</b> Nothing.</p>
<p><b>Example:</b></p> <p><b>Example:</b></p>
<blockquote> <blockquote>
<pre>T v; <pre>
T v;
T&amp; vref = v ; T&amp; vref = v ;
optional&lt;T&amp;&gt; opt(vref); optional&lt;T&amp;&gt; opt(vref);
assert ( *opt == v ) ; assert ( *opt == v ) ;
++ v ; // mutate referee ++ v ; // mutate referee
assert (*opt == v); </pre> assert (*opt == v);
</pre>
</blockquote> </blockquote>
</blockquote> </blockquote>
<HR> <HR>
<pre>optional&lt;T <i>(not a ref)</i>&gt;::optional( bool condition, T const&amp; v ) ;
optional&lt;T&amp;&gt; ::optional( bool condition, T&amp; 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; ::optional( T&amp; v )
</pre>
<p>otherwise, same as:</p>
<pre>
optional&lt;T <i>(not a ref)</i>&gt;::optional()
optional&lt;T&amp;&gt; ::optional()
</pre>
</blockquote>
<HR>
<pre>optional&lt;T <i>(not a ref)</i>&gt;::optional( optional const&amp; rhs );</pre> <pre>optional&lt;T <i>(not a ref)</i>&gt;::optional( optional const&amp; rhs );</pre>
<blockquote> <blockquote>
<p><b>Effect:</b> Copy-Constructs an <b>optional</b>.</p> <p><b>Effect:</b> Copy-Constructs an <b>optional</b>.</p>
@ -508,7 +566,8 @@ in that case, this constructor has no effect.
</p> </p>
<p><b>Example:</b></p> <p><b>Example:</b></p>
<blockquote> <blockquote>
<pre>optional&lt;T&gt; uninit ; <pre>
optional&lt;T&gt; uninit ;
assert (!uninit); assert (!uninit);
optional&lt;T&gt; uinit2 ( uninit ) ; optional&lt;T&gt; uinit2 ( uninit ) ;
@ -537,7 +596,8 @@ is uninitialized.</p>
reefer to the same object<b> </b>(they alias).</p> reefer to the same object<b> </b>(they alias).</p>
<p><b>Example:</b></p> <p><b>Example:</b></p>
<blockquote> <blockquote>
<pre>optional&lt;T&amp;&gt; uninit ; <pre>
optional&lt;T&amp;&gt; uninit ;
assert (!uninit); assert (!uninit);
optional&lt;T&amp;&gt; uinit2 ( uninit ) ; optional&lt;T&amp;&gt; uinit2 ( uninit ) ;
@ -580,7 +640,8 @@ in that case, this constructor has no effect.
<p><b>Example:</b></p> <p><b>Example:</b></p>
<blockquote> <blockquote>
<pre>optional&lt;double&gt; x(123.4); <pre>
optional&lt;double&gt; x(123.4);
assert ( *x == 123.4 ) ; assert ( *x == 123.4 ) ;
optional&lt;int&gt; y(x) ; optional&lt;int&gt; y(x) ;
@ -608,7 +669,8 @@ in that case, this constructor has no effect.
<p><b>Example:</b></p> <p><b>Example:</b></p>
<blockquote> <blockquote>
<pre>class C { C ( char, double, std::string ) ; } ; <pre>
class C { C ( char, double, std::string ) ; } ;
C v('A',123.4,&quot;hello&quot;); C v('A',123.4,&quot;hello&quot;);
@ -624,6 +686,27 @@ assert ( *y == v ) ;
<HR> <HR>
<pre>optional&amp; optional&lt;T</i>&gt;::operator= ( none_t n ) ;</pre>
<blockquote>
<p><b>Effect:</b> Same as opeator=(optional const&amp; rhs), when rhs is default-constructed (uninitialized).</p>
<p><b>Postconditions:</b> <b>*this</b> is uninitialized</p>
<p><b>Example:</b></p>
<blockquote>
<pre>
#include &lt;boost/none.hpp&gt;
optional&lt;int&gt; def ;
optional&lt;int&gt; opt(123) ;
opt = boost::none ;
assert ( opt == def ) ;
</pre>
</blockquote>
</blockquote>
<HR>
<pre>optional&amp; optional&lt;T <i>(not a ref)</i>&gt;::operator= ( T const&amp; rhs ) ;</pre> <pre>optional&amp; optional&lt;T <i>(not a ref)</i>&gt;::operator= ( T const&amp; rhs ) ;</pre>
<blockquote> <blockquote>
<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>
@ -639,7 +722,8 @@ uninitialized and T's <i>copy constructor</i> fails, <b>*this</b> is left
properly uninitialized]</p> properly uninitialized]</p>
<p><b>Example:</b></p> <p><b>Example:</b></p>
<blockquote> <blockquote>
<pre>T x; <pre>
T x;
optional&lt;T&gt; def ; optional&lt;T&gt; def ;
optional&lt;T&gt; opt(x) ; optional&lt;T&gt; opt(x) ;
@ -662,7 +746,8 @@ and it references the same object referenced by <b>rhs.</b></p>
new object. See <A HREF="#refassign">here</a> for details on this behavior.</p> new object. See <A HREF="#refassign">here</a> for details on this behavior.</p>
<p><b>Example:</b></p> <p><b>Example:</b></p>
<blockquote> <blockquote>
<pre>int a = 1 ; <pre>
int a = 1 ;
int b = 2 ; int b = 2 ;
T&amp; ra = a ; T&amp; ra = a ;
T&amp; rb = b ; T&amp; rb = b ;
@ -792,12 +877,11 @@ assert ( *opt1 == static_cast&lt;U&gt;(v) ) ;
<HR> <HR>
<pre>void optional&lt;T&gt;::reset() ;</pre> <pre>void optional&lt;T&gt;::reset() ;</pre>
<blockquote> <blockquote>
<p><b>Deprecated: </b>Same as operator=( detail::none_t );</p> <p><b>Deprecated: </b>Same as operator=( none_t n);</p>
</blockquote> </blockquote>
<HR> <HR>
<pre>T const&amp; optional&lt;T <i>(not a ref)</i>&gt;::operator*() const ; <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> T&amp; optional&lt;T<i> (not a ref)</i>&gt;::operator*();</pre>
@ -828,6 +912,32 @@ assert ( *opt == w ) ;
<HR> <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 ; <pre>T const&amp; optional&lt;T&amp;&gt;::operator*() const ;
T &amp; optional&lt;T<i>&amp;</i>&gt;::operator*();</pre> T &amp; optional&lt;T<i>&amp;</i>&gt;::operator*();</pre>
@ -857,29 +967,39 @@ assert ( *opt == v ) ;</pre>
<HR> <HR>
<pre>T const* optional&lt;T <i>(not a ref)</i>&gt;::get_ptr() const ; <pre>T const* optional&lt;T&gt;::get_ptr() const ;
T* optional&lt;T <i>(not a ref)</i>&gt;::get_ptr() ; T* optional&lt;T&gt;::get_ptr() ;
inline T const* get_pointer ( optional&lt;T <i>(not a ref)</i>&gt; const&amp; ) ; inline T const* get_pointer ( optional&lt;T&gt; const&amp; ) ;
inline T* get_pointer ( optional&lt;T <i>(not a ref)</i>&gt; &amp;) ; inline T* get_pointer ( optional&lt;T&gt; &amp;) ;
</pre> </pre>
<blockquote> <blockquote>
<p><b>Returns:</b> If <b>*this</b> is initialized, a pointer to the contained <p><b>Returns:</b> If <b>*this</b> is initialized, a pointer to the contained
value; else 0 (<i>null</i>). value; else 0 (<i>null</i>).
</p> </p>
<p><b>Throws:</b> Nothing.</p> <p><b>Throws:</b> Nothing.</p>
<p><b>Notes:</b> If T is a reference type, the pointer is to the referenced object</p>
<p><b>Notes:</b> The contained value is permanently stored within *this, so <p><b>Notes:</b> The contained value is permanently stored within *this, so
you should not hold nor delete this pointer you should not hold nor delete this pointer.
</p> </p>
<p><b>Example:</b></p> <p><b>Example:</b></p>
<blockquote> <blockquote>
<pre>T v; <pre>int v=123;
optional&lt;T&gt; opt(v); optional&lt;int&gt; opt(v);
optional&lt;T&gt; const copt(v); optional&lt;int&gt; const copt(v);
T* p = opt.get_ptr() ; int* p = opt.get_ptr() ;
T const* cp = copt.get_ptr(); int const* cp = copt.get_ptr();
assert ( p == get_pointer(opt) ); assert ( p == get_pointer(opt) );
assert ( cp == get_pointer(copt) ) ; assert ( cp == get_pointer(copt) ) ;
int& rv = v ;
optional&lt;int&amp;&gt; optr(rv);
*(optr.get_ptr()) = 456 ;
assert ( v == 456 );
</pre> </pre>
</blockquote> </blockquote>
</blockquote> </blockquote>
@ -888,13 +1008,14 @@ assert ( cp == get_pointer(copt) ) ;
<HR> <HR>
<pre>T const* optional&lt;T <i>(not a ref)</i>&gt;::operator -&gt;() const ; <pre>T const* optional&lt;T&gt;::operator -&gt;() const ;
T* optional&lt;T <i>(not a ref)</i>&gt;::operator -&gt;() ; T* optional&lt;T&gt;::operator -&gt;() ;
</pre> </pre>
<blockquote> <blockquote>
<p><b>Requirements: *this</b> is initialized.</p> <p><b>Requirements: *this</b> is initialized.</p>
<p><b>Returns:</b> A pointer to the contained value.</p> <p><b>Returns:</b> A pointer to the contained value.</p>
<p><b>Throws:</b> Nothing.</p> <p><b>Throws:</b> Nothing.</p>
<p><b>Notes:</b> If T is a reference type, the pointer is to the referenced object</p>
<p><b>Notes:</b> The requirement is asserted via BOOST_ASSERT().</p> <p><b>Notes:</b> The requirement is asserted via BOOST_ASSERT().</p>
<p><b>Example:</b></p> <p><b>Example:</b></p>
<blockquote> <blockquote>
@ -902,6 +1023,14 @@ T* optional&lt;T <i>(not a ref)</i>&gt;::operator -&gt;() ;
X x ; X x ;
optional&lt;X&gt; opt (x); optional&lt;X&gt; opt (x);
opt-&gt;mdata = 2 ; opt-&gt;mdata = 2 ;
X& rx = x ;
optional&lt;X&amp;&gt; optr (rx);
optr-&gt;mdata = 4 ;
assert ( x.mdata = 4 )
</pre> </pre>
</blockquote> </blockquote>
</blockquote> </blockquote>
@ -965,18 +1094,47 @@ assert ( opt.is_initialized() );</pre>
<HR> <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> <pre>bool operator == ( optional&lt;T&gt; const&amp x, optional&lt;T&gt const&amp y );</pre>
<blockquote> <blockquote>
<p><b>Returns:</b> If both <b>x</b> and <b>y</b> are initialied, <code>(*x == *y)</code>. <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>. If only x or y is initialized, <code>false</code>. If both are uninitialized, <code>true</code>. </p>
</p>
<p><b>Throws:</b> Nothing.</p> <p><b>Throws:</b> Nothing.</p>
<p><b>Notes:</b> Pointers have shallow relational operators while <b>optional</b> has <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 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; 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 use <a href="../../utility/OptionalPointee.html#equal">equal_pointees()</a> instead </p>
</p>
<p><b>Example:</b></p> <p><b>Example:</b></p>
<blockquote> <blockquote>
<pre>T x(12); <pre>T x(12);
@ -1012,14 +1170,12 @@ assert ( optX != optZ ) ;
<blockquote> <blockquote>
<p><b>Returns:</b> If <b>y</b> is not initialized, <code>false</code>. <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 <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>. If both <b>x</b> and <b>y</b> are initialized, <code>(*x &lt; *y)</code>. </p>
</p>
<p><b>Throws:</b> Nothing.</p> <p><b>Throws:</b> Nothing.</p>
<p><b>Notes:</b> Pointers have shallow relational operators while <b>optional</b> has <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 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; 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 use <a href="../../utility/OptionalPointee.html#less">less_pointees()</a> instead </p>
</p>
<p><b>Example:</b></p> <p><b>Example:</b></p>
<blockquote> <blockquote>
<pre>T x(12); <pre>T x(12);
@ -1077,28 +1233,40 @@ assert ( optX != optZ ) ;
<p><b>Throws:</b> Nothing.</p> <p><b>Throws:</b> Nothing.</p>
</blockquote> </blockquote>
<HR>
<pre>
bool operator == ( optional&lt;T&gt; const&amp x, none_t n );
bool operator != ( optional&lt;T&gt; const&amp x, none_t n );
bool operator &lt; ( optional&lt;T&gt; const&amp x, none_t n );
bool operator &gt; ( optional&lt;T&gt; const&amp x, none_t n );
bool operator &lt;= ( optional&lt;T&gt; const&amp x, none_t n );
bool operator &gt;= ( optional&lt;T&gt; const&amp x, none_t n );
bool operator == ( none_t n, optional&lt;T&gt; const&amp y );
bool operator != ( none_t n, optional&lt;T&gt; const&amp y );
bool operator &lt; ( none_t n, optional&lt;T&gt; const&amp y );
bool operator &gt; ( none_t n, optional&lt;T&gt; const&amp y );
bool operator &lt;= ( none_t n, optional&lt;T&gt; const&amp y );
bool operator &gt;= ( none_t n, optional&lt;T&gt; const&amp y );
</pre>
<blockquote>
<p><b>Returns:</b> The result obtained by replacing the argument 'n' by optional&lt;T&gt;().</p>
</blockquote>
<HR> <HR>
<pre>void swap ( optional&lt;T&gt;&amp x, optional&lt;T&gt&amp y );</pre> <pre>void swap ( optional&lt;T&gt;&amp x, optional&lt;T&gt&amp y );</pre>
<blockquote> <blockquote>
<p><b>Effect:</b> If both <b>x</b> and <b>y</b> are initialized, calls <code>swap(*x,*y)</code> <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>
using std::swap.<br> If only one is initialized, say x, calls: <code>y = *x; x = boost:none;</code><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>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. <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. If only one is initialized, whatever T::T ( T const&amp; ) throws. </p>
</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>
<p><b>Notes:</b> If both are initialized, swap(T&amp;,T&amp;) is used <i>unqualified</i> If only one is initialized, T::~T() and T::T( T const& ) is called. </p>
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 <p><b>Exception Safety:</b> If both are initialized, this operation has the exception
safety guarantees of swap(T&,T&).<br> 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& ). If only one is initialized, it has the same <b>basic</b> guarantee as optional&lt;T&gt;::operator=( T const& ). </p>
</p>
<p><b>Example:</b></p> <p><b>Example:</b></p>
<blockquote> <blockquote>
<pre>T x(12); <pre>T x(12);
@ -1148,12 +1316,12 @@ void receive_async_message()
<pre>optional&lt;string&gt; name ; <pre>optional&lt;string&gt; name ;
if ( database.open() ) if ( database.open() )
{ {
&nbsp; name.reset ( database.lookup(employer_name) ) ; &nbsp; name = database.lookup(employer_name) ;
} }
else else
{ {
&nbsp; if ( can_ask_user ) &nbsp; if ( can_ask_user )
&nbsp;&nbsp;&nbsp; name.reset ( user.ask(employer_name) ) ; &nbsp;&nbsp;&nbsp; name = user.ask(employer_name) ;
} }
if ( name ) if ( name )
@ -1174,7 +1342,7 @@ else print(&quot;employer's name not found!&quot;);
&nbsp;&nbsp;&nbsp; void clip_in_rect ( rect const&amp; rect ) &nbsp;&nbsp;&nbsp; void clip_in_rect ( rect const&amp; rect )
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .... &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ....
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_clipping_rect.reset ( rect ) ; // initialized here. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_clipping_rect = rect ; // initialized here.
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp; void draw ( canvas& cvs ) &nbsp;&nbsp;&nbsp; void draw ( canvas& cvs )
@ -1218,15 +1386,16 @@ some operations are not available in this case:</p>
<li>Converting assignment</li> <li>Converting assignment</li>
<li>InPlace construction</li> <li>InPlace construction</li>
<li>InPlace assignment</li> <li>InPlace assignment</li>
<li>Value-access via pointer</li>
</ul> </ul>
<p>Also, even though optional&lt;T&amp;&gt; treats it wrapped pseudo-object much as a real <p>Also, even though optional&lt;T&amp;&gt; treats it wrapped pseudo-object much as a real
value, a true real reference is stored so aliasing will ocurr: </p> value, a true real reference is stored so aliasing will ocurr: </p>
<ul> <ul>
<li>Copies of optional&lt;T&amp;&gt; will copy the references but all these references <li>Copies of optional&lt;T&amp;&gt; copies the reference, but all copied references
will nonetheless reefer to the same object.</li> will nonetheless reefer to the same object.</li>
<li>Value-access will actually provide access to the referenced object rather <li>Value-access provides access to the referenced object rather
than the reference itself.</li>
<li>Pointer-access provides a pointer to the referenced object rather
than the reference itself.</li> than the reference itself.</li>
</ul> </ul>
@ -1254,8 +1423,7 @@ assert(a==b);
b = 3 ; b = 3 ;
assert(ra!=b); // 'ra' is not rebound to 'b' assert(ra!=b); // 'ra' is not rebound to 'b'
</pre> </pre>
<p>Now, if you assign to an <i>initialized</i> optional&lt;T&amp;&gt;, the effect is to <b> <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
rebind</b> to the new object instead of assigning the referee. This is unlike
bare C++ references.</p> bare C++ references.</p>
<pre>int a = 1 ; <pre>int a = 1 ;
int b = 2 ; int b = 2 ;
@ -1309,6 +1477,13 @@ In such scenario, you can assign the value itself directly, as in:</p>
<pre>assert(!!opt); <pre>assert(!!opt);
*opt=value; </pre> *opt=value; </pre>
<HR>
<H2><A NAME="none">none_t</A></H2>
<p>
</p>
<HR> <HR>
<H2><A NAME="inplace">In-Place Factories</A></H2> <H2><A NAME="inplace">In-Place Factories</A></H2>
@ -1358,8 +1533,7 @@ public:
</pre> </pre>
<p>A limitation of this method is that it doesn't scale well to wrapped objects with multiple <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> 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 <p>The solution presented in this library is the family of <b>InPlaceFactories</b> and <b>TypedInPlaceFactories</b>.<br>
<b>TypedInPlaceFactories</b>.<br>
These factories are a family of classes which encapsulate an increasing number of arbitrary 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 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> parameters at an address specified by the user via placement new.</p>
@ -1427,10 +1601,7 @@ public:
W ( in_place(123,"hello") ) ; W ( in_place(123,"hello") ) ;
} }
</pre> </pre>
<p>The factories are implemented in the headers: <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>
<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> <HR>
@ -1440,9 +1611,8 @@ public:
the <i>maybe</i> state <u>represents a valid value</u>, unlike the corresponding state the <i>maybe</i> state <u>represents a valid value</u>, unlike the corresponding state
of an uninitialized optional&lt;bool&gt;.<br> of an uninitialized optional&lt;bool&gt;.<br>
It should be carefully considered if an optional&lt;bool&gt; instead of a tribool is really needed</p> It should be carefully considered if an optional&lt;bool&gt; instead of a tribool is really needed</p>
<p>Second, optional&lt;&gt; provides an implicit conversion to bool. This conversion <p>Second, optional&lt;&gt; provides a simple way to test initialization state: an implicit conversion to a type that evaluates as a 'bool' in a boolean context.<br>
refers to the initialization state and not to the contained value.<br> Using optional&lt;bool&gt; can lead to subtle errors due to this implicit conversion:</p>
Using optional&lt;bool&gt; can lead to subtle errors due to the implicit bool conversion:</p>
<pre>void foo ( bool v ) ; <pre>void foo ( bool v ) ;
void bar() void bar()
{ {
@ -1458,7 +1628,9 @@ void bar()
integral promotions don't apply (i.e. if foo() takes an 'int' instead, it won't compile). <HR> integral promotions don't apply (i.e. if foo() takes an 'int' instead, it won't compile). <HR>
<H2><A NAME="exsafety">Exception Safety Guarantees</A></H2> <H2><A NAME="exsafety">Exception Safety Guarantees</A></H2>
<H3><u>Assignment and Reset:</u></H3>
<H3><u>Assignment:</u></H3>
<p><i>IMPORTANT NOTE: This changed in 1.33.1 with respect to previous versions</i></p>
<p>Because of the current implementation (see <A HREF="#impl">Implementation Notes</A>), all <p>Because of the current implementation (see <A HREF="#impl">Implementation Notes</A>), all
of the assignment methods:</p> of the assignment methods:</p>
<ul> <ul>
@ -1471,61 +1643,17 @@ of the assignment methods:</p>
InPlaceFactory const&amp; ) </code></li> InPlaceFactory const&amp; ) </code></li>
<li> <code>template&lt;class TypedInPlaceFactory&gt; optional&lt;T&gt;::operator= ( <li> <code>template&lt;class TypedInPlaceFactory&gt; optional&lt;T&gt;::operator= (
TypedInPlaceFactory const&amp; ) </code></li> TypedInPlaceFactory const&amp; ) </code></li>
<li> <code>optional&lt;T&gt;:::reset ( T const&amp;)</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>cannot offer any <i>exception safety guarantee</i> beyond that provided by <code>T::operator=( T const&amp; )</code></p>
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> <p>On the other hand, the <i>uninitializing</i> methods:</p>
<ul> <ul>
<li><code>optional&lt;T&gt;::operator= ( detail::none_t ) </code></li> <li><code>optional&lt;T&gt;::operator= ( detail::none_t ) </code></li>
<li><code>optional&lt;T&gt;::reset()</code></li>
</ul> </ul>
<p>Provide the no-throw guarantee (assuming a no-throw T::~T())</p> <p>Provides the no-throw guarantee (assuming a no-throw T::~T()) becuse it only destroys the stored object.</p>
<p>However, since <code>optional&lt&gt</code> itself doesn't throw any exceptions,
the only source for exceptions here are T's constructor, so if you know the exception guarantees
for T::T ( T const&amp; ), you know that optional's assignment and reset has the same guarantees.</p>
<pre>//
// Case 1: Exception thrown during assignment.
//
T v0(123);
optional&ltT&gt opt0(v0);
try
{
&nbsp; T v1(456);
&nbsp; optional&ltT&gt opt1(v1);
&nbsp; opt0 = opt1 ;
&nbsp; // If no exception was thrown, assignment succeeded.
&nbsp; assert( *opt0 == v1 ) ;
}
catch(...)
{
&nbsp; // If any exception was thrown, 'opt0' is reset to uninitialized.
&nbsp; assert( !opt0 ) ;
}
//
// Case 2: Exception thrown during reset(v)
//
T v0(123);
optional&ltT&gt opt(v0);
try
{
&nbsp; T v1(456);
&nbsp; opt.reset ( v1 ) ;
&nbsp; // If no exception was thrown, reset succeeded.
&nbsp; assert( *opt == v1 ) ;
}
catch(...)
{
&nbsp; // If any exception was thrown, 'opt' is reset to uninitialized.
&nbsp; assert( !opt ) ;
}
</pre>
<H3><u>Swap:</u></H3> <H3><u>Swap:</u></H3>
<p><code>void swap( optional&lt;T&gt;&amp;, optional&lt;T&gt;&amp; )</code> has the same exception guarantee as <code>swap(T&amp;,T&amp;)</code> when both optionals are initialized.<br> <p><code>void swap( optional&lt;T&gt;&amp;, optional&lt;T&gt;&amp; )</code> has the same exception guarantee as <code>swap(T&amp;,T&amp;)</code> when both optionals are initialized.<br>
If only one of the optionals is initialized, it gives the same <i>basic</i> exception guarantee as <code>optional&lt;T&gt;::reset( T const&amp; )</code> (since <code>optional&lt;T&gt;::reset()</code> doesn't throw).<br> If only one of the optionals is initialized, it gives the same exception guarantee as <code>T::operator=( T const&amp; )</code> (since <code>optional&lt;T&gt;::operator=( none_t )</code> doesn't throw).<br>
If none of the optionals is initialized, it has no-throw guarantee since it is a no-op. </p> If none of the optionals is initialized, it has no-throw guarantee since it is a no-op. </p>
<HR> <HR>
@ -1539,14 +1667,11 @@ T <u>is not</u> required to be <a href="http://www.sgi.com/tech/stl/DefaultConst
<H2><A NAME="impl">Implementation Notes</A></H2> <H2><A NAME="impl">Implementation Notes</A></H2>
<p>optional&lt;T&gt; is currently implemented <p>optional&lt;T&gt; is currently implemented
using a custom aligned storage facility built from <code>alignment_of</code> and <code>type_with_alignment</code> (both from Type Traits). using a custom aligned storage facility built from <code>alignment_of</code> and <code>type_with_alignment</code> (both from Type Traits).
It uses a separate boolean flag to indicate the initialization state.<br> It uses a separate boolean flag to indicate the initialization state.</p>
Placement new with T's copy constructor and T's destructor <p>Placement new with T's copy constructor and T's destructor
are explicitly used to initialize,copy and destroy optional values.<br> is explicitly used to initialize and destroy optional values. This allows T's default constructor to be effectively by-passed.</p>
As a result, T's default constructor is effectively by-passed, but the exception <p>If assignment is used and the lvalue optional is uninitialized, T's copy constructor is used. However, if it is already initialized, T's assignment operator is used. This prevents optional from offering any exception guarantee stronger than the one offered by the type T itself</p>
guarantees are basic.<br>
It is planned to replace the current implementation with another with
stronger exception safety, such as a future boost::variant<T,nil_t>. </p>
<HR> <HR>
@ -1600,15 +1725,12 @@ T <u>is not</u> required to be <a href="http://www.sgi.com/tech/stl/DefaultConst
</blockquote> </blockquote>
<HR> <HR>
<P>Revised April 21, 2005</P> <P>Revised March 1, 2007</P>
<p><EFBFBD> Copyright Fernando Luis Cacciola Carballal, 2003,2004,2005</p> <p><EFBFBD> Copyright Fernando Luis Cacciola Carballal, 2003-2007</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">www.boost.org/LICENSE_1_0.txt</a>)</p>
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>, <P>Developed by <A HREF="mailto:fernando_cacciola@hotmail.com">Fernando Cacciola</A>,
the latest version of this file can be found at <A 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> </pre></BODY>
</BODY> </HTML>
</HTML>

View File

@ -12,17 +12,12 @@
#ifndef BOOST_NONE_17SEP2003_HPP #ifndef BOOST_NONE_17SEP2003_HPP
#define BOOST_NONE_17SEP2003_HPP #define BOOST_NONE_17SEP2003_HPP
#include "boost/none_t.hpp"
// NOTE: Borland users have to include this header outside any precompiled headers
// (bcc<=5.64 cannot include instance data in a precompiled header)
// -- * To be verified, now that there's no unnamed namespace
namespace boost { namespace boost {
none_t const none = ((none_t)0) ; enum none_t {none = 0};
} // namespace boost } // namespace boost
#endif #endif

View File

@ -1,24 +0,0 @@
// 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

View File

@ -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/none_t.hpp" #include "boost/none.hpp"
#include "boost/utility/compare_pointees.hpp" #include "boost/utility/compare_pointees.hpp"
#include "boost/optional/optional_fwd.hpp" #include "boost/optional/optional_fwd.hpp"
@ -173,7 +173,7 @@ class optional_base : public optional_tag
// Creates an optional<T> uninitialized. // Creates an optional<T> uninitialized.
// No-throw // No-throw
optional_base ( none_t const& ) optional_base ( none_t )
: :
m_initialized(false) {} m_initialized(false) {}
@ -266,7 +266,7 @@ class optional_base : public optional_tag
// 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 ( none_t const& ) { destroy(); } void assign ( none_t ) { destroy(); }
#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT #ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
template<class Expr> template<class Expr>
@ -461,7 +461,7 @@ class optional : public optional_detail::optional_base<T>
// Creates an optional<T> uninitialized. // Creates an optional<T> uninitialized.
// No-throw // No-throw
optional( none_t const& none_ ) : base(none_) {} optional( none_t 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
@ -552,7 +552,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= ( none_t const& none_ ) optional& operator= ( none_t none_ )
{ {
this->assign( none_ ) ; this->assign( none_ ) ;
return *this ; return *this ;
@ -680,6 +680,11 @@ get_pointer ( optional<T>& opt )
// optional's relational operators ( ==, !=, <, >, <=, >= ) have deep-semantics (compare values). // optional's relational operators ( ==, !=, <, >, <=, >= ) have deep-semantics (compare values).
// WARNING: This is UNLIKE pointers. Use equal_pointees()/less_pointess() in generic code instead. // WARNING: This is UNLIKE pointers. Use equal_pointees()/less_pointess() in generic code instead.
//
// optional<T> vs optional<T> cases
//
template<class T> template<class T>
inline inline
bool operator == ( optional<T> const& x, optional<T> const& y ) bool operator == ( optional<T> const& x, optional<T> const& y )
@ -710,64 +715,141 @@ inline
bool operator >= ( optional<T> const& x, optional<T> const& y ) bool operator >= ( optional<T> const& x, optional<T> const& y )
{ return !( x < y ) ; } { return !( x < y ) ; }
//
// optional<T> vs T cases
//
template<class T> template<class T>
inline inline
bool operator == ( optional<T> const& x, none_t const& ) bool operator == ( optional<T> const& x, T const& y )
{ return equal_pointees(x, optional<T>(y)); }
template<class T>
inline
bool operator < ( optional<T> const& x, T const& y )
{ return less_pointees(x, optional<T>(y)); }
template<class T>
inline
bool operator != ( optional<T> const& x, T const& y )
{ return !( x == y ) ; }
template<class T>
inline
bool operator > ( optional<T> const& x, T const& y )
{ return y < x ; }
template<class T>
inline
bool operator <= ( optional<T> const& x, T const& y )
{ return !( y < x ) ; }
template<class T>
inline
bool operator >= ( optional<T> const& x, T const& y )
{ return !( x < y ) ; }
//
// T vs optional<T> cases
//
template<class T>
inline
bool operator == ( T const& x, optional<T> const& y )
{ return equal_pointees( optional<T>(x), y ); }
template<class T>
inline
bool operator < ( T const& x, optional<T> const& y )
{ return less_pointees( optional<T>(x), y ); }
template<class T>
inline
bool operator != ( T const& x, optional<T> const& y )
{ return !( x == y ) ; }
template<class T>
inline
bool operator > ( T const& x, optional<T> const& y )
{ return y < x ; }
template<class T>
inline
bool operator <= ( T const& x, optional<T> const& y )
{ return !( y < x ) ; }
template<class T>
inline
bool operator >= ( T const& x, optional<T> const& y )
{ return !( x < y ) ; }
//
// optional<T> vs none cases
//
template<class T>
inline
bool operator == ( optional<T> const& x, none_t )
{ 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, none_t const& ) bool operator < ( optional<T> const& x, none_t )
{ 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, none_t const& y ) bool operator != ( optional<T> const& x, none_t y )
{ return !( x == y ) ; } { return !( x == y ) ; }
template<class T> template<class T>
inline inline
bool operator > ( optional<T> const& x, none_t const& y ) bool operator > ( optional<T> const& x, none_t y )
{ return y < x ; } { return y < x ; }
template<class T> template<class T>
inline inline
bool operator <= ( optional<T> const& x, none_t const& y ) bool operator <= ( optional<T> const& x, none_t y )
{ return !( y < x ) ; } { return !( y < x ) ; }
template<class T> template<class T>
inline inline
bool operator >= ( optional<T> const& x, none_t const& y ) bool operator >= ( optional<T> const& x, none_t y )
{ return !( x < y ) ; } { return !( x < y ) ; }
//
// none vs optional<T> cases
//
template<class T> template<class T>
inline inline
bool operator == ( none_t const& x, optional<T> const& y ) bool operator == ( none_t 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 < ( none_t const& x, optional<T> const& y ) bool operator < ( none_t 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 != ( none_t const& x, optional<T> const& y ) bool operator != ( none_t x, optional<T> const& y )
{ return !( x == y ) ; } { return !( x == y ) ; }
template<class T> template<class T>
inline inline
bool operator > ( none_t const& x, optional<T> const& y ) bool operator > ( none_t x, optional<T> const& y )
{ return y < x ; } { return y < x ; }
template<class T> template<class T>
inline inline
bool operator <= ( none_t const& x, optional<T> const& y ) bool operator <= ( none_t x, optional<T> const& y )
{ return !( y < x ) ; } { return !( y < x ) ; }
template<class T> template<class T>
inline inline
bool operator >= ( none_t const& x, optional<T> const& y ) bool operator >= ( none_t x, optional<T> const& y )
{ return !( x < y ) ; } { return !( x < y ) ; }
// //

View File

@ -22,7 +22,6 @@ import testing ;
[ run optional_test_inplace.cpp ] [ run optional_test_inplace.cpp ]
[ run optional_test_io.cpp ] [ run optional_test_io.cpp ]
[ compile-fail optional_test_fail1.cpp ] [ compile-fail optional_test_fail1.cpp ]
[ compile-fail optional_test_fail2.cpp ]
[ compile-fail optional_test_fail3a.cpp ] [ compile-fail optional_test_fail3a.cpp ]
[ compile-fail optional_test_fail3b.cpp ] [ compile-fail optional_test_fail3b.cpp ]
[ compile-fail optional_test_ref_fail1.cpp ] [ compile-fail optional_test_ref_fail1.cpp ]

View File

@ -704,16 +704,16 @@ void test_relops( T const* )
{ {
TRACE( std::endl << BOOST_CURRENT_FUNCTION ); TRACE( std::endl << BOOST_CURRENT_FUNCTION );
T v0(18); T v0(0);
T v1(19); T v1(1);
T v2(19); T v2(1);
optional<T> def0 ; optional<T> def0 ;
optional<T> def1 ; optional<T> def1 ;
optional<T> opt0(v0); optional<T> opt0(v0);
optional<T> opt1(v1); optional<T> opt1(v1);
optional<T> opt2(v2); optional<T> opt2(v2);
// Check identity // Check identity
BOOST_CHECK ( def0 == def0 ) ; BOOST_CHECK ( def0 == def0 ) ;
BOOST_CHECK ( opt0 == opt0 ) ; BOOST_CHECK ( opt0 == opt0 ) ;
@ -751,6 +751,33 @@ void test_relops( T const* )
BOOST_CHECK ( opt1 > opt0 ) ; BOOST_CHECK ( opt1 > opt0 ) ;
BOOST_CHECK ( opt1 <= opt2 ) ; BOOST_CHECK ( opt1 <= opt2 ) ;
BOOST_CHECK ( opt1 >= opt0 ) ; BOOST_CHECK ( opt1 >= opt0 ) ;
// Compare against a value directly
BOOST_CHECK ( opt0 == v0 ) ;
BOOST_CHECK ( opt0 != v1 ) ;
BOOST_CHECK ( opt1 == v2 ) ;
BOOST_CHECK ( opt0 < v1 ) ;
BOOST_CHECK ( opt1 > v0 ) ;
BOOST_CHECK ( opt1 <= v2 ) ;
BOOST_CHECK ( opt1 >= v0 ) ;
BOOST_CHECK ( v0 != opt1 ) ;
BOOST_CHECK ( v1 == opt2 ) ;
BOOST_CHECK ( v0 < opt1 ) ;
BOOST_CHECK ( v1 > opt0 ) ;
BOOST_CHECK ( v1 <= opt2 ) ;
BOOST_CHECK ( v1 >= opt0 ) ;
BOOST_CHECK ( def0 != v0 ) ;
BOOST_CHECK ( !(def0 == v0) ) ;
BOOST_CHECK ( def0 < v0 ) ;
BOOST_CHECK ( !(def0 > v0) ) ;
BOOST_CHECK ( def0 <= v0 ) ;
BOOST_CHECK ( !(def0 >= v0) ) ;
BOOST_CHECK ( v0 != def0 ) ;
BOOST_CHECK ( !(v0 == def0) ) ;
BOOST_CHECK ( !(v0 < def0) ) ;
BOOST_CHECK ( v0 > def0 ) ;
BOOST_CHECK ( !(v0 <= def0) ) ;
BOOST_CHECK ( v0 >= opt0 ) ;
} }
template<class T> template<class T>
@ -767,6 +794,10 @@ void test_none( T const* )
BOOST_CHECK ( def0 == none ) ; BOOST_CHECK ( def0 == none ) ;
BOOST_CHECK ( non_def != none ) ; BOOST_CHECK ( non_def != none ) ;
BOOST_CHECK ( !def1 ) ; BOOST_CHECK ( !def1 ) ;
BOOST_CHECK ( !(non_def < none) ) ;
BOOST_CHECK ( non_def > none ) ;
BOOST_CHECK ( !(non_def <= none) ) ;
BOOST_CHECK ( non_def >= none ) ;
non_def = none ; non_def = none ;
BOOST_CHECK ( !non_def ) ; BOOST_CHECK ( !non_def ) ;