Compare commits

...

18 Commits

Author SHA1 Message Date
041aa12848 Create branch for next serialization release
[SVN r38613]
2007-08-13 03:23:47 +00:00
3ff4258fbb This commit was manufactured by cvs2svn to create tag
'Version_1_34_1'.

[SVN r38286]
2007-07-24 19:28:14 +00:00
35040aab6a Add missing newline at eof.
[SVN r37425]
2007-04-12 19:43:30 +00:00
bfd5cc0a87 Updated single-header implementation
[SVN r37420]
2007-04-12 14:25:21 +00:00
0fd45d73b1 Doc update to reflect latest additions
[SVN r37368]
2007-04-05 18:55:22 +00:00
3bf8d0f1b4 Fixed incorrect BORLANDC macro
[SVN r37314]
2007-03-28 21:26:19 +00:00
789cb2b24f boost::none implementation fixed for bcc <= 5.6.4
[SVN r37301]
2007-03-27 16:02:57 +00:00
7287f2bf11 in_palce_factory.apply problem fixed
[SVN r37157]
2007-03-07 20:17:23 +00:00
b6a1946a60 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]
2007-03-01 23:08:33 +00:00
9bbde2be14 Fixed operator->() for optional references.
[SVN r37125]
2007-03-01 21:50:12 +00:00
f258713788 Fixed operator->() for optional references.
[SVN r37124]
2007-03-01 21:39:25 +00:00
3dc3f46d66 Merged copyright and license addition
[SVN r35907]
2006-11-07 19:27:00 +00:00
c23c21d9c2 Remove obsolete Boost.Build v1 files.
[SVN r35880]
2006-11-06 17:10:46 +00:00
5182283649 misused "precedence" changed to "precedent"
[SVN r35831]
2006-11-04 02:13:53 +00:00
4599ae0bfd merge from head [removed unnamed namespace (see http://lists.boost.org/Archives/boost/2006/07/107873.php); usual copyright/license/url fixes]
[SVN r34647]
2006-07-20 23:23:09 +00:00
9ccefc8349 workaround for Borland
[SVN r34288]
2006-06-12 19:02:41 +00:00
0961a6598a Disambiguated certain constructs.
[SVN r34226]
2006-06-08 01:39:40 +00:00
03248b5fd8 This commit was manufactured by cvs2svn to create branch 'RC_1_34_0'.
[SVN r33417]
2006-03-21 02:26:31 +00:00
10 changed files with 724 additions and 296 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="#ref">Optional references</A></DT>
<DT><A HREF="#refassign">Rebinding semantics for assignment of optional references</A></DT>
<DT><A HREF="#none">none_t and none</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="#exsafety">Exception Safety Guarantees</A></DT>
@ -127,7 +128,7 @@ undefined behavior</i>
which in our case is either <code>T</code> or <code>nil_t</code>.<br>
Using the <a href="../../../doc/html/variant.html">Boost.Variant</a> library, this model can be implemented
in terms of <code>boost::variant&lt;T,nil_t&gt;</code>.<br>
There is precedence for a discriminated union as a model for an optional value: the
There is precedent 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> built-in type constructor.
Thus, a discriminated union <code>T+nil_t</code> serves as a conceptual foundation.</p>
<p>A <code>variant&lt;T,nil_t&gt;</code> follows naturally from the traditional idiom of extending
@ -139,7 +140,7 @@ necessary in order to do so.</p>
<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.
</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
the lack of practical implementations of such a container rather than an inherent shortcoming
of the container model.</p>
@ -324,6 +325,8 @@ class optional
optional ( T const&amp; v ) ;
optional ( bool condition, T const&amp; v ) ; <u><i>[new in 1.34]</u></i>
optional ( optional const&amp; rhs ) ;
template&lt;class U&gt; explicit optional ( optional&lt;U&gt; const&amp; rhs ) ;
@ -347,6 +350,8 @@ class optional
T const& get() const ;
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* operator -&gt;() ;
@ -380,6 +385,60 @@ 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, T const& n ) ; <u><i>[new in 1.34]</u></i>
template&lt;class T&gt; inline bool operator != ( optional&lt;T&gt; const& x, T const& n ) ; <u><i>[new in 1.34]</u></i>
template&lt;class T&gt; inline bool operator < ( optional&lt;T&gt; const& x, T const& n ) ; <u><i>[new in 1.34]</u></i>
template&lt;class T&gt; inline bool operator > ( optional&lt;T&gt; const& x, T const& n ) ; <u><i>[new in 1.34]</u></i>
template&lt;class T&gt; inline bool operator <= ( optional&lt;T&gt; const& x, T const& n ) ; <u><i>[new in 1.34]</u></i>
template&lt;class T&gt; inline bool operator >= ( optional&lt;T&gt; const& x, T const& n ) ; <u><i>[new in 1.34]</u></i>
template&lt;class T&gt; inline bool operator == ( T const& n, optional&lt;T&gt; const& y ) ; <u><i>[new in 1.34]</u></i>
template&lt;class T&gt; inline bool operator != ( T const& n, optional&lt;T&gt; const& y ) ; <u><i>[new in 1.34]</u></i>
template&lt;class T&gt; inline bool operator < ( T const& n, optional&lt;T&gt; const& y ) ; <u><i>[new in 1.34]</u></i>
template&lt;class T&gt; inline bool operator > ( T const& n, optional&lt;T&gt; const& y ) ; <u><i>[new in 1.34]</u></i>
template&lt;class T&gt; inline bool operator <= ( T const& n, optional&lt;T&gt; const& y ) ; <u><i>[new in 1.34]</u></i>
template&lt;class T&gt; inline bool operator >= ( T const& n, optional&lt;T&gt; const& y ) ; <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 >= ( 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& get ( optional&lt;T&gt; & opt ) ;
@ -436,7 +495,7 @@ assert ( !def ) ;</pre>
<pre>optional&lt;T&gt;::optional( none_t );</pre>
<blockquote>
<p><b>Effect:</b> Constructs an <b>optional </b>uninitialized.</p>
<p><b>Effect:</b> Constructs an <b>optional</b> uninitialized.</p>
<p><b>Postconditions:</b> <b>*this</b> is <u>uninitialized</u>.</p>
<p><b>Throws:</b> Nothing.</p>
<p><b>Notes:</b></p>
@ -448,9 +507,11 @@ used as the parameter.</p>
</blockquote>
<p><b>Example:</b></p>
<blockquote>
<pre>#include &lt;boost/none.hpp&gt;</pre>
<pre>optional&lt;T&gt; n(none) ;
assert ( !n ) ;</pre>
<pre>
#include &lt;boost/none.hpp&gt;
optional&lt;int&gt; n(boost::none) ;
assert ( !n ) ;
</pre>
</blockquote>
</blockquote>
@ -459,7 +520,6 @@ assert ( !n ) ;</pre>
<pre>optional&lt;T <i>(not a ref)</i>&gt;::optional( T const&amp; v )</pre>
<blockquote>
<p><b>Effect:</b> Directly-Constructs an <b>optional</b>.</p>
<!-- TemplateName: general/sy_footer_inc.isml -->
<p><b>Postconditions:</b> <b>*this</b> is <u>initialized</u> and its value is a <i>copy</i> of 'v'.</p>
<p><b>Throws:</b> Whatever T::T( T const&amp; ) throws.</p>
<p><b>Notes: </b> T::T( T const&amp; ) is called.</p>
@ -468,9 +528,11 @@ in that case, this constructor has no effect.
</p>
<p><b>Example:</b></p>
<blockquote>
<pre>T v;
<pre>
T v;
optional&lt;T&gt; opt(v);
assert ( *opt == v ) ;</pre>
assert ( *opt == v ) ;
</pre>
</blockquote>
</blockquote>
@ -484,17 +546,37 @@ instance of an internal type wrapping the reference 'ref'.</p>
<p><b>Throws:</b> Nothing.</p>
<p><b>Example:</b></p>
<blockquote>
<pre>T v;
<pre>
T v;
T&amp; vref = v ;
optional&lt;T&amp;&gt; opt(vref);
assert ( *opt == v ) ;
++ v ; // mutate referee
assert (*opt == v); </pre>
assert (*opt == v);
</pre>
</blockquote>
</blockquote>
<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>
<blockquote>
<p><b>Effect:</b> Copy-Constructs an <b>optional</b>.</p>
@ -508,7 +590,8 @@ in that case, this constructor has no effect.
</p>
<p><b>Example:</b></p>
<blockquote>
<pre>optional&lt;T&gt; uninit ;
<pre>
optional&lt;T&gt; uninit ;
assert (!uninit);
optional&lt;T&gt; uinit2 ( uninit ) ;
@ -537,7 +620,8 @@ is uninitialized.</p>
reefer to the same object<b> </b>(they alias).</p>
<p><b>Example:</b></p>
<blockquote>
<pre>optional&lt;T&amp;&gt; uninit ;
<pre>
optional&lt;T&amp;&gt; uninit ;
assert (!uninit);
optional&lt;T&amp;&gt; uinit2 ( uninit ) ;
@ -580,7 +664,8 @@ in that case, this constructor has no effect.
<p><b>Example:</b></p>
<blockquote>
<pre>optional&lt;double&gt; x(123.4);
<pre>
optional&lt;double&gt; x(123.4);
assert ( *x == 123.4 ) ;
optional&lt;int&gt; y(x) ;
@ -608,7 +693,8 @@ in that case, this constructor has no effect.
<p><b>Example:</b></p>
<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;);
@ -624,6 +710,27 @@ assert ( *y == v ) ;
<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>
<blockquote>
<p><b>Effect:</b> Assigns the value 'rhs' to an <b>optional</b>.</p>
@ -639,7 +746,8 @@ uninitialized and T's <i>copy constructor</i> fails, <b>*this</b> is left
properly uninitialized]</p>
<p><b>Example:</b></p>
<blockquote>
<pre>T x;
<pre>
T x;
optional&lt;T&gt; def ;
optional&lt;T&gt; opt(x) ;
@ -662,7 +770,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>
<p><b>Example:</b></p>
<blockquote>
<pre>int a = 1 ;
<pre>
int a = 1 ;
int b = 2 ;
T&amp; ra = a ;
T&amp; rb = b ;
@ -792,12 +901,11 @@ assert ( *opt1 == static_cast&lt;U&gt;(v) ) ;
<HR>
<pre>void optional&lt;T&gt;::reset() ;</pre>
<blockquote>
<p><b>Deprecated: </b>Same as operator=( detail::none_t );</p>
<p><b>Deprecated: </b>Same as operator=( none_t n);</p>
</blockquote>
<HR>
<pre>T const&amp; optional&lt;T <i>(not a ref)</i>&gt;::operator*() const ;
T&amp; optional&lt;T<i> (not a ref)</i>&gt;::operator*();</pre>
@ -857,29 +965,66 @@ assert ( *opt == v ) ;</pre>
<HR>
<pre>T const* optional&lt;T <i>(not a ref)</i>&gt;::get_ptr() const ;
T* optional&lt;T <i>(not a ref)</i>&gt;::get_ptr() ;
<pre>T const&amp; optional&lt;T&gt;::get_value_or( T const&amp; default) const ;
T&amp; optional&lt;T&gt;::get_value_or( T&amp; default ) ;
inline T const* get_pointer ( optional&lt;T <i>(not a ref)</i>&gt; const&amp; ) ;
inline T* get_pointer ( optional&lt;T <i>(not a ref)</i>&gt; &amp;) ;
inline T const&amp; get_optional_value_or ( optional&lt;T&gt; const&amp; o, T const&amp; default ) ;
inline T&amp; get_optional_value_or ( optional&lt;T&gt;&amp; o, T&amp; default ) ;
</pre>
<blockquote>
<p><b>Returns:</b> A reference to the contained value (which can be itself a reference), 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* optional&lt;T&gt;::get_ptr() const ;
T* optional&lt;T&gt;::get_ptr() ;
inline T const* get_pointer ( optional&lt;T&gt; const&amp; ) ;
inline T* get_pointer ( optional&lt;T&gt; &amp;) ;
</pre>
<blockquote>
<p><b>Returns:</b> If <b>*this</b> is initialized, a pointer to the contained
value; else 0 (<i>null</i>).
</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
you should not hold nor delete this pointer
you should not hold nor delete this pointer.
</p>
<p><b>Example:</b></p>
<blockquote>
<pre>T v;
optional&lt;T&gt; opt(v);
optional&lt;T&gt; const copt(v);
T* p = opt.get_ptr() ;
T const* cp = copt.get_ptr();
<pre>int v=123;
optional&lt;int&gt; opt(v);
optional&lt;int&gt; const copt(v);
int* p = opt.get_ptr() ;
int const* cp = copt.get_ptr();
assert ( p == get_pointer(opt) );
assert ( cp == get_pointer(copt) ) ;
int& rv = v ;
optional&lt;int&amp;&gt; optr(rv);
*(optr.get_ptr()) = 456 ;
assert ( v == 456 );
</pre>
</blockquote>
</blockquote>
@ -888,13 +1033,14 @@ assert ( cp == get_pointer(copt) ) ;
<HR>
<pre>T const* optional&lt;T <i>(not a ref)</i>&gt;::operator -&gt;() const ;
T* optional&lt;T <i>(not a ref)</i>&gt;::operator -&gt;() ;
<pre>T const* optional&lt;T&gt;::operator -&gt;() const ;
T* optional&lt;T&gt;::operator -&gt;() ;
</pre>
<blockquote>
<p><b>Requirements: *this</b> is initialized.</p>
<p><b>Returns:</b> A pointer to the contained value.</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>Example:</b></p>
<blockquote>
@ -902,6 +1048,14 @@ T* optional&lt;T <i>(not a ref)</i>&gt;::operator -&gt;() ;
X x ;
optional&lt;X&gt; opt (x);
opt-&gt;mdata = 2 ;
X& rx = x ;
optional&lt;X&amp;&gt; optr (rx);
optr-&gt;mdata = 4 ;
assert ( x.mdata = 4 )
</pre>
</blockquote>
</blockquote>
@ -965,18 +1119,47 @@ assert ( opt.is_initialized() );</pre>
<HR>
<pre>optional&lt;T <i>(not a ref)</i>&gt; make_optional( T const&amp; v )</pre>
<blockquote>
<p><b>Returns:</b> optional&lt;T&gt;(v) for the <i>deduced</i> type <code>T</code> of <code>v</code>.</p>
<p><b>Example:</b></p>
<blockquote>
<pre>template&lt;class T&gt; void foo ( optional&lt;T&gt; const& opt ) ;
foo ( make_optional(1+1) ) ; // Creates an optional&lt;int&gt;
</blockquote>
</blockquote>
<HR>
<pre>optional&lt;T <i>(not a ref)</i>&gt; make_optional( bool condition, T const&amp; v )</pre>
<blockquote>
<p><b>Returns:</b> optional&lt;T&gt;(condition,v) for the <i>deduced</i> type <code>T</code> of <code>v</code>.</p>
<p><b>Example:</b></p>
<blockquote>
<pre>optional&lt;double&gt; calculate_foo()
{
double val = compute_foo();
return make_optional(is_not_nan_and_finite(val),val);
}
optional&lt;double&gt; v = calculate_foo();
if ( !v )
error("foo wasn't computed");
</blockquote>
</blockquote>
<HR>
<pre>bool operator == ( optional&lt;T&gt; const&amp x, optional&lt;T&gt const&amp y );</pre>
<blockquote>
<p><b>Returns:</b> If both <b>x</b> and <b>y</b> are initialied, <code>(*x == *y)</code>.
If only x or y is initialized, <code>false</code>. If both are uninitialized, <code>true</code>.
</p>
If only x or y is initialized, <code>false</code>. If both are uninitialized, <code>true</code>. </p>
<p><b>Throws:</b> Nothing.</p>
<p><b>Notes:</b> Pointers have shallow relational operators while <b>optional</b> has
deep relational operators. Do not use operator == directly in generic code
which expect to be given either an optional&lt;T&gt; or a pointer;
use <a href="../../utility/OptionalPointee.html#equal">equal_pointees()</a> instead
</p>
use <a href="../../utility/OptionalPointee.html#equal">equal_pointees()</a> instead </p>
<p><b>Example:</b></p>
<blockquote>
<pre>T x(12);
@ -1012,14 +1195,12 @@ assert ( optX != optZ ) ;
<blockquote>
<p><b>Returns:</b> If <b>y</b> is not initialized, <code>false</code>.
If <b>y</b> is initialized and <b>x</b> is not initialized, <code>true</code>.
If both <b>x</b> and <b>y</b> are initialized, <code>(*x &lt; *y)</code>.
</p>
If both <b>x</b> and <b>y</b> are initialized, <code>(*x &lt; *y)</code>. </p>
<p><b>Throws:</b> Nothing.</p>
<p><b>Notes:</b> Pointers have shallow relational operators while <b>optional</b> has
deep relational operators. Do not use operator &lt; directly in generic code
which expect to be given either an optional&lt;T&gt; or a pointer;
use <a href="../../utility/OptionalPointee.html#less">less_pointees()</a> instead
</p>
use <a href="../../utility/OptionalPointee.html#less">less_pointees()</a> instead </p>
<p><b>Example:</b></p>
<blockquote>
<pre>T x(12);
@ -1077,28 +1258,59 @@ assert ( optX != optZ ) ;
<p><b>Throws:</b> Nothing.</p>
</blockquote>
<HR>
<pre>
bool operator == ( optional&lt;T&gt; const&amp; x, T const&amp; n );
bool operator != ( optional&lt;T&gt; const&amp; x, T const&amp; n );
bool operator &lt; ( optional&lt;T&gt; const&amp; x, T const&amp; n );
bool operator &gt; ( optional&lt;T&gt; const&amp; x, T const&amp; n );
bool operator &lt;= ( optional&lt;T&gt; const&amp; x, T const&amp; n );
bool operator &gt;= ( optional&lt;T&gt; const&amp; x, T const&amp; n );
bool operator == ( T const&amp; n, optional&lt;T&gt; const&amp; y );
bool operator != ( T const&amp; n, optional&lt;T&gt; const&amp; y );
bool operator &lt; ( T const&amp; n, optional&lt;T&gt; const&amp; y );
bool operator &gt; ( T const&amp; n, optional&lt;T&gt; const&amp; y );
bool operator &lt;= ( T const&amp; n, optional&lt;T&gt; const&amp; y );
bool operator &gt;= ( T const&amp; 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;(n).</p>
</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>
<pre>void swap ( optional&lt;T&gt;&amp x, optional&lt;T&gt&amp y );</pre>
<blockquote>
<p><b>Effect:</b> If both <b>x</b> and <b>y</b> are initialized, calls <code>swap(*x,*y)</code>
using std::swap.<br>
If only one is initialized, say x, calls: <code>y.reset(*x); x.reset();</code><br>
If none is initialized, does nothing.
</p>
<p><b>Effect:</b> If both <b>x</b> and <b>y</b> are initialized, calls <code>swap(*x,*y)</code> using std::swap.<br>
If only one is initialized, say x, calls: <code>y = *x; x = boost:none;</code><br>
If none is initialized, does nothing. </p>
<p><b>Postconditions:</b> The states of x and y interchanged.</p>
<p><b>Throws:</b> If both are initialized, whatever swap(T&amp;,T&amp;) throws.
If only one is initialized, whatever T::T ( T const&amp; ) throws.
</p>
<p><b>Notes:</b> If both are initialized, swap(T&amp;,T&amp;) is used <i>unqualified</i>
but with std::swap introduced in scope.<br>
If only one is initialized, T::~T() and T::T( T const& ) is called.
</p>
If only one is initialized, whatever T::T ( T const&amp; ) throws. </p>
<p><b>Notes:</b> If both are initialized, swap(T&amp;,T&amp;) is used <i>unqualified</i> but with std::swap introduced in scope.<br>
If only one is initialized, T::~T() and T::T( T const& ) is called. </p>
<p><b>Exception Safety:</b> If both are initialized, this operation has the exception
safety guarantees of swap(T&,T&).<br>
If only one is initialized, it has the same <b>basic</b> guarantee as optional&lt;T&gt;::reset( T const& ).
</p>
If only one is initialized, it has the same <b>basic</b> guarantee as optional&lt;T&gt;::operator=( T const& ). </p>
<p><b>Example:</b></p>
<blockquote>
<pre>T x(12);
@ -1148,12 +1360,12 @@ void receive_async_message()
<pre>optional&lt;string&gt; name ;
if ( database.open() )
{
&nbsp; name.reset ( database.lookup(employer_name) ) ;
&nbsp; name = database.lookup(employer_name) ;
}
else
{
&nbsp; if ( can_ask_user )
&nbsp;&nbsp;&nbsp; name.reset ( user.ask(employer_name) ) ;
&nbsp;&nbsp;&nbsp; name = user.ask(employer_name) ;
}
if ( name )
@ -1174,7 +1386,7 @@ else print(&quot;employer's name not found!&quot;);
&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; 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; void draw ( canvas& cvs )
@ -1218,16 +1430,17 @@ some operations are not available in this case:</p>
<li>Converting assignment</li>
<li>InPlace construction</li>
<li>InPlace assignment</li>
<li>Value-access via pointer</li>
</ul>
<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, thus aliasing can ocurr: </p>
<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>
<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 a pointer to the reference itself.</li>
</ul>
<HR>
@ -1238,7 +1451,7 @@ Clearly, there is no other choice.</p>
<pre>int x = 1 ;
int&amp; rx = x ;
optional&lt;int&amp;&gt; ora ;
optional&lt;int&amp;&gt; orb(x) ;
optional&lt;int&amp;&gt; orb(rx) ;
ora = orb ; // now 'ora'&nbsp;is bound to 'x' through 'rx'
*ora = 2 ; // Changes value of 'x' through 'ora'
assert(x==2);
@ -1249,13 +1462,12 @@ referenced object; it's value changes but the reference is never rebound.</p>
int&amp; ra = a ;
int b = 2 ;
int&amp; rb = b ;
ra = rb ; // Changes the value of 'a' to 'b'
ra = rb ; // Changes the VALUE of 'a' to that of '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&lt;T&amp;&gt;, the effect is to <b>
rebind</b> to the new object instead of assigning the referee. This is unlike
<p>Now, if you assign to an <i>initialized</i> optional&lt;T&amp;&gt;, the effect is to <b>rebind</b> to the new object instead of assigning the referee. This is unlike
bare C++ references.</p>
<pre>int a = 1 ;
int b = 2 ;
@ -1276,38 +1488,68 @@ C++ references.<br>
It is true that optional&lt;U&gt; strives to behave as much as possible as U does
whenever it is initialized; but in the case when U is T&amp;, doing so would result
in inconsistent behavior w.r.t to the lvalue initialization state.</p>
<p>Imagine optional&lt;T&amp;&gt; forwarding assignment to the referenced object (thus
changing the referenced object value but not rebinding), and consider the
following code :</p>
<pre>&nbsp; optional&lt;int&amp;&gt; a = get();
&nbsp; int x = 1 ;
&nbsp; int&amp; rx = x ;
&nbsp; optional&lt;int&amp;&gt; b(rx);
&nbsp; a = b ;
<p>Consider the following code :</p>
<pre>
int x = 1 ;
int& rx = x ;
void foo ( optional&lt;int&amp;&gt; & outer )
{
optional&lt;int&amp;&gt; b(rx);
outer = b ;
}
</pre>
<p>What should the assignment to 'outer' do?<br>
If 'outer' is <i>uninitialized</i>, the answer is clear: it should bind to 'x' (so we now have
a second reference to 'x').<br>
But what if 'outer' is already <i>initialized?</i><br>
The assignment could change the value of the
referenced object (whatever that is), but doing that would be inconsistent with the uninitialized case
and then you wouldn't be able to reason at compile time about all the references to x since
the appearance of a new reference to it would depend on wheter the lvalue ('outer')
is initialized or not.</p>
<p>Arguably, if rebinding the reference to another object is wrong for your code, then is
likely that binding it for the fist time via assignment instead of intialization is also wrong.
In that case, you can always just assign the value to the referenced object directly via
the access operator <code>*opt=value</code>.</p>
<p>If rebinding is wrong but first-time binding
isn't (via assignment), you can always work around the rebinding semantics using a discriminator:</p>
<pre>
if ( !opt )
opt = value ; // first-time binding
else *opt = value ; // assign to referee without rebinding
</pre>
<HR>
<H2><A NAME="none">none_t and none</A></H2>
<p>optional&lt;T&gt; supports uninitialized states with a convenient syntax via a constant of
the <i>implementation-defined</i> type <code>boost::none_t</code>, identified as <code>boost::none</code>.</p>
<p>Starting with Boost version 1.34.0, both <code>boost::none_t</code> and <code>boost::none</code> are
included in <code>boost/none.hpp</code>, which is automatically included by <code>boost/optional/optional.hpp</code>
</p>
<p>This contant is similar in purpose to NULL, except that is not a <i>null pointer value</i>. You can use it to initialize
an optional&lt;T&gt; instance, which has the same effect of a default constructor, and you can assign it which has the
effect of reseting the optional&lt;T&gt; instance. You can also use it in relational operators to make the predicate expression
more clear.</p>
<p>Here are some typical examples:</p>
<pre>
#include "boost/optional/optional.hpp" // boost/none.hpp is included automatically
boost::optional&lt;int&gt; foo ( int a )
{
return some_condition(a) ? boost::make_optional(a) : boost::none ;
// NOTE: in real code you can just use this: make_optional(some_condition(a), a )
}
boost::optional&lt;int&gt; opt = boost::none ;
if ( opt == boost::none )
opt = foo(123);
opt = boost::none ;
</pre>
<p>What does the assignment do?<br>
If 'a' is <i>uninitialized</i>, the answer is clear: it binds to 'x' (we now have
another reference to 'x').<br>
But what if 'a' is already <i>initialized? </i>it would change the value of the
referenced object (whatever that is); which is inconsistent with the other
possible case.</p>
<p>If optional&lt;T&amp;&gt; would assign just like T&amp; does, you would never be able to
use Optional's assignment without explicitly handling the previous
initialization state unless your code is capable of functioning whether after
the assignment, 'a'
aliases the same object as 'b' or not.</p>
<p>That is, you would have to discriminate in order to be consistency.<br>
<br>
If in your code rebinding to another object is not an option, then is very
likely that binding for the fist time isn't either. In such case, assignment to
an <i>uninitialized</i> optional&lt;T&amp;&gt; 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>
@ -1358,8 +1600,7 @@ public:
</pre>
<p>A limitation of this method is that it doesn't scale well to wrapped objects with multiple
constructors nor to generic code were the constructor overloads are unknown.</p>
<p>The solution presented in this library is the family of <b>InPlaceFactories</b> and
<b>TypedInPlaceFactories</b>.<br>
<p>The solution presented in this library is the family of <b>InPlaceFactories</b> and <b>TypedInPlaceFactories</b>.<br>
These factories are a family of classes which encapsulate an increasing number of arbitrary
constructor parameters and supply a method to construct an object of a given type using those
parameters at an address specified by the user via placement new.</p>
@ -1427,10 +1668,7 @@ public:
W ( in_place(123,"hello") ) ;
}
</pre>
<p>The factories are implemented in the headers:
<a href="../../../boost/utility/in_place_factory.hpp">in_place_factory.hpp</a> and
<a href="../../../boost/utility/typed_in_place_factory.hpp">typed_in_place_factory.hpp</a>
</p>
<p>The factories are implemented in the headers: <a href="../../../boost/utility/in_place_factory.hpp">in_place_factory.hpp</a> and <a href="../../../boost/utility/typed_in_place_factory.hpp">typed_in_place_factory.hpp</a> </p>
<HR>
@ -1440,9 +1678,8 @@ public:
the <i>maybe</i> state <u>represents a valid value</u>, unlike the corresponding state
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>
<p>Second, optional&lt;&gt; provides an implicit conversion to bool. This conversion
refers to the initialization state and not to the contained value.<br>
Using optional&lt;bool&gt; can lead to subtle errors due to the implicit bool conversion:</p>
<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>
Using optional&lt;bool&gt; can lead to subtle errors due to this implicit conversion:</p>
<pre>void foo ( bool v ) ;
void bar()
{
@ -1458,7 +1695,9 @@ void bar()
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>
<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
of the assignment methods:</p>
<ul>
@ -1471,61 +1710,17 @@ of the assignment methods:</p>
InPlaceFactory const&amp; ) </code></li>
<li> <code>template&lt;class TypedInPlaceFactory&gt; optional&lt;T&gt;::operator= (
TypedInPlaceFactory const&amp; ) </code></li>
<li> <code>optional&lt;T&gt;:::reset ( T const&amp;)</code></li>
</ul>
<p>Can only <i>guarantee</i> the <u>basic exception safety</u>: The lvalue optional is left <u>uninitialized</u>
if an exception is thrown (any previous value is <i>first</i> destroyed using T::~T())</p>
<p>cannot offer any <i>exception safety guarantee</i> beyond that provided by <code>T::operator=( T const&amp; )</code></p>
<p>On the other hand, the <i>uninitializing</i> methods:</p>
<ul>
<li><code>optional&lt;T&gt;::operator= ( detail::none_t ) </code></li>
<li><code>optional&lt;T&gt;::reset()</code></li>
</ul>
<p>Provide the no-throw guarantee (assuming a no-throw T::~T())</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 ;
<p>Provides the no-throw guarantee (assuming a no-throw T::~T()) becuse it only destroys the stored object.</p>
&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>
<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>
<HR>
@ -1539,14 +1734,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>
<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).
It uses a separate boolean flag to indicate the initialization state.<br>
Placement new with T's copy constructor and T's destructor
are explicitly used to initialize,copy and destroy optional values.<br>
As a result, T's default constructor is effectively by-passed, but the exception
guarantees are basic.<br>
It is planned to replace the current implementation with another with
stronger exception safety, such as a future boost::variant<T,nil_t>. </p>
using a custom aligned storage facility built from <code>alignment_of</code> and <code>type_with_alignment</code> (both from Type Traits).
It uses a separate boolean flag to indicate the initialization state.</p>
<p>Placement new with T's copy constructor and T's destructor
is explicitly used to initialize and destroy optional values. This allows T's default constructor to be effectively by-passed.</p>
<p>If assignment is used and the lvalue optional is uninitialized, T's copy constructor is used. However, if it is already initialized, T's assignment operator is used. This prevents optional from offering any exception guarantee stronger than the one offered by the type T itself</p>
<HR>
@ -1600,15 +1792,12 @@ T <u>is not</u> required to be <a href="http://www.sgi.com/tech/stl/DefaultConst
</blockquote>
<HR>
<P>Revised April 21, 2005</P>
<p><EFBFBD> Copyright Fernando Luis Cacciola Carballal, 2003,2004,2005</p>
<P>Revised March 27, 2007</P>
<p><EFBFBD> Copyright Fernando Luis Cacciola Carballal, 2003-2007</p>
<p> Use, modification, and distribution are subject to the Boost Software
License, Version 1.0. (See accompanying file <a href="../../../LICENSE_1_0.txt">
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
www.boost.org/LICENSE_1_0.txt</a>)</p>
License, Version 1.0. (See accompanying file <a href="../../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a>)</p>
<P>Developed by <A HREF="mailto:fernando_cacciola@hotmail.com">Fernando Cacciola</A>,
the latest version of this file can be found at <A
HREF="http://www.boost.org">www.boost.org</A>, and the boost
<A HREF="http://www.boost.org/more/mailing_lists.htm#main">discussion lists</A></P>
</BODY>
HREF="http://www.boost.org">www.boost.org</A>, and the boost <A HREF="http://www.boost.org/more/mailing_lists.htm#main">discussion lists</A></P>
</pre></BODY>
</HTML>

View File

@ -1,31 +1,43 @@
// Copyright (C) 2003, Fernando Luis Cacciola Carballal.
// Copyright (C) 2007, Anthony Williams
// Copyright (C) 2007, Steven Watanabe, Richard Smith
//
// Use, modification, and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// Distributed under 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.
// See http://www.boost.org/lib/optional/ for documentation.
//
// You are welcome to contact the author at:
// fernando_cacciola@hotmail.com
// fernando.cacciola@gmail.com
//
#ifndef BOOST_NONE_17SEP2003_HPP
#define BOOST_NONE_17SEP2003_HPP
#include "boost/none_t.hpp"
namespace boost
{
namespace detail
{
class none_helper;
}
// NOTE: Borland users have to include this header outside any precompiled headers
// (bcc<=5.64 cannot include instance data in a precompiled header)
inline void none(detail::none_helper);
namespace boost {
namespace detail
{
class none_helper
{
private:
none_helper( none_helper const& ) {}
friend void boost::none(none_helper);
};
}
namespace {
none_t const none = ((none_t)0) ;
typedef void (*none_t)(detail::none_helper);
inline void none(detail::none_helper) {}
}
} // namespace boost
#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/not.hpp"
#include "boost/detail/reference_content.hpp"
#include "boost/none_t.hpp"
#include "boost/none.hpp"
#include "boost/utility/compare_pointees.hpp"
#include "boost/optional/optional_fwd.hpp"
@ -76,6 +76,19 @@
#define BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION
#endif
// Daniel Wallin discovered that bind/apply.hpp badly interacts with the apply<>
// member template of a factory as used in the optional<> implementation.
// He proposed this simple fix which is to move the call to apply<> outside
// namespace boost.
namespace boost_optional_detail
{
template <class T, class Factory>
void construct(Factory const& factory, void* address)
{
factory.BOOST_NESTED_TEMPLATE apply<T>(address);
}
}
namespace boost {
@ -133,7 +146,11 @@ class optional_base : public optional_tag
{
private :
typedef BOOST_DEDUCED_TYPENAME detail::make_reference_content<T>::type internal_type ;
typedef
#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
BOOST_DEDUCED_TYPENAME
#endif
::boost::detail::make_reference_content<T>::type internal_type ;
typedef aligned_storage<internal_type> storage_type ;
@ -169,7 +186,7 @@ class optional_base : public optional_tag
// Creates an optional<T> uninitialized.
// No-throw
optional_base ( none_t const& )
optional_base ( none_t )
:
m_initialized(false) {}
@ -181,6 +198,16 @@ class optional_base : public optional_tag
{
construct(val);
}
// Creates an optional<T> initialized with 'val' IFF cond is true, otherwise creates an uninitialzed optional<T>.
// Can throw if T::T(T const&) does
optional_base ( bool cond, argument_type val )
:
m_initialized(false)
{
if ( cond )
construct(val);
}
// Creates a deep copy of another optional<T>
// Can throw if T::T(T const&) does
@ -252,7 +279,7 @@ class optional_base : public optional_tag
// Assigns from "none", destroying the current value, if any, leaving this UNINITIALIZED
// 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
template<class Expr>
@ -295,7 +322,7 @@ class optional_base : public optional_tag
void construct ( Expr const& factory, in_place_factory_base const* )
{
BOOST_STATIC_ASSERT ( ::boost::mpl::not_<is_reference_predicate>::value ) ;
factory.BOOST_NESTED_TEMPLATE apply<value_type>(m_storage.address()) ;
boost_optional_detail::construct<value_type>(factory, m_storage.address());
m_initialized = true ;
}
@ -414,6 +441,8 @@ class optional_base : public optional_tag
// the following olverloads are used to filter out the case and guarantee an error in case of T being a reference.
pointer_const_type cast_ptr( internal_type const* p, is_not_reference_tag ) const { return p ; }
pointer_type cast_ptr( internal_type * p, is_not_reference_tag ) { return p ; }
pointer_const_type cast_ptr( internal_type const* p, is_reference_tag ) const { return &p->get() ; }
pointer_type cast_ptr( internal_type * p, is_reference_tag ) { return &p->get() ; }
bool m_initialized ;
storage_type m_storage ;
@ -445,12 +474,15 @@ class optional : public optional_detail::optional_base<T>
// Creates an optional<T> uninitialized.
// No-throw
optional( none_t const& none_ ) : base(none_) {}
optional( none_t none_ ) : base(none_) {}
// Creates an optional<T> initialized with 'val'.
// Can throw if T::T(T const&) does
optional ( argument_type val ) : base(val) {}
// Creates an optional<T> initialized with 'val' IFF cond is true, otherwise creates an uninitialized optional.
// Can throw if T::T(T const&) does
optional ( bool cond, argument_type val ) : base(cond,val) {}
#ifndef BOOST_OPTIONAL_NO_CONVERTING_COPY_CTOR
// NOTE: MSVC needs templated versions first
@ -533,7 +565,7 @@ class optional : public optional_detail::optional_base<T>
// Assigns from a "none"
// Which destroys the current value, if any, leaving this UNINITIALIZED
// No-throw (assuming T::~T() doesn't)
optional& operator= ( none_t const& none_ )
optional& operator= ( none_t none_ )
{
this->assign( none_ ) ;
return *this ;
@ -545,6 +577,10 @@ class optional : public optional_detail::optional_base<T>
reference_const_type get() const { BOOST_ASSERT(this->is_initialized()) ; return this->get_impl(); }
reference_type get() { BOOST_ASSERT(this->is_initialized()) ; return this->get_impl(); }
// Returns a copy of the value if this is initialized, 'v' otherwise
reference_const_type get_value_or ( reference_const_type v ) const { return this->is_initialized() ? get() : v ; }
reference_type get_value_or ( reference_type v ) { return this->is_initialized() ? get() : v ; }
// Returns a pointer to the value if this is initialized, otherwise,
// the behaviour is UNDEFINED
// No-throw
@ -566,6 +602,22 @@ class optional : public optional_detail::optional_base<T>
bool operator!() const { return !this->is_initialized() ; }
} ;
// Returns optional<T>(v)
template<class T>
inline
optional<T> make_optional ( T const& v )
{
return optional<T>(v);
}
// Returns optional<T>(cond,v)
template<class T>
inline
optional<T> make_optional ( bool cond, T const& v )
{
return optional<T>(cond,v);
}
// Returns a reference to the value if this is initialized, otherwise, the behaviour is UNDEFINED.
// No-throw
template<class T>
@ -602,6 +654,24 @@ get ( optional<T>* opt )
return opt->get_ptr() ;
}
// Returns a reference to the value if this is initialized, otherwise, the behaviour is UNDEFINED.
// No-throw
template<class T>
inline
BOOST_DEDUCED_TYPENAME optional<T>::reference_const_type
get_optional_value_or ( optional<T> const& opt, BOOST_DEDUCED_TYPENAME optional<T>::reference_const_type v )
{
return opt.get_value_or(v) ;
}
template<class T>
inline
BOOST_DEDUCED_TYPENAME optional<T>::reference_type
get_optional_value_or ( optional<T>& opt, BOOST_DEDUCED_TYPENAME optional<T>::reference_type v )
{
return opt.get_value_or(v) ;
}
// Returns a pointer to the value if this is initialized, otherwise, returns NULL.
// No-throw
template<class T>
@ -623,6 +693,11 @@ get_pointer ( optional<T>& opt )
// optional's relational operators ( ==, !=, <, >, <=, >= ) have deep-semantics (compare values).
// WARNING: This is UNLIKE pointers. Use equal_pointees()/less_pointess() in generic code instead.
//
// optional<T> vs optional<T> cases
//
template<class T>
inline
bool operator == ( optional<T> const& x, optional<T> const& y )
@ -653,64 +728,141 @@ inline
bool operator >= ( optional<T> const& x, optional<T> const& y )
{ return !( x < y ) ; }
//
// optional<T> vs T cases
//
template<class T>
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>() ); }
template<class T>
inline
bool operator < ( optional<T> const& x, none_t const& )
bool operator < ( optional<T> const& x, none_t )
{ return less_pointees(x,optional<T>() ); }
template<class T>
inline
bool operator != ( optional<T> const& x, none_t const& y )
bool operator != ( optional<T> const& x, none_t y )
{ return !( x == y ) ; }
template<class T>
inline
bool operator > ( optional<T> const& x, none_t const& y )
bool operator > ( optional<T> const& x, none_t y )
{ return y < x ; }
template<class T>
inline
bool operator <= ( optional<T> const& x, none_t const& y )
bool operator <= ( optional<T> const& x, none_t y )
{ return !( y < x ) ; }
template<class T>
inline
bool operator >= ( optional<T> const& x, none_t const& y )
bool operator >= ( optional<T> const& x, none_t y )
{ return !( x < y ) ; }
//
// none vs optional<T> cases
//
template<class T>
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); }
template<class T>
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); }
template<class T>
inline
bool operator != ( none_t const& x, optional<T> const& y )
bool operator != ( none_t x, optional<T> const& y )
{ return !( x == y ) ; }
template<class T>
inline
bool operator > ( none_t const& x, optional<T> const& y )
bool operator > ( none_t x, optional<T> const& y )
{ return y < x ; }
template<class T>
inline
bool operator <= ( none_t const& x, optional<T> const& y )
bool operator <= ( none_t x, optional<T> const& y )
{ return !( y < x ) ; }
template<class T>
inline
bool operator >= ( none_t const& x, optional<T> const& y )
bool operator >= ( none_t x, optional<T> const& y )
{ return !( x < y ) ; }
//
@ -763,10 +915,6 @@ template<class T> inline void swap ( optional<T>& x, optional<T>& y )
optional_detail::optional_swap(x,y);
}
template<class T> inline optional<T> make_optional ( T const& v )
{
return optional<T>(v);
}
} // namespace boost

View File

@ -4,6 +4,10 @@
</head>
<body>
Automatic redirection failed, please go to
<a href="doc/optional.html">doc/optional.html</a>.
<a href="doc/optional.html">doc/optional.html</a>.&nbsp;<hr>
<p><EFBFBD> Copyright Beman Dawes, 2001</p>
<p>Distributed under the Boost Software License, Version 1.0. (See accompanying
file <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or copy
at <a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a>)</p>
</body>
</html>

View File

@ -1,37 +0,0 @@
# Boost.Optional Library test Jamfile
#
# 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)
#
subproject libs/optional/test ;
# bring in rules for testing
SEARCH on testing.jam = $(BOOST_BUILD_PATH) ;
include testing.jam ;
# Make tests run by default.
DEPENDS all : test ;
{
test-suite optional :
[ run optional_test.cpp ]
[ run optional_test_tie.cpp ]
[ run optional_test_ref.cpp ]
[ run optional_test_inplace.cpp ]
[ run optional_test_io.cpp ]
[ compile-fail optional_test_fail1.cpp ]
[ compile-fail optional_test_fail2.cpp ]
[ compile-fail optional_test_fail3a.cpp ]
[ compile-fail optional_test_fail3b.cpp ]
[ compile-fail optional_test_ref_fail1.cpp ]
[ compile-fail optional_test_ref_fail2.cpp ]
[ compile-fail optional_test_ref_fail3.cpp ]
[ compile-fail optional_test_ref_fail4.cpp ]
[ compile-fail optional_test_inplace_fail.cpp ]
[ compile-fail optional_test_inplace_fail2.cpp ]
;
}

View File

@ -22,11 +22,9 @@ import testing ;
[ run optional_test_inplace.cpp ]
[ run optional_test_io.cpp ]
[ compile-fail optional_test_fail1.cpp ]
[ compile-fail optional_test_fail2.cpp ]
[ compile-fail optional_test_fail3a.cpp ]
[ compile-fail optional_test_fail3b.cpp ]
[ compile-fail optional_test_ref_fail1.cpp ]
[ compile-fail optional_test_ref_fail2.cpp ]
[ compile-fail optional_test_ref_fail3.cpp ]
[ compile-fail optional_test_ref_fail4.cpp ]
[ compile-fail optional_test_inplace_fail.cpp ]

View File

@ -15,7 +15,9 @@
#define BOOST_ENABLE_ASSERT_HANDLER
#include "boost/optional.hpp"
#include "boost/bind/apply.hpp" // Included just to test proper interaction with boost::apply<> as reported by Daniel Wallin
#include "boost/optional/optional.hpp"
#ifdef __BORLANDC__
#pragma hdrstop
@ -151,6 +153,95 @@ void test_basics( T const* )
ob.reset();
check_is_pending_dtor( ARG(T) ) ;
check_uninitialized(ob);
}
template<class T>
void test_conditional_ctor_and_get_valur_or ( T const* )
{
TRACE( std::endl << BOOST_CURRENT_FUNCTION );
T a(321);
T z(123);
optional<T> const cdef0(false,a);
optional<T> def0(false,a);
optional<T> def1 = boost::make_optional(false,a); // T is not within boost so ADL won't find make_optional unqualified
check_uninitialized(def0);
check_uninitialized(def1);
optional<T> const co0(true,a);
optional<T> o0(true,a);
optional<T> o1 = boost::make_optional(true,a); // T is not within boost so ADL won't find make_optional unqualified
check_initialized(o0);
check_initialized(o1);
check_value(o0,a,z);
check_value(o1,a,z);
T b = def0.get_value_or(z);
BOOST_CHECK( b == z ) ;
b = get_optional_value_or(def0,z);
BOOST_CHECK( b == z ) ;
b = o0.get_value_or(z);
BOOST_CHECK( b == a ) ;
b = get_optional_value_or(o0,z);
BOOST_CHECK( b == a ) ;
T const& crz = z ;
T& rz = z ;
T const& crzz = def0.get_value_or(crz);
BOOST_CHECK( crzz == crz ) ;
T& rzz = def0.get_value_or(rz);
BOOST_CHECK( rzz == rz ) ;
T const& crzzz = get_optional_value_or(cdef0,crz);
BOOST_CHECK( crzzz == crz ) ;
T& rzzz = get_optional_value_or(def0,rz);
BOOST_CHECK( rzzz == rz ) ;
T const& crb = o0.get_value_or(crz);
BOOST_CHECK( crb == a ) ;
T& rb = o0.get_value_or(rz);
BOOST_CHECK( rb == b ) ;
T const& crbb = get_optional_value_or(co0,crz);
BOOST_CHECK( crbb == b ) ;
T const& crbbb = get_optional_value_or(o0,crz);
BOOST_CHECK( crbbb == b ) ;
T& rbb = get_optional_value_or(o0,rz);
BOOST_CHECK( rbb == b ) ;
T& ra = a ;
optional<T&> defref(false,ra);
BOOST_CHECK(!defref);
optional<T&> ref(true,ra);
BOOST_CHECK(!!ref);
a = T(432);
BOOST_CHECK( *ref == a ) ;
T& r1 = defref.get_value_or(z);
BOOST_CHECK( r1 == z ) ;
T& r2 = ref.get_value_or(z);
BOOST_CHECK( r2 == a ) ;
}
//
@ -613,16 +704,16 @@ void test_relops( T const* )
{
TRACE( std::endl << BOOST_CURRENT_FUNCTION );
T v0(18);
T v1(19);
T v2(19);
T v0(0);
T v1(1);
T v2(1);
optional<T> def0 ;
optional<T> def1 ;
optional<T> opt0(v0);
optional<T> opt1(v1);
optional<T> opt2(v2);
// Check identity
BOOST_CHECK ( def0 == def0 ) ;
BOOST_CHECK ( opt0 == opt0 ) ;
@ -660,6 +751,33 @@ void test_relops( T const* )
BOOST_CHECK ( opt1 > opt0 ) ;
BOOST_CHECK ( opt1 <= opt2 ) ;
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>
@ -676,6 +794,10 @@ void test_none( T const* )
BOOST_CHECK ( def0 == none ) ;
BOOST_CHECK ( non_def != none ) ;
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 ;
BOOST_CHECK ( !non_def ) ;
@ -683,11 +805,30 @@ void test_none( T const* )
test_default_implicit_construction(T(1),none);
}
template<class T>
void test_arrow( T const* )
{
TRACE( std::endl << BOOST_CURRENT_FUNCTION );
T a(1234);
optional<T> oa(a) ;
optional<T> const coa(a) ;
BOOST_CHECK ( coa->V() == 1234 ) ;
oa->V() = 4321 ;
BOOST_CHECK ( a.V() = 1234 ) ;
BOOST_CHECK ( (*oa).V() = 4321 ) ;
}
void test_with_builtin_types()
{
TRACE( std::endl << BOOST_CURRENT_FUNCTION );
test_basics( ARG(double) );
test_conditional_ctor_and_get_valur_or( ARG(double) );
test_uninitialized_access( ARG(double) );
test_no_throwing_swap( ARG(double) );
test_relops( ARG(double) ) ;
@ -699,6 +840,7 @@ void test_with_class_type()
TRACE( std::endl << BOOST_CURRENT_FUNCTION );
test_basics( ARG(X) );
test_conditional_ctor_and_get_valur_or( ARG(X) );
test_direct_value_manip( ARG(X) );
test_uninitialized_access( ARG(X) );
test_throwing_direct_init( ARG(X) );
@ -711,6 +853,7 @@ void test_with_class_type()
test_throwing_swap( ARG(X) );
test_relops( ARG(X) ) ;
test_none( ARG(X) ) ;
test_arrow( ARG(X) ) ;
BOOST_CHECK ( X::count == 0 ) ;
}

View File

@ -299,6 +299,23 @@ void test_none( T const* )
BOOST_CHECK ( !non_def ) ;
}
template<class T>
void test_arrow( T const* )
{
TRACE( std::endl << BOOST_CURRENT_FUNCTION );
T a(1234);
optional<T&> oa(a) ;
optional<T&> const coa(a) ;
BOOST_CHECK ( coa->V() == 1234 ) ;
oa->V() = 4321 ;
BOOST_CHECK ( a.V() = 4321 ) ;
}
void test_with_builtin_types()
{
TRACE( std::endl << BOOST_CURRENT_FUNCTION );
@ -315,6 +332,7 @@ void test_with_class_type()
test_basics( ARG(X) );
test_relops( ARG(X) ) ;
test_none ( ARG(X) ) ;
test_arrow ( ARG(X) ) ;
BOOST_CHECK ( X::count == 0 ) ;
}

View File

@ -1,23 +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
//
#include "boost/optional.hpp"
//
// THIS TEST SHOULD FAIL TO COMPILE
//
void optional_reference__test_no_ptr_access()
{
boost::optional<int&> opt ;
opt.get_ptr();
}