Compare commits

..

11 Commits

Author SHA1 Message Date
bf1efe99e0 This commit was manufactured by cvs2svn to create tag
'Version_1_32_0'.

[SVN r26264]
2004-11-19 19:19:18 +00:00
9dfbbef796 This commit was manufactured by cvs2svn to create branch 'RC_1_32_0'.
[SVN r25797]
2004-10-20 08:26:43 +00:00
d61baf2a94 bad links fixed
added myself to people


[SVN r25610]
2004-10-07 16:01:24 +00:00
1412c04b24 c++boost.gif -> boost.png replacement
[SVN r25573]
2004-10-05 15:45:52 +00:00
24c5f92413 In-place factories moved from /detail to /utility
New value_initalized tests added


[SVN r25436]
2004-09-27 12:28:21 +00:00
07a80c1b9b In-place factories moved from /detail to /utility
New value_initalized tests added


[SVN r25313]
2004-09-21 14:54:32 +00:00
7717a785de Fix some typos
[SVN r23844]
2004-07-20 14:42:19 +00:00
3db413cc30 Pseudo-destructor fixed (fix adjusted for BCB6)
[SVN r23632]
2004-07-16 14:42:25 +00:00
46fafdb7c9 Fix outdated reference to boost/detail/none.hpp, to current boost/none.hpp.
[SVN r23439]
2004-07-11 16:40:21 +00:00
9aa4943b7a Pseudo-destructor fixed
[SVN r23393]
2004-07-07 15:13:25 +00:00
7cacecb6f9 Pseudo-destructor fixed
[SVN r23392]
2004-07-07 15:04:52 +00:00
14 changed files with 900 additions and 1015 deletions

View File

@ -9,8 +9,8 @@
</HEAD>
<BODY BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#0000FF" VLINK="#800080">
<H2><IMG SRC="../../../c++boost.gif" WIDTH="276" HEIGHT="86">Header &lt;<A
HREF="../../../boost/optional.hpp">boost/optional.hpp</A>&gt; </H2>
<H2><IMG SRC="../../../boost.png" WIDTH="276" HEIGHT="86">Header &lt;<A
HREF="../../../boost/optional/optional.hpp">boost/optional/optional.hpp</A>&gt; </H2>
<H2>Contents</H2>
<DL CLASS="page-index">
@ -33,28 +33,28 @@ HREF="../../../boost/optional.hpp">boost/optional.hpp</A>&gt; </H2>
<H2><A NAME="mot"></A>Motivation</H2>
<P>Consider these functions which should return a value but which might not have
<P>Consider these functions which should return a value but which might not have
a value to return:</P>
<pre>(A) double sqrt(double n );
(B) char get_async_input();
(C) point polygon::get_any_point_effectively_inside();</pre>
<P>There are different approaches to the issue of not having a value to return.</P>
<P>A typical approach is to consider the existence of a valid return value as
a postcondition, so that if the function cannot compute the value to return,
it has either undefined behavior (and can use asssert in a debug build)
or uses a runtime check and throws an exception if the postcondition is violated.
This is a reasonable choice for example, for function (A), because the
lack of a proper return value is directly related to an invalid parameter (out
of domain argument), so it is appropriate to require the callee to supply only
<P>A typical approach is to consider the existence of a valid return value as
a postcondition, so that if the function cannot compute the value to return,
it has either undefined behavior (and can use asssert in a debug build)
or uses a runtime check and throws an exception if the postcondition is violated.
This is a reasonable choice for example, for function (A), because the
lack of a proper return value is directly related to an invalid parameter (out
of domain argument), so it is appropriate to require the callee to supply only
parameters in a valid domain for execution to continue normally.</P>
<P>However, function (B), because of its asynchronous nature, does not fail just
<P>However, function (B), because of its asynchronous nature, does not fail just
because it can't find a value to return; so it is incorrect to consider
such a situation an error and assert or throw an exception. This function must
return, and somehow, must tell the callee that it is not returning a meaningful
such a situation an error and assert or throw an exception. This function must
return, and somehow, must tell the callee that it is not returning a meaningful
value.</P>
<P>A similar situation occurs with function (C): it is conceptually an error to
ask a <i>null-area</i> polygon to return a point inside itself, but in many
applications, it is just impractical for performance reasons to treat this as
<P>A similar situation occurs with function (C): it is conceptually an error to
ask a <i>null-area</i> polygon to return a point inside itself, but in many
applications, it is just impractical for performance reasons to treat this as
an error (because detecting that the polygon has no area might be too expensive
to be required to be tested previously), and either an arbitrary point (typically
at infinity) is returned, or some efficient way to tell the callee that there
@ -106,7 +106,7 @@ if ( p.second )
when a variable is declared as optional&lt;T&gt; and no initial value is given,
the variable is formally uninitialized. A formally uninitialized optional object has conceptually
no value at all and this situation can be tested at runtime. It is formally <i>undefined behaviour</i>
to try to access the value of an uninitialized optional. An uninitialized optional can be <i>assigned</i> a value, in which case its initialization state changes to initialized. Furthermore, given the formal
to try to access the value of an uninitialized optional. An uninitialized optional can be <i>assigned</i> a value, in which case its initialization state changes to initialized. Furthermore, given the formal
treatment of initialization states in optional objects, it is even possible to reset an optional to <i>uninitialized</i>.</P>
<P>In C++ there is no formal notion of uninitialized objects, which
means that objects always have an initial value even if indeterminate.<br>
@ -114,8 +114,8 @@ if ( p.second )
information to tell if an object has been effectively initialized.<br>
One of the typical ways in which this has been historically
dealt with is via a special value: EOF,npos,-1, etc... This is equivalent to adding
the special value to the set of possible values of a given type. This super set of
T plus some <i>nil_t</i>&mdash;were nil_t is some stateless POD<EFBFBD>can be modeled in modern
the special value to the set of possible values of a given type. This super set of
T plus some <i>nil_t</i>&mdash;were nil_t is some stateless POD-can be modeled in modern
languages as a <b>discriminated union</b> of <code>T</code> and <code>nil_t</code>.
Discriminated unions are often called <i>variants</i>. A variant has a <i>current type</i>,
which in our case is either <code>T</code> or <code>nil_t</code>.<br>
@ -128,13 +128,13 @@ if ( p.second )
the range of possible values adding an additional sentinel value with the special meaning of <i>Nothing. </i>
However, this additional <i>Nothing</i> value is largely irrelevant for our purpose
since our goal is to formalize the notion of uninitialized objects and, while a special extended value <i>can</i> be used to convey that meaning, it is not strictly neccesary in order to do so.</p>
<p>The observation made in the last paragraph about the irrelevant nature of the additional <code>nil_t</code> with respect to
<p>The observation made in the last paragraph about the irrelevant nature of the additional <code>nil_t</code> with respect to
<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 writting I don't know of any precedence 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
<p>As of this writting I don't know of any precedence 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>
<p>In any event, both the discriminated-union or the single-element container models serve as a conceptual
ground for a class representing optional&mdash;i.e. possibly uninitialized&mdash;objects.<br>
@ -174,71 +174,71 @@ conceptually wrong but also impractical: it is not allowed to derive from a non-
<p>We can draw from the purpose of optional&lt;T&gt; the required basic semantics:</p>
<blockquote>
<p><b>Default Construction:</b> To introduce a formally uninitialized wrapped
<p><b>Default Construction:</b> To introduce a formally uninitialized wrapped
object.</p>
<p><b>Direct Value Construction via copy:</b> To introduce a formally
<p><b>Direct Value Construction via copy:</b> To introduce a formally
initialized wrapped object whose value is obtained as a copy of some object.</p>
<p><b>Deep Copy Construction:</b> To obtain a different yet equivalent wrapped
<p><b>Deep Copy Construction:</b> To obtain a different yet equivalent wrapped
object.</p>
<p><b>Direct Value Assignment (upon initialized):</b> To assign the wrapped object a value obtained
<p><b>Direct Value Assignment (upon initialized):</b> To assign the wrapped object a value obtained
as a copy of some object.</p>
<p><b>Direct Value Assignment (upon uninitialized):</b> To initialize the wrapped object
with a value obtained
<p><b>Direct Value Assignment (upon uninitialized):</b> To initialize the wrapped object
with a value obtained
as a copy of some object.</p>
<p><b>Assignnment (upon initialized):</b> To assign the wrapped object a value obtained as a copy
<p><b>Assignnment (upon initialized):</b> To assign the wrapped object a value obtained as a copy
of another wrapper's object.</p>
<p><b>Assignnment (upon uninitialized):</b> To initialize the wrapped object
with value obtained as a copy
<p><b>Assignnment (upon uninitialized):</b> To initialize the wrapped object
with value obtained as a copy
of another wrapper's object.</p>
<p><b>Deep Relational Operations (when supported by the type T):</b> To compare
wrapped object values taking into account the presence of uninitialized
<p><b>Deep Relational Operations (when supported by the type T):</b> To compare
wrapped object values taking into account the presence of uninitialized
operands.</p>
<p><b>Value access:</b> To unwrap the wrapped object.</p>
<p><b>Initialization state query:</b> To determine if the object is formally
<p><b>Initialization state query:</b> To determine if the object is formally
initialized or not.</p>
<p><b>Swap:</b> To exchange wrapper's objects. (with whatever exception safety
<p><b>Swap:</b> To exchange wrapper's objects. (with whatever exception safety
guarantiees are provided by T's swap).</p>
<p><b>De-initialization:</b> To release the wrapped object (if any) and leave
<p><b>De-initialization:</b> To release the wrapped object (if any) and leave
the wrapper in the uninitialized state.</p>
</blockquote>
<p>Additional operations are useful, such as converting constructors and
converting assignments, in-place construction and assignment, and safe value
<p>Additional operations are useful, such as converting constructors and
converting assignments, in-place construction and assignment, and safe value
access via a pointer to the wrapped object or null.</p>
<h3><u>The Interface:</u></h3>
<p>Since the purpose of optional is to allow us to use objects with a formal
uninitialized additional state, the interface could try to follow the interface
of the underlying T type as much as possible. In order to choose the proper
<p>Since the purpose of optional is to allow us to use objects with a formal
uninitialized additional state, the interface could try to follow the interface
of the underlying T type as much as possible. In order to choose the proper
degree of adoption of the native T interface, the following must be noted: <br>
Even if all the operations supported by an instance of type T are defined for
the entire range of values for such a type, an optional&lt;T&gt; extends such a set of
values with a new value for which most (otherwise valid) operations are not
Even if all the operations supported by an instance of type T are defined for
the entire range of values for such a type, an optional&lt;T&gt; extends such a set of
values with a new value for which most (otherwise valid) operations are not
defined in terms of T.<br>
Furthermore, since optional&lt;T&gt; itself is merely a T wrapper (modeling a T
supertype), any attempt to define such operations upon uninitialized optionals
Furthermore, since optional&lt;T&gt; itself is merely a T wrapper (modeling a T
supertype), any attempt to define such operations upon uninitialized optionals
will be totally artificial w.r.t. T.<br>
This library chooses an interface which follows from T's interface only for
those operations which are well defined (w.r.t the type T) even if any of the
operands are uninitialized. These operations include: construction,
This library chooses an interface which follows from T's interface only for
those operations which are well defined (w.r.t the type T) even if any of the
operands are uninitialized. These operations include: construction,
copy-construction, assignment, swap and relational operations.<br>
For the value access operations, which are undefined (w.r.t the type T) when the
operand is uninitialized, a different interface is choosen (which will be
For the value access operations, which are undefined (w.r.t the type T) when the
operand is uninitialized, a different interface is choosen (which will be
explained next).<br>
Also, the presence of the possibly uninitialized state requires additional
Also, the presence of the possibly uninitialized state requires additional
operations not provided by T itself which are supported by a special interface.</p>
<h3>Lexically-hinted Value Access in the presence of possibly untitialized
<h3>Lexically-hinted Value Access in the presence of possibly untitialized
optional objects: The operators * and -&gt;</h3>
<p>A relevant feature of a pointer is that it can have a <b>null
pointer value</b>. This is a <i>special</i> value which is used to indicate that the
@ -248,7 +248,7 @@ optional objects: The operators * and -&gt;</h3>
for handling optional objects because all you have to do to refer to a value which you
don't really have is to use a null pointer value of the appropriate type.
Pointers have been used for decades&mdash;from the days of C APIs to modern C++ libraries&mdash;to
<i>refer</i> to optional (that is, possibly inexistent) objects; particularly
<i>refer</i> to optional (that is, possibly inexistent) objects; particularly
as optional arguments to a function, but also quite often as optional data members.</P>
<P>The possible presence of a null pointer value makes the operations that access the
pointee's value possibly undefined, therefore, expressions which use dereference
@ -282,10 +282,10 @@ them. The problem resides in the shallow-copy of pointer semantics: if you need
concept incarnated by pointers.
</p>
<h4>Optional&lt;T&gt; as a model of OptionalPointee</h4>
<P>For value access operations optional&lt;&gt; uses operators * and -&gt; to lexically
warn about the possibliy uninitialized state appealing to the familiar pointer
<P>For value access operations optional&lt;&gt; uses operators * and -&gt; to lexically
warn about the possibliy uninitialized state appealing to the familiar pointer
semantics w.r.t. to null pointers.<br>
<u><b>However, it is particularly important to note that optional<> objects are not pointers. optional&lt;&gt;
<u><b>However, it is particularly important to note that optional<> objects are not pointers. optional&lt;&gt;
is not, and does not model, a pointer</b></u><b>.</b>
<P>For instance, optional&lt;&gt; has not shallow-copy so does not alias: two different optionals
never refer to the <i>same</i> value unless T itself is an reference (but my have <i>equivalent</i> values).<br>
@ -296,7 +296,7 @@ is not, and does not model, a pointer</b></u><b>.</b>
As a result, you might be able to replace optional&lt;T&gt; by T* on some situations but
not always. Specifically, on generic code written for both, you cannot use relational
operators directly, and must use the template functions
<a href="../../utility/OptionalPointee.html#equal">equal_pointees()</a> and
<a href="../../utility/OptionalPointee.html#equal">equal_pointees()</a> and
<a href="../../utility/OptionalPointee.html#less">less_pointees()</a> instead.
<HR>
@ -309,36 +309,36 @@ class optional
{
public :
<i><u>(If T is of referennce type, the parameters and results by reference are by value)</u></i>
<i><u>(If T is of reference type, the parameters and results by reference are by value)</u></i>
optional () ;
optional ( detail::none_t ) ;
optional ( T const&amp; v ) ;
optional ( T const&amp; v ) ;
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 InPlaceFactory&gt; explicit optional ( InPlaceFactory const&amp; f ) ;
template&lt;class TypedInPlaceFactory&gt; explicit optional ( TypedInPlaceFactory const&amp; f ) ;
optional&amp; operator = ( detail::none_t ) ;
optional&amp; operator = ( T const&amp; v ) ;
optional&amp; operator = ( T const&amp; v ) ;
optional&amp; operator = ( optional const&amp; rhs ) ;
template&lt;class U&gt; optional&amp; operator = ( optional&lt;U&gt; const&amp rhs ) ;
template&lt;class InPlaceFactory&gt; optional&amp; operator = ( InPlaceFactory const&amp f ) ;
template&lt;class TypedInPlaceFactory&gt; optional&amp; operator = ( TypedInPlaceFactory const&amp f ) ;
T const& get() const ;
T& get() ;
T const& get() const ;
T& get() ;
T const* operator -&gt;() const ;
T* operator -&gt;() ;
@ -352,12 +352,12 @@ class optional
operator <i>unspecified-bool-type</i>() const ;
bool operator!() const ;
<i><u>deprectated methods</u></i>
void reset() ; (deprectated)
void reset ( T const&amp; ) ; (deprectated)
bool is_initialized() const ; (deprectated)
<i><u>deprecated methods</u></i>
void reset() ; (deprecated)
void reset ( T const&amp; ) ; (deprecated)
bool is_initialized() const ; (deprecated)
} ;
@ -396,18 +396,18 @@ template&lt;class T&gt; inline void swap( optional&lt;T&gt;& x, optional&lt;T&gt
<p><b><u>NOTES: </u></b></p>
<p><b>Because T might be of reference type, in the sequel, those entries whose
semantic depends on T being of reference type or not will be distinguished using
<p><b>Because T might be of reference type, in the sequel, those entries whose
semantic depends on T being of reference type or not will be distinguished using
the following convention:<br>
If the entry reads: optional&lt;T (not a ref)&gt;, the description corresponds only to
If the entry reads: optional&lt;T (not a ref)&gt;, the description corresponds only to
the case where T is not of reference type.<br>
If the entry reads: optional&lt;T&amp;&gt;, the description corresponds only to the case
If the entry reads: optional&lt;T&amp;&gt;, the description corresponds only to the case
where T is of reference type. <br>
If the entry reads: optional&lt;T&gt;, the description is the same for both cases.</b></p>
<p><i>The following section contains various assert() which are used only to
show the postconditions as sample code. It is not implied that the type T must
support each particular expression but that if the expression is supported, the
<p><i>The following section contains various assert() which are used only to
show the postconditions as sample code. It is not implied that the type T must
support each particular expression but that if the expression is supported, the
implied condition holds.</i></p>
<hr>
@ -435,8 +435,8 @@ assert ( !def ) ;</pre>
<p><b>Notes:</b></p>
<blockquote>
<p>T's default constructor <u><i>is not</i></u> called.<br>
The
expression <code>boost::none</code> denotes an instance of <code>boost::detail::none_t</code> that can be
The
expression <code>boost::none</code> denotes an instance of <code>boost::detail::none_t</code> that can be
used as the parameter.</p>
</blockquote>
<p><b>Example:</b></p>
@ -471,7 +471,7 @@ assert ( *opt == v ) ;</pre>
<pre>optional&lt;T&amp;&gt;::optional( T ref )</pre>
<blockquote>
<p><b>Effect:</b> Directly-Constructs an <b>optional</b>.</p>
<p><b>Postconditions:</b> <b>*this</b> is <u>initialized</u> and its value is an
<p><b>Postconditions:</b> <b>*this</b> is <u>initialized</u> and its value is an
instance of an internal type wrapping the reference 'ref'.</p>
<p><b>Throws:</b> Nothing.</p>
<p><b>Example:</b></p>
@ -525,8 +525,8 @@ assert ( init2 == init ) ;
and its value is a <i>copy</i> of the internal wrapper holding the references in <b>rhs</b>; else <b>*this</b>
is uninitialized.</p>
<p><b>Throws:</b> Nothing.</p>
<p><b>Notes:</b> If <b>rhs</b> is initialized, the internal wrapper will be
copied and just like true references, both <b>*this</b> and <b>rhs</b> will
<p><b>Notes:</b> If <b>rhs</b> is initialized, the internal wrapper will be
copied and just like true references, both <b>*this</b> and <b>rhs</b> will
referr to the same object<b> </b>(will alias).</p>
<p><b>Example:</b></p>
<blockquote>
@ -581,13 +581,13 @@ assert( *y == 123 ) ;
<pre>template&lt;<i>TypedInPlaceFactory</i>&gt; explicit optional&lt;T <i>(not a ref)</i>&gt;::optional( <i>TypedInPlaceFactory</i> const&amp; f );</pre>
<blockquote>
<p><b>Effect:</b> Constructs an <b>optional</b> with a value of T obtained from
<p><b>Effect:</b> Constructs an <b>optional</b> with a value of T obtained from
the factory.</p>
<p><b>Postconditions:</b>&nbsp; <b>*this</b> is <u>initialized</u> and its value is
<p><b>Postconditions:</b>&nbsp; <b>*this</b> is <u>initialized</u> and its value is
<i>directly given</i> from the factory 'f' (i.e, the value<u> is not copied</u>).</p>
<p><b>Throws:</b> Whatever the T constructor called by the factory throws.</p>
<p><b>Notes:</b> See <A HREF="#inplace">In-Place Factories</A></p>
<p><b>Exception Safety:</b> Exceptions can only be thrown during the call to the
<p><b>Exception Safety:</b> Exceptions can only be thrown during the call to the
T constructor used by the factory;
in that case, this constructor has no effect.
</p>
@ -863,7 +863,7 @@ assert ( !!opt ) ;
<pre>bool optional&lt;T&gt;::is_initialized() const ;</pre>
<blockquote>
<p><b>Returns:</b> <i>true</i> is the <b>optional</b> is initialized, <i>false</i>
<p><b>Returns:</b> <i>true</i> is the <b>optional</b> is initialized, <i>false</i>
otherwise.</p>
<p><b>Throws:</b> Nothing.</p>
<blockquote>
@ -921,7 +921,7 @@ assert ( optX != optZ ) ;
<pre>bool operator &lt; ( optional&lt;T&gt; const&amp x, optional&lt;T&gt const&amp y );</pre>
<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 both <b>x</b> and <b>y</b> are initialized, <code>(*x &lt; *y)</code>.
</p>
@ -991,8 +991,8 @@ assert ( optX != optZ ) ;
<HR>
<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>
using std::swap.<br>
If only one is initialized, say x, calls: <code>y.reset(*x); x.reset();</code><br>
@ -1105,7 +1105,7 @@ else print(&quot;employer's name not found!&quot;);
};
</pre>
<h3>Bypassing expensive unnecesary default construction</h3>
<h3>Bypassing expensive unnecesary default construction</h3>
<pre>class ExpensiveCtor { ... } ;
class Fred
{
@ -1118,10 +1118,10 @@ class Fred
<HR>
<H2><A NAME="ref">Optional references</A></H2>
<p>This library allow the template parameter T to be of reference type: T&amp;, and
<p>This library allow the template parameter T to be of reference type: T&amp;, and
to some extent, T const&amp;.</p>
<p>However, since references are not real objects some restrictions apply and
<p>However, since references are not real objects some restrictions apply and
some operations are not available in this case:</p>
<ul>
@ -1131,13 +1131,13 @@ some operations are not available in this case:</p>
<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
<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>
<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; will copy the references but all these references
will nonetheless refeer to the same object.</li>
<li>Value-access will actually provide access to the referenced object rather
<li>Value-access will actually provide access to the referenced object rather
than the reference itself.</li>
</ul>
@ -1145,52 +1145,52 @@ value, a true real reference is stored so aliasing will ocurr: </p>
<H2><A NAME="inplace">In-Place Factories</A></H2>
<p>
One of the typical problems with wrappers and containers is that their
interfaces usually provide an operation to initialize or assign the contained
object as a copy of some other object. This not only requires the underlying
type to be <a href="../../utility/CopyConstructible.html">Copy Constructible</a>, but also requires the existence of a fully
One of the typical problems with wrappers and containers is that their
interfaces usually provide an operation to initialize or assign the contained
object as a copy of some other object. This not only requires the underlying
type to be <a href="../../utility/CopyConstructible.html">Copy Constructible</a>, but also requires the existence of a fully
constructed object, often temporary, just to follow the copy from:</p>
<pre>struct X
<pre>struct X
{
X ( int, std:::string ) ;
X ( int, std:::string ) ;
} ;</pre>
<pre>class W
{
X wrapped_ ;
public:
W ( X const& x ) : wrapped_(x) {}
W ( X const& x ) : wrapped_(x) {}
} ;</pre>
<pre>void foo()
{
// Temporary object created.
W ( X(123,"hello") ) ;
W ( X(123,"hello") ) ;
}
</pre>
<p>A solution to this problem is to support direct construction of the contained
<p>A solution to this problem is to support direct construction of the contained
object right in the container's storage.<br>
In this shceme, the user only needs to supply the arguments to the constructor
In this shceme, the user only needs to supply the arguments to the constructor
to use in the wrapped object construction.</p>
<pre>class W
{
X wrapped_ ;
public:
W ( X const& x ) : wrapped_(x) {}
W ( X const& x ) : wrapped_(x) {}
W ( int a0, std::string a1) : wrapped_(a0,a1) {}
} ;</pre>
<pre>void foo()
{
// Wrapped object constructed in-place
// No temporary created.
W (123,"hello") ;
W (123,"hello") ;
}
</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 familiy of <b>InPlaceFactories</b> and
<p>The solution presented in this library is the familiy 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
@ -1200,29 +1200,29 @@ parameters at an address specified by the user via placement new.</p>
class TypedInPlaceFactory2
{
A0 m_a0 ; A1 m_a1 ;
public:
TypedInPlaceFactory2( A0 const& a0, A1 const& a1 ) : m_a0(a0), m_a1(a1) {}
void construct ( void* p ) { new (p) T(m_a0,m_a1) ; }
void construct ( void* p ) { new (p) T(m_a0,m_a1) ; }
} ;
</pre>
<p>A wrapper class aware of this can use it as:</p>
<pre>class W
{
X wrapped_ ;
public:
W ( X const& x ) : wrapped_(x) {}
W ( X const& x ) : wrapped_(x) {}
W ( TypedInPlaceFactory2 const& fac ) { fac.construct(&wrapped_) ; }
} ;</pre>
<pre>void foo()
{
// Wrapped object constructed in-place via a TypedInPlaceFactory.
// No temporary created.
W ( TypedInPlaceFactory2&lt;X,int,std::string&rt;(123,"hello")) ;
W ( TypedInPlaceFactory2&lt;X,int,std::string&rt;(123,"hello")) ;
}
</pre>
<p>The factories are divided in two groups:<ul>
@ -1233,35 +1233,35 @@ public:
<p></p>
<p>This library provides an overloaded set of helper template functions to construct these factories
without requiring unnecessary template parameters:</p>
<pre>template&lt;class A0,...,class AN&gt;
<pre>template&lt;class A0,...,class AN&gt;
InPlaceFactory<i>N </i>&lt;A0,...,AN&gt; <b>in_place</b> ( A0 const& a0, ..., AN const& aN) ;
template&lt;class T,class A0,...,class AN&gt;
template&lt;class T,class A0,...,class AN&gt;
TypedInPlaceFactory<i>N </i>&lt;T,A0,...,AN&gt; <b>in_place</b> ( T const& a0, A0 const& a0, ..., AN const& aN) ;</pre>
<p>In-place factories can be used generically by the wrapper and user as follows:</p>
<pre>class W
{
X wrapped_ ;
public:
W ( X const& x ) : wrapped_(x) {}
W ( X const& x ) : wrapped_(x) {}
template<class InPlaceFactory></class>
W ( InPlaceFactory const& fac ) { fac.template &lt;X&gt;construct(&wrapped_) ; }
} ;</pre>
<pre>void foo()
{
// Wrapped object constructed in-place via a InPlaceFactory.
// No temporary created.
W ( in_place(123,"hello") ) ;
W ( in_place(123,"hello") ) ;
}
</pre>
<p>The factories are implemented in the headers:
<a href="../../../boost/detail/in_place_factory.hpp">in_place_factory.hpp</a> and
<a href="../../../boost/detail/typed_in_place_factory.hpp">typed_in_place_factory.hpp</a>
<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>
@ -1272,7 +1272,7 @@ 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 bool 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 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>
<pre>void foo ( bool v ) ;
@ -1291,7 +1291,7 @@ integral promotions don't apply (i.e. if foo() takes an 'int' instead, it won't
<H2><A NAME="exsafety">Exception Safety Guarantees</A></H2>
<H3><u>Assignment and Reset:</u></H3>
<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>
<ul>
<li> <code>optional&lt;T&gt;::operator= ( optional&lt;T&gt; const&amp; ) </code>
@ -1299,9 +1299,9 @@ of the assignment methods:</p>
<li> <code>optional&lt;T&gt;::operator= ( T const&amp; ) </code></li>
<li> <code>template&lt;class U&gt; optional&lt;T&gt;::operator= ( optional&lt;U&gt; const&amp; ) </code>
</li>
<li> <code>template&lt;class InPlaceFactory&gt; optional&lt;T&gt;::operator= (
<li> <code>template&lt;class InPlaceFactory&gt; optional&lt;T&gt;::operator= (
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>
<li> <code>optional&lt;T&gt;:::reset ( T const&amp;)</code></li>
</ul>
@ -1363,7 +1363,7 @@ If none of the optionals is initialized, it has no-throw guarantee since it is a
<HR>
<H2><A NAME="requirements">Type requirements</A></H2>
<p>In general, T must be <a href="../../utility/CopyConstructible.html">Copy Constructible</a> and have a no-throw destructor. The copy-constructible requirement is not needed
<p>In general, T must be <a href="../../utility/CopyConstructible.html">Copy Constructible</a> and have a no-throw destructor. The copy-constructible requirement is not needed
if InPlaceFactories are used.<br>
T <u>is not</u> required to be <a href="http://www.sgi.com/tech/stl/DefaultConstructible.html">Default Constructible</a> </p>
@ -1407,39 +1407,40 @@ T <u>is not</u> required to be <a href="http://www.sgi.com/tech/stl/DefaultConst
Henney, David Abrahams, and others I can't recall. </p>
</blockquote>
<p>Post-formal review:</p>
<blockquote>
<p>William Kempf carefully considered the originally proposed interface and
suggested the new interface which is currently used. He also started and fueled
the discussion about the analogy optional&lt;&gt;/smart pointer and about
<blockquote>
<p>William Kempf carefully considered the originally proposed interface and
suggested the new interface which is currently used. He also started and fueled
the discussion about the analogy optional&lt;&gt;/smart pointer and about
relational operators.<br>
Peter Dimov, Joel de Guzman, David Abrahams, Tanton Gibbs and Ian Hanson focused
on the relational semantics of optional (originally undefined); concluding
with the fact that the pointer-like interface doesn't make it a pointer so
Peter Dimov, Joel de Guzman, David Abrahams, Tanton Gibbs and Ian Hanson focused
on the relational semantics of optional (originally undefined); concluding
with the fact that the pointer-like interface doesn't make it a pointer so
it shall have deep relational operators.<br>
Augustus Saunders also explored the different relational semantics between
optional&lt;&gt; and a pointer and developed the OptionalPointee concept as
Augustus Saunders also explored the different relational semantics between
optional&lt;&gt; and a pointer and developed the OptionalPointee concept as
an aid against potential conflicts on generic code.<br>
Joel de Guzman noticed that optional&lt;&gt; can be seen as an API on top
Joel de Guzman noticed that optional&lt;&gt; can be seen as an API on top
of variant&lt;T,nil_t&gt;.<br>
Dave Gomboc explained the meaning and usage of the Haskell analog to optional&lt;&gt;:
Dave Gomboc explained the meaning and usage of the Haskell analog to optional&lt;&gt;:
the Maybe type constructor (analogy originally pointed out by David Sankel).<br>
Other comments were posted by Vincent Finn, Anthony Williams, Ed Brey, Rob
Other comments were posted by Vincent Finn, Anthony Williams, Ed Brey, Rob
Stewart, and others.<br>
Joel de Guzman made the case for the support of references and helped with
Joel de Guzman made the case for the support of references and helped with
the proper semantics.<br>
Mat Marcus shown the virtues of a value-oriented interface, influencing the
Mat Marcus shown the virtues of a value-oriented interface, influencing the
current design, and contributed the idea of &quot;none&quot;.</p>
</blockquote>
<HR>
<P>Revised Jannuary 30, 2004</P>
<P>&copy; Copyright boost.org 2003. Permission to copy, use, modify, sell and
distribute this document is granted provided this copyright notice appears in
all copies. This document is provided &quot;as is&quot; without express or implied
warranty, and with no claim as to its suitability for any purpose.</P>
<p><EFBFBD> Copyright Fernando Luis Cacciola Carballal, 2003,2004</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>
<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
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>
</HTML>
</HTML>

View File

@ -1,56 +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_UTILITY_INPLACE_FACTORY_25AGO2003_HPP
#define BOOST_UTILITY_INPLACE_FACTORY_25AGO2003_HPP
#include <boost/detail/in_place_factory_prefix.hpp>
#include <boost/type.hpp>
namespace boost {
class InPlaceFactoryBase {} ;
#define BOOST_DEFINE_INPLACE_FACTORY_CLASS(z,n,_) \
template< BOOST_PP_ENUM_PARAMS(BOOST_PP_INC(n),class A) > \
class BOOST_PP_CAT(InPlaceFactory, BOOST_PP_INC(n) ) : public InPlaceFactoryBase \
{ \
public: \
\
BOOST_PP_CAT(InPlaceFactory, BOOST_PP_INC(n) ) ( BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_INC(n),A,const& a) ) \
: \
BOOST_PP_ENUM( BOOST_PP_INC(n), BOOST_DEFINE_INPLACE_FACTORY_CLASS_MEMBER_INIT, _ ) \
{} \
\
template<class T> \
void apply ( void* address BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(T) ) const \
{ \
new ( address ) T ( BOOST_PP_ENUM_PARAMS( BOOST_PP_INC(n), m_a ) ) ; \
} \
\
BOOST_PP_REPEAT( BOOST_PP_INC(n), BOOST_DEFINE_INPLACE_FACTORY_CLASS_MEMBER_DECL, _) \
} ; \
\
template< BOOST_PP_ENUM_PARAMS(BOOST_PP_INC(n),class A) > \
BOOST_PP_CAT(InPlaceFactory, BOOST_PP_INC(n) ) < BOOST_PP_ENUM_PARAMS( BOOST_PP_INC(n), A ) > \
in_place ( BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_INC(n),A, const& a) ) \
{ \
return BOOST_PP_CAT(InPlaceFactory, BOOST_PP_INC(n) ) < BOOST_PP_ENUM_PARAMS( BOOST_PP_INC(n), A ) > \
( BOOST_PP_ENUM_PARAMS( BOOST_PP_INC(n), a ) ) ; \
} ; \
BOOST_PP_REPEAT( BOOST_MAX_INPLACE_FACTORY_ARITY, BOOST_DEFINE_INPLACE_FACTORY_CLASS, BOOST_PP_EMPTY() )
} // namespace boost
#endif

View File

@ -1,33 +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_UTILITY_INPLACE_FACTORY_PREFIX_25AGO2003_HPP
#define BOOST_UTILITY_INPLACE_FACTORY_PREFIX_25AGO2003_HPP
#include <boost/config.hpp>
#include <boost/preprocessor/repetition/enum.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/arithmetic/inc.hpp>
#include <boost/preprocessor/punctuation/paren.hpp>
#include <boost/preprocessor/facilities/empty.hpp>
#define BOOST_DEFINE_INPLACE_FACTORY_CLASS_MEMBER_INIT(z,n,_) BOOST_PP_CAT(m_a,n) BOOST_PP_LPAREN() BOOST_PP_CAT(a,n) BOOST_PP_RPAREN()
#define BOOST_DEFINE_INPLACE_FACTORY_CLASS_MEMBER_DECL(z,n,_) BOOST_PP_CAT(A,n) const& BOOST_PP_CAT(m_a,n);
#define BOOST_DEFINE_INPLACE_FACTORY_CLASS_MEMBER_ARG(z,n,_) BOOST_PP_CAT(m_a,n)
#define BOOST_MAX_INPLACE_FACTORY_ARITY 10
#undef BOOST_UTILITY_INPLACE_FACTORY_SUFFIX_25AGO2003_HPP
#endif

View File

@ -1,57 +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_UTILITY_TYPED_INPLACE_FACTORY_25AGO2003_HPP
#define BOOST_UTILITY_TYPED_INPLACE_FACTORY_25AGO2003_HPP
#include <boost/detail/in_place_factory_prefix.hpp>
namespace boost {
class TypedInPlaceFactoryBase {} ;
#define BOOST_DEFINE_TYPED_INPLACE_FACTORY_CLASS(z,n,_) \
template< class T, BOOST_PP_ENUM_PARAMS(BOOST_PP_INC(n),class A) > \
class BOOST_PP_CAT(TypedInPlaceFactory, BOOST_PP_INC(n) ) : public TypedInPlaceFactoryBase \
{ \
public: \
\
typedef T value_type ; \
\
BOOST_PP_CAT(TypedInPlaceFactory, BOOST_PP_INC(n) ) ( BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_INC(n),A,const& a) ) \
: \
BOOST_PP_ENUM( BOOST_PP_INC(n), BOOST_DEFINE_INPLACE_FACTORY_CLASS_MEMBER_INIT, _ ) \
{} \
\
void apply ( void* address ) const \
{ \
new ( address ) T ( BOOST_PP_ENUM_PARAMS( BOOST_PP_INC(n), m_a ) ) ; \
} \
\
BOOST_PP_REPEAT( BOOST_PP_INC(n), BOOST_DEFINE_INPLACE_FACTORY_CLASS_MEMBER_DECL, _) \
} ; \
\
template< class T, BOOST_PP_ENUM_PARAMS(BOOST_PP_INC(n),class A) > \
BOOST_PP_CAT(TypedInPlaceFactory, BOOST_PP_INC(n) ) < T , BOOST_PP_ENUM_PARAMS( BOOST_PP_INC(n), A ) > \
in_place ( BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_INC(n),A, const& a) ) \
{ \
return BOOST_PP_CAT(TypedInPlaceFactory, BOOST_PP_INC(n) ) < T, BOOST_PP_ENUM_PARAMS( BOOST_PP_INC(n), A ) > \
( BOOST_PP_ENUM_PARAMS( BOOST_PP_INC(n), a ) ) ; \
} ; \
BOOST_PP_REPEAT( BOOST_MAX_INPLACE_FACTORY_ARITY, BOOST_DEFINE_TYPED_INPLACE_FACTORY_CLASS, BOOST_PP_EMPTY() )
} // namespace boost
#include <boost/detail/in_place_factory_suffix.hpp>
#endif

View File

@ -9,8 +9,8 @@
// You are welcome to contact the author at:
// fernando_cacciola@hotmail.com
//
#ifndef BOOST_UTILITY_NONE_17SEP2003_HPP
#define BOOST_UTILITY_NONE_17SEP2003_HPP
#ifndef BOOST_NONE_17SEP2003_HPP
#define BOOST_NONE_17SEP2003_HPP
#include "boost/detail/none_t.hpp"

View File

@ -12,700 +12,7 @@
#ifndef BOOST_OPTIONAL_FLC_19NOV2002_HPP
#define BOOST_OPTIONAL_FLC_19NOV2002_HPP
#include<new>
#include<algorithm>
#include "boost/config.hpp"
#include "boost/assert.hpp"
#include "boost/type.hpp"
#include "boost/type_traits/alignment_of.hpp"
#include "boost/type_traits/type_with_alignment.hpp"
#include "boost/type_traits/remove_reference.hpp"
#include "boost/type_traits/is_reference.hpp"
#include "boost/mpl/if.hpp"
#include "boost/mpl/bool.hpp"
#include "boost/mpl/not.hpp"
#include "boost/detail/reference_content.hpp"
#include "boost/detail/none_t.hpp"
#include "boost/utility/compare_pointees.hpp"
#if BOOST_WORKAROUND(BOOST_MSVC, == 1200)
// VC6.0 has the following bug:
// When a templated assignment operator exist, an implicit conversion
// constructing an optional<T> is used when assigment of the form:
// optional<T> opt ; opt = T(...);
// is compiled.
// However, optional's ctor is _explicit_ and the assignemt shouldn't compile.
// Therefore, for VC6.0 templated assignment is disabled.
//
#define BOOST_OPTIONAL_NO_CONVERTING_ASSIGNMENT
#endif
#if BOOST_WORKAROUND(BOOST_MSVC, == 1300)
// VC7.0 has the following bug:
// When both a non-template and a template copy-ctor exist
// and the templated version is made 'explicit', the explicit is also
// given to the non-templated version, making the class non-implicitely-copyable.
//
#define BOOST_OPTIONAL_NO_CONVERTING_COPY_CTOR
#endif
#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) || BOOST_WORKAROUND(BOOST_INTEL_CXX_VERSION,<=700)
// AFAICT only VC7.1 correctly resolves the overload set
// that includes the in-place factory taking functions,
// so for the other VC versions, in-place factory support
// is disabled
#define BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
#endif
#if BOOST_WORKAROUND(__BORLANDC__, <= 0x551)
// BCB (5.5.1) cannot parse the nested template struct in an inplace factory.
#define BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
#endif
#if !defined(BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT) \
&& BOOST_WORKAROUND(__BORLANDC__, <= 0x564)
// BCB (up to 5.64) has the following bug:
// If there is a member function/operator template of the form
// template<class Expr> mfunc( Expr expr ) ;
// some calls are resolved to this even if there are other better matches.
// The effect of this bug is that calls to converting ctors and assignments
// are incrorrectly sink to this general catch-all member function template as shown above.
#define BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION
#endif
namespace boost {
class InPlaceFactoryBase ;
class TypedInPlaceFactoryBase ;
namespace optional_detail {
// This local class is used instead of that in "aligned_storage.hpp"
// because I've found the 'official' class to ICE BCB5.5
// when some types are used with optional<>
// (due to sizeof() passed down as a non-type template parameter)
template <class T>
class aligned_storage
{
// Borland ICEs if unnamed unions are used for this!
union dummy_u
{
char data[ sizeof(T) ];
BOOST_DEDUCED_TYPENAME type_with_alignment<
::boost::alignment_of<T>::value >::type aligner_;
} dummy_ ;
public:
void const* address() const { return &dummy_.data[0]; }
void * address() { return &dummy_.data[0]; }
} ;
template<class T>
struct types_when_isnt_ref
{
typedef T const& reference_const_type ;
typedef T & reference_type ;
typedef T const* pointer_const_type ;
typedef T * pointer_type ;
typedef T const& argument_type ;
} ;
template<class T>
struct types_when_is_ref
{
typedef BOOST_DEDUCED_TYPENAME remove_reference<T>::type raw_type ;
typedef raw_type& reference_const_type ;
typedef raw_type& reference_type ;
typedef raw_type* pointer_const_type ;
typedef raw_type* pointer_type ;
typedef raw_type& argument_type ;
} ;
struct optional_tag {} ;
template<class T>
class optional_base : public optional_tag
{
private :
typedef BOOST_DEDUCED_TYPENAME detail::make_reference_content<T>::type internal_type ;
typedef aligned_storage<internal_type> storage_type ;
typedef types_when_isnt_ref<T> types_when_not_ref ;
typedef types_when_is_ref<T> types_when_ref ;
typedef optional_base<T> this_type ;
protected :
typedef T value_type ;
typedef mpl::true_ is_reference_tag ;
typedef mpl::false_ is_not_reference_tag ;
typedef BOOST_DEDUCED_TYPENAME is_reference<T>::type is_reference_predicate ;
typedef BOOST_DEDUCED_TYPENAME mpl::if_<is_reference_predicate,types_when_ref,types_when_not_ref>::type types ;
typedef bool (this_type::*unspecified_bool_type)() const;
typedef BOOST_DEDUCED_TYPENAME types::reference_type reference_type ;
typedef BOOST_DEDUCED_TYPENAME types::reference_const_type reference_const_type ;
typedef BOOST_DEDUCED_TYPENAME types::pointer_type pointer_type ;
typedef BOOST_DEDUCED_TYPENAME types::pointer_const_type pointer_const_type ;
typedef BOOST_DEDUCED_TYPENAME types::argument_type argument_type ;
// Creates an optional<T> uninitialized.
// No-throw
optional_base()
:
m_initialized(false) {}
// Creates an optional<T> uninitialized.
// No-throw
optional_base ( detail::none_t const& )
:
m_initialized(false) {}
// Creates an optional<T> initialized with 'val'.
// Can throw if T::T(T const&) does
optional_base ( argument_type val )
:
m_initialized(false)
{
construct(val);
}
// Creates a deep copy of another optional<T>
// Can throw if T::T(T const&) does
optional_base ( optional_base const& rhs )
:
m_initialized(false)
{
if ( rhs.is_initialized() )
construct(rhs.get_impl());
}
// This is used for both converting and in-place constructions.
// Derived classes use the 'tag' to select the appropriate
// implementation (the correct 'construct()' overload)
template<class Expr>
explicit optional_base ( Expr const& expr, Expr const* tag )
:
m_initialized(false)
{
construct(expr,tag);
}
// No-throw (assuming T::~T() doesn't)
~optional_base() { destroy() ; }
// Assigns from another optional<T> (deep-copies the rhs value)
// Basic Guarantee: If T::T( T const& ) throws, this is left UNINITIALIZED
void assign ( optional_base const& rhs )
{
destroy();
if ( rhs.is_initialized() )
construct(rhs.get_impl());
}
// Assigns from a T (deep-copies the rhs value)
// Basic Guarantee: If T::( T const& ) throws, this is left UNINITIALIZED
void assign ( argument_type val )
{
destroy();
construct(val);
}
// Assigns from "none", destroying the current value, if any, leaving this UNINITIALIZED
// No-throw (assuming T::~T() doesn't)
void assign ( detail::none_t const& ) { destroy(); }
#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
template<class Expr>
void assign_expr ( Expr const& expr, Expr const* tag )
{
destroy();
construct(expr,tag);
}
#endif
public :
// Destroys the current value, if any, leaving this UNINITIALIZED
// No-throw (assuming T::~T() doesn't)
void reset() { destroy(); }
// Replaces the current value -if any- with 'val'
// Basic Guarantee: If T::T( T const& ) throws this is left UNINITIALIZED.
void reset ( argument_type val ) { assign(val); }
// Returns a pointer to the value if this is initialized, otherwise,
// returns NULL.
// No-throw
pointer_const_type get_ptr() const { return m_initialized ? get_ptr_impl() : 0 ; }
pointer_type get_ptr() { return m_initialized ? get_ptr_impl() : 0 ; }
bool is_initialized() const { return m_initialized ; }
protected :
void construct ( argument_type val )
{
new (m_storage.address()) internal_type(val) ;
m_initialized = true ;
}
#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
// Constructs in-place using the given factory
template<class Expr>
void construct ( Expr const& factory, InPlaceFactoryBase const* )
{
BOOST_STATIC_ASSERT ( ::boost::mpl::not_<is_reference_predicate>::value ) ;
factory.BOOST_NESTED_TEMPLATE apply<value_type>(m_storage.address()) ;
m_initialized = true ;
}
// Constructs in-place using the given typed factory
template<class Expr>
void construct ( Expr const& factory, TypedInPlaceFactoryBase const* )
{
BOOST_STATIC_ASSERT ( ::boost::mpl::not_<is_reference_predicate>::value ) ;
factory.apply(m_storage.address()) ;
m_initialized = true ;
}
#endif
// Constructs using any expression implicitely convertible to the single argument
// of a one-argument T constructor.
// Converting constructions of optional<T> from optional<U> uses this function with
// 'Expr' being of type 'U' and relying on a converting constructor of T from U.
template<class Expr>
void construct ( Expr const& expr, void const* )
{
new (m_storage.address()) internal_type(expr) ;
m_initialized = true ;
}
#ifdef BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION
// BCB5.64 (and probably lower versions) workaround.
// The in-place factories are supported by means of catch-all constructors
// and assignment operators (the functions are parameterized in terms of
// an arbitrary 'Expr' type)
// This compiler incorrectly resolves the overload set and sinks optional<T> and optional<U>
// to the 'Expr'-taking functions even though explicit overloads are present for them.
// Thus, the following overload is needed to properly handle the case when the 'lhs'
// is another optional.
//
// For VC<=70 compilers this workaround dosen't work becasue the comnpiler issues and error
// instead of choosing the wrong overload
//
// Notice that 'Expr' will be optional<T> or optional<U> (but not optional_base<..>)
template<class Expr>
void construct ( Expr const& expr, optional_tag const* )
{
if ( expr.is_initialized() )
{
// An exception can be thrown here.
// It it happens, THIS will be left uninitialized.
new (m_storage.address()) internal_type(expr.get()) ;
m_initialized = true ;
}
}
#endif
void destroy()
{
if ( m_initialized )
destroy_impl(is_reference_predicate()) ;
}
unspecified_bool_type safe_bool() const { return m_initialized ? &this_type::is_initialized : 0 ; }
reference_const_type get_impl() const { return dereference(get_object(), is_reference_predicate() ) ; }
reference_type get_impl() { return dereference(get_object(), is_reference_predicate() ) ; }
pointer_const_type get_ptr_impl() const { return cast_ptr(get_object(), is_reference_predicate() ) ; }
pointer_type get_ptr_impl() { return cast_ptr(get_object(), is_reference_predicate() ) ; }
private :
// internal_type can be either T or reference_content<T>
internal_type const* get_object() const { return static_cast<internal_type const*>(m_storage.address()); }
internal_type * get_object() { return static_cast<internal_type *> (m_storage.address()); }
// reference_content<T> lacks an implicit conversion to T&, so the following is needed to obtain a proper reference.
reference_const_type dereference( internal_type const* p, is_not_reference_tag ) const { return *p ; }
reference_type dereference( internal_type* p, is_not_reference_tag ) { return *p ; }
reference_const_type dereference( internal_type const* p, is_reference_tag ) const { return p->get() ; }
reference_type dereference( internal_type* p, is_reference_tag ) { return p->get() ; }
void destroy_impl ( is_not_reference_tag ) { get_impl().~T() ; m_initialized = false ; }
void destroy_impl ( is_reference_tag ) { m_initialized = false ; }
// If T is of reference type, trying to get a pointer to the held value must result in a compile-time error.
// Decent compilers should disallow conversions from reference_content<T>* to T*, but just in case,
// 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 ; }
bool m_initialized ;
storage_type m_storage ;
} ;
} // namespace optional_detail
template<class T>
class optional : public optional_detail::optional_base<T>
{
typedef optional_detail::optional_base<T> base ;
typedef BOOST_DEDUCED_TYPENAME base::unspecified_bool_type unspecified_bool_type ;
public :
typedef optional<T> this_type ;
typedef BOOST_DEDUCED_TYPENAME base::value_type value_type ;
typedef BOOST_DEDUCED_TYPENAME base::reference_type reference_type ;
typedef BOOST_DEDUCED_TYPENAME base::reference_const_type reference_const_type ;
typedef BOOST_DEDUCED_TYPENAME base::pointer_type pointer_type ;
typedef BOOST_DEDUCED_TYPENAME base::pointer_const_type pointer_const_type ;
typedef BOOST_DEDUCED_TYPENAME base::argument_type argument_type ;
// Creates an optional<T> uninitialized.
// No-throw
optional() : base() {}
// Creates an optional<T> uninitialized.
// No-throw
optional( detail::none_t const& none_ ) : base(none_) {}
// Creates an optional<T> initialized with 'val'.
// Can throw if T::T(T const&) does
optional ( argument_type val ) : base(val) {}
#ifndef BOOST_OPTIONAL_NO_CONVERTING_COPY_CTOR
// NOTE: MSVC needs templated versions first
// Creates a deep copy of another convertible optional<U>
// Requires a valid conversion from U to T.
// Can throw if T::T(U const&) does
template<class U>
explicit optional ( optional<U> const& rhs )
:
base()
{
if ( rhs.is_initialized() )
this->construct(rhs.get());
}
#endif
#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
// Creates an optional<T> with an expression which can be either
// (a) An instance of InPlaceFactory (i.e. in_place(a,b,...,n);
// (b) An instance of TypedInPlaceFactory ( i.e. in_place<T>(a,b,...,n);
// (c) Any expression implicitely convertible to the single type
// of a one-argument T's constructor.
// (d*) Weak compilers (BCB) might also resolved Expr as optional<T> and optional<U>
// even though explicit overloads are present for these.
// Depending on the above some T ctor is called.
// Can throw is the resolved T ctor throws.
template<class Expr>
explicit optional ( Expr const& expr ) : base(expr,&expr) {}
#endif
// Creates a deep copy of another optional<T>
// Can throw if T::T(T const&) does
optional ( optional const& rhs ) : base(rhs) {}
// No-throw (assuming T::~T() doesn't)
~optional() {}
#if !defined(BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT) && !defined(BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION)
// Assigns from an expression. See corresponding constructor.
// Basic Guarantee: If the resolved T ctor throws, this is left UNINITIALIZED
template<class Expr>
optional& operator= ( Expr expr )
{
this->assign_expr(expr,&expr);
return *this ;
}
#endif
#ifndef BOOST_OPTIONAL_NO_CONVERTING_ASSIGNMENT
// Assigns from another convertible optional<U> (converts && deep-copies the rhs value)
// Requires a valid conversion from U to T.
// Basic Guarantee: If T::T( U const& ) throws, this is left UNINITIALIZED
template<class U>
optional& operator= ( optional<U> const& rhs )
{
this->destroy(); // no-throw
if ( rhs.is_initialized() )
{
// An exception can be thrown here.
// It it happens, THIS will be left uninitialized.
this->assign(rhs.get());
}
return *this ;
}
#endif
// Assigns from another optional<T> (deep-copies the rhs value)
// Basic Guarantee: If T::T( T const& ) throws, this is left UNINITIALIZED
// (NOTE: On BCB, this operator is not actually called and left is left UNMODIFIED in case of a throw)
optional& operator= ( optional const& rhs )
{
this->assign( rhs ) ;
return *this ;
}
// Assigns from a T (deep-copies the rhs value)
// Basic Guarantee: If T::( T const& ) throws, this is left UNINITIALIZED
optional& operator= ( argument_type val )
{
this->assign( val ) ;
return *this ;
}
// Assigns from a "none"
// Which destroys the current value, if any, leaving this UNINITIALIZED
// No-throw (assuming T::~T() doesn't)
optional& operator= ( detail::none_t const& none_ )
{
this->assign( none_ ) ;
return *this ;
}
// Returns a reference to the value if this is initialized, otherwise,
// the behaviour is UNDEFINED
// No-throw
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 pointer to the value if this is initialized, otherwise,
// the behaviour is UNDEFINED
// No-throw
pointer_const_type operator->() const { BOOST_ASSERT(this->is_initialized()) ; return this->get_ptr_impl() ; }
pointer_type operator->() { BOOST_ASSERT(this->is_initialized()) ; return this->get_ptr_impl() ; }
// Returns a reference to the value if this is initialized, otherwise,
// the behaviour is UNDEFINED
// No-throw
reference_const_type operator *() const { return this->get() ; }
reference_type operator *() { return this->get() ; }
// implicit conversion to "bool"
// No-throw
operator unspecified_bool_type() const { return this->safe_bool() ; }
// This is provided for those compilers which don't like the conversion to bool
// on some contexts.
bool operator!() const { return !this->is_initialized() ; }
} ;
// 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<T> const& opt )
{
return opt.get() ;
}
template<class T>
inline
BOOST_DEDUCED_TYPENAME optional<T>::reference_type
get ( optional<T>& opt )
{
return opt.get() ;
}
// Returns a pointer to the value if this is initialized, otherwise, returns NULL.
// No-throw
template<class T>
inline
BOOST_DEDUCED_TYPENAME optional<T>::pointer_const_type
get ( optional<T> const* opt )
{
return opt->get_ptr() ;
}
template<class T>
inline
BOOST_DEDUCED_TYPENAME optional<T>::pointer_type
get ( optional<T>* opt )
{
return opt->get_ptr() ;
}
// Returns a pointer to the value if this is initialized, otherwise, returns NULL.
// No-throw
template<class T>
inline
BOOST_DEDUCED_TYPENAME optional<T>::pointer_const_type
get_pointer ( optional<T> const& opt )
{
return opt.get_ptr() ;
}
template<class T>
inline
BOOST_DEDUCED_TYPENAME optional<T>::pointer_type
get_pointer ( optional<T>& opt )
{
return opt.get_ptr() ;
}
// optional's relational operators ( ==, !=, <, >, <=, >= ) have deep-semantics (compare values).
// WARNING: This is UNLIKE pointers. Use equal_pointees()/less_pointess() in generic code instead.
template<class T>
inline
bool operator == ( optional<T> const& x, optional<T> const& y )
{ return equal_pointees(x,y); }
template<class T>
inline
bool operator < ( optional<T> const& x, optional<T> const& y )
{ return less_pointees(x,y); }
template<class T>
inline
bool operator != ( optional<T> const& x, optional<T> const& y )
{ return !( x == y ) ; }
template<class T>
inline
bool operator > ( optional<T> const& x, optional<T> const& y )
{ return y < x ; }
template<class T>
inline
bool operator <= ( optional<T> const& x, optional<T> const& y )
{ return !( y < x ) ; }
template<class T>
inline
bool operator >= ( optional<T> const& x, optional<T> const& y )
{ return !( x < y ) ; }
template<class T>
inline
bool operator == ( optional<T> const& x, detail::none_t const& )
{ return equal_pointees(x, optional<T>() ); }
template<class T>
inline
bool operator < ( optional<T> const& x, detail::none_t const& )
{ return less_pointees(x,optional<T>() ); }
template<class T>
inline
bool operator != ( optional<T> const& x, detail::none_t const& y )
{ return !( x == y ) ; }
template<class T>
inline
bool operator > ( optional<T> const& x, detail::none_t const& y )
{ return y < x ; }
template<class T>
inline
bool operator <= ( optional<T> const& x, detail::none_t const& y )
{ return !( y < x ) ; }
template<class T>
inline
bool operator >= ( optional<T> const& x, detail::none_t const& y )
{ return !( x < y ) ; }
template<class T>
inline
bool operator == ( detail::none_t const& x, optional<T> const& y )
{ return equal_pointees(optional<T>() ,y); }
template<class T>
inline
bool operator < ( detail::none_t const& x, optional<T> const& y )
{ return less_pointees(optional<T>() ,y); }
template<class T>
inline
bool operator != ( detail::none_t const& x, optional<T> const& y )
{ return !( x == y ) ; }
template<class T>
inline
bool operator > ( detail::none_t const& x, optional<T> const& y )
{ return y < x ; }
template<class T>
inline
bool operator <= ( detail::none_t const& x, optional<T> const& y )
{ return !( y < x ) ; }
template<class T>
inline
bool operator >= ( detail::none_t const& x, optional<T> const& y )
{ return !( x < y ) ; }
//
// The following swap implementation follows the GCC workaround as found in
// "boost/detail/compressed_pair.hpp"
//
namespace optional_detail {
// GCC < 3.2 gets the using declaration at namespace scope (FLC, DWA)
#if BOOST_WORKAROUND(__GNUC__, < 3) \
|| BOOST_WORKAROUND(__GNUC__, == 3) && __GNUC_MINOR__ <= 2
using std::swap;
#define BOOST_OPTIONAL_STD_SWAP_INTRODUCED_AT_NS_SCOPE
#endif
// optional's swap:
// If both are initialized, calls swap(T&, T&), with whatever exception guarantess are given there.
// If only one is initialized, calls I.reset() and U.reset(*I), with the Basic Guarantee
// If both are uninitialized, do nothing (no-throw)
template<class T>
inline
void optional_swap ( optional<T>& x, optional<T>& y )
{
if ( !x && !!y )
{
x.reset(*y); // Basic guarantee.
y.reset();
}
else if ( !!x && !y )
{
y.reset(*x); // Basic guarantee.
x.reset();
}
else if ( !!x && !!y )
{
// GCC > 3.2 and all other compilers have the using declaration at function scope (FLC)
#ifndef BOOST_OPTIONAL_STD_SWAP_INTRODUCED_AT_NS_SCOPE
// allow for Koenig lookup
using std::swap ;
#endif
swap(*x,*y);
}
}
} // namespace optional_detail
template<class T> inline void swap ( optional<T>& x, optional<T>& y )
{
optional_detail::optional_swap(x,y);
}
} // namespace boost
#include "boost/optional/optional.hpp"
#endif

View File

@ -0,0 +1,720 @@
// 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_OPTIONAL_OPTIONAL_FLC_19NOV2002_HPP
#define BOOST_OPTIONAL_OPTIONAL_FLC_19NOV2002_HPP
#include<new>
#include<algorithm>
#include "boost/config.hpp"
#include "boost/assert.hpp"
#include "boost/type.hpp"
#include "boost/type_traits/alignment_of.hpp"
#include "boost/type_traits/type_with_alignment.hpp"
#include "boost/type_traits/remove_reference.hpp"
#include "boost/type_traits/is_reference.hpp"
#include "boost/mpl/if.hpp"
#include "boost/mpl/bool.hpp"
#include "boost/mpl/not.hpp"
#include "boost/detail/reference_content.hpp"
#include "boost/detail/none_t.hpp"
#include "boost/utility/compare_pointees.hpp"
#if BOOST_WORKAROUND(BOOST_MSVC, == 1200)
// VC6.0 has the following bug:
// When a templated assignment operator exist, an implicit conversion
// constructing an optional<T> is used when assigment of the form:
// optional<T> opt ; opt = T(...);
// is compiled.
// However, optional's ctor is _explicit_ and the assignemt shouldn't compile.
// Therefore, for VC6.0 templated assignment is disabled.
//
#define BOOST_OPTIONAL_NO_CONVERTING_ASSIGNMENT
#endif
#if BOOST_WORKAROUND(BOOST_MSVC, == 1300)
// VC7.0 has the following bug:
// When both a non-template and a template copy-ctor exist
// and the templated version is made 'explicit', the explicit is also
// given to the non-templated version, making the class non-implicitely-copyable.
//
#define BOOST_OPTIONAL_NO_CONVERTING_COPY_CTOR
#endif
#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) || BOOST_WORKAROUND(BOOST_INTEL_CXX_VERSION,<=700)
// AFAICT only VC7.1 correctly resolves the overload set
// that includes the in-place factory taking functions,
// so for the other VC versions, in-place factory support
// is disabled
#define BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
#endif
#if BOOST_WORKAROUND(__BORLANDC__, <= 0x551)
// BCB (5.5.1) cannot parse the nested template struct in an inplace factory.
#define BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
#endif
#if !defined(BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT) \
&& BOOST_WORKAROUND(__BORLANDC__, <= 0x564)
// BCB (up to 5.64) has the following bug:
// If there is a member function/operator template of the form
// template<class Expr> mfunc( Expr expr ) ;
// some calls are resolved to this even if there are other better matches.
// The effect of this bug is that calls to converting ctors and assignments
// are incrorrectly sink to this general catch-all member function template as shown above.
#define BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION
#endif
namespace boost {
class in_place_factory_base ;
class typed_in_place_factory_base ;
namespace optional_detail {
// This local class is used instead of that in "aligned_storage.hpp"
// because I've found the 'official' class to ICE BCB5.5
// when some types are used with optional<>
// (due to sizeof() passed down as a non-type template parameter)
template <class T>
class aligned_storage
{
// Borland ICEs if unnamed unions are used for this!
union dummy_u
{
char data[ sizeof(T) ];
BOOST_DEDUCED_TYPENAME type_with_alignment<
::boost::alignment_of<T>::value >::type aligner_;
} dummy_ ;
public:
void const* address() const { return &dummy_.data[0]; }
void * address() { return &dummy_.data[0]; }
} ;
template<class T>
struct types_when_isnt_ref
{
typedef T const& reference_const_type ;
typedef T & reference_type ;
typedef T const* pointer_const_type ;
typedef T * pointer_type ;
typedef T const& argument_type ;
} ;
template<class T>
struct types_when_is_ref
{
typedef BOOST_DEDUCED_TYPENAME remove_reference<T>::type raw_type ;
typedef raw_type& reference_const_type ;
typedef raw_type& reference_type ;
typedef raw_type* pointer_const_type ;
typedef raw_type* pointer_type ;
typedef raw_type& argument_type ;
} ;
struct optional_tag {} ;
template<class T>
class optional_base : public optional_tag
{
private :
typedef BOOST_DEDUCED_TYPENAME detail::make_reference_content<T>::type internal_type ;
typedef aligned_storage<internal_type> storage_type ;
typedef types_when_isnt_ref<T> types_when_not_ref ;
typedef types_when_is_ref<T> types_when_ref ;
typedef optional_base<T> this_type ;
protected :
typedef T value_type ;
typedef mpl::true_ is_reference_tag ;
typedef mpl::false_ is_not_reference_tag ;
typedef BOOST_DEDUCED_TYPENAME is_reference<T>::type is_reference_predicate ;
typedef BOOST_DEDUCED_TYPENAME mpl::if_<is_reference_predicate,types_when_ref,types_when_not_ref>::type types ;
typedef bool (this_type::*unspecified_bool_type)() const;
typedef BOOST_DEDUCED_TYPENAME types::reference_type reference_type ;
typedef BOOST_DEDUCED_TYPENAME types::reference_const_type reference_const_type ;
typedef BOOST_DEDUCED_TYPENAME types::pointer_type pointer_type ;
typedef BOOST_DEDUCED_TYPENAME types::pointer_const_type pointer_const_type ;
typedef BOOST_DEDUCED_TYPENAME types::argument_type argument_type ;
// Creates an optional<T> uninitialized.
// No-throw
optional_base()
:
m_initialized(false) {}
// Creates an optional<T> uninitialized.
// No-throw
optional_base ( detail::none_t const& )
:
m_initialized(false) {}
// Creates an optional<T> initialized with 'val'.
// Can throw if T::T(T const&) does
optional_base ( argument_type val )
:
m_initialized(false)
{
construct(val);
}
// Creates a deep copy of another optional<T>
// Can throw if T::T(T const&) does
optional_base ( optional_base const& rhs )
:
m_initialized(false)
{
if ( rhs.is_initialized() )
construct(rhs.get_impl());
}
// This is used for both converting and in-place constructions.
// Derived classes use the 'tag' to select the appropriate
// implementation (the correct 'construct()' overload)
template<class Expr>
explicit optional_base ( Expr const& expr, Expr const* tag )
:
m_initialized(false)
{
construct(expr,tag);
}
// No-throw (assuming T::~T() doesn't)
~optional_base() { destroy() ; }
// Assigns from another optional<T> (deep-copies the rhs value)
// Basic Guarantee: If T::T( T const& ) throws, this is left UNINITIALIZED
void assign ( optional_base const& rhs )
{
destroy();
if ( rhs.is_initialized() )
construct(rhs.get_impl());
}
// Assigns from a T (deep-copies the rhs value)
// Basic Guarantee: If T::( T const& ) throws, this is left UNINITIALIZED
void assign ( argument_type val )
{
destroy();
construct(val);
}
// Assigns from "none", destroying the current value, if any, leaving this UNINITIALIZED
// No-throw (assuming T::~T() doesn't)
void assign ( detail::none_t const& ) { destroy(); }
#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
template<class Expr>
void assign_expr ( Expr const& expr, Expr const* tag )
{
destroy();
construct(expr,tag);
}
#endif
public :
// Destroys the current value, if any, leaving this UNINITIALIZED
// No-throw (assuming T::~T() doesn't)
void reset() { destroy(); }
// Replaces the current value -if any- with 'val'
// Basic Guarantee: If T::T( T const& ) throws this is left UNINITIALIZED.
void reset ( argument_type val ) { assign(val); }
// Returns a pointer to the value if this is initialized, otherwise,
// returns NULL.
// No-throw
pointer_const_type get_ptr() const { return m_initialized ? get_ptr_impl() : 0 ; }
pointer_type get_ptr() { return m_initialized ? get_ptr_impl() : 0 ; }
bool is_initialized() const { return m_initialized ; }
protected :
void construct ( argument_type val )
{
new (m_storage.address()) internal_type(val) ;
m_initialized = true ;
}
#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
// Constructs in-place using the given factory
template<class Expr>
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()) ;
m_initialized = true ;
}
// Constructs in-place using the given typed factory
template<class Expr>
void construct ( Expr const& factory, typed_in_place_factory_base const* )
{
BOOST_STATIC_ASSERT ( ::boost::mpl::not_<is_reference_predicate>::value ) ;
factory.apply(m_storage.address()) ;
m_initialized = true ;
}
#endif
// Constructs using any expression implicitely convertible to the single argument
// of a one-argument T constructor.
// Converting constructions of optional<T> from optional<U> uses this function with
// 'Expr' being of type 'U' and relying on a converting constructor of T from U.
template<class Expr>
void construct ( Expr const& expr, void const* )
{
new (m_storage.address()) internal_type(expr) ;
m_initialized = true ;
}
#ifdef BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION
// BCB5.64 (and probably lower versions) workaround.
// The in-place factories are supported by means of catch-all constructors
// and assignment operators (the functions are parameterized in terms of
// an arbitrary 'Expr' type)
// This compiler incorrectly resolves the overload set and sinks optional<T> and optional<U>
// to the 'Expr'-taking functions even though explicit overloads are present for them.
// Thus, the following overload is needed to properly handle the case when the 'lhs'
// is another optional.
//
// For VC<=70 compilers this workaround dosen't work becasue the comnpiler issues and error
// instead of choosing the wrong overload
//
// Notice that 'Expr' will be optional<T> or optional<U> (but not optional_base<..>)
template<class Expr>
void construct ( Expr const& expr, optional_tag const* )
{
if ( expr.is_initialized() )
{
// An exception can be thrown here.
// It it happens, THIS will be left uninitialized.
new (m_storage.address()) internal_type(expr.get()) ;
m_initialized = true ;
}
}
#endif
void destroy()
{
if ( m_initialized )
destroy_impl(is_reference_predicate()) ;
}
unspecified_bool_type safe_bool() const { return m_initialized ? &this_type::is_initialized : 0 ; }
reference_const_type get_impl() const { return dereference(get_object(), is_reference_predicate() ) ; }
reference_type get_impl() { return dereference(get_object(), is_reference_predicate() ) ; }
pointer_const_type get_ptr_impl() const { return cast_ptr(get_object(), is_reference_predicate() ) ; }
pointer_type get_ptr_impl() { return cast_ptr(get_object(), is_reference_predicate() ) ; }
private :
// internal_type can be either T or reference_content<T>
internal_type const* get_object() const { return static_cast<internal_type const*>(m_storage.address()); }
internal_type * get_object() { return static_cast<internal_type *> (m_storage.address()); }
// reference_content<T> lacks an implicit conversion to T&, so the following is needed to obtain a proper reference.
reference_const_type dereference( internal_type const* p, is_not_reference_tag ) const { return *p ; }
reference_type dereference( internal_type* p, is_not_reference_tag ) { return *p ; }
reference_const_type dereference( internal_type const* p, is_reference_tag ) const { return p->get() ; }
reference_type dereference( internal_type* p, is_reference_tag ) { return p->get() ; }
#if BOOST_WORKAROUND(__BORLANDC__, <= 0x564)
void destroy_impl ( is_not_reference_tag ) { get_ptr_impl()->internal_type::~internal_type() ; m_initialized = false ; }
#else
void destroy_impl ( is_not_reference_tag ) { get_ptr_impl()->T::~T() ; m_initialized = false ; }
#endif
void destroy_impl ( is_reference_tag ) { m_initialized = false ; }
// If T is of reference type, trying to get a pointer to the held value must result in a compile-time error.
// Decent compilers should disallow conversions from reference_content<T>* to T*, but just in case,
// 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 ; }
bool m_initialized ;
storage_type m_storage ;
} ;
} // namespace optional_detail
template<class T>
class optional : public optional_detail::optional_base<T>
{
typedef optional_detail::optional_base<T> base ;
typedef BOOST_DEDUCED_TYPENAME base::unspecified_bool_type unspecified_bool_type ;
public :
typedef optional<T> this_type ;
typedef BOOST_DEDUCED_TYPENAME base::value_type value_type ;
typedef BOOST_DEDUCED_TYPENAME base::reference_type reference_type ;
typedef BOOST_DEDUCED_TYPENAME base::reference_const_type reference_const_type ;
typedef BOOST_DEDUCED_TYPENAME base::pointer_type pointer_type ;
typedef BOOST_DEDUCED_TYPENAME base::pointer_const_type pointer_const_type ;
typedef BOOST_DEDUCED_TYPENAME base::argument_type argument_type ;
// Creates an optional<T> uninitialized.
// No-throw
optional() : base() {}
// Creates an optional<T> uninitialized.
// No-throw
optional( detail::none_t const& none_ ) : base(none_) {}
// Creates an optional<T> initialized with 'val'.
// Can throw if T::T(T const&) does
optional ( argument_type val ) : base(val) {}
#ifndef BOOST_OPTIONAL_NO_CONVERTING_COPY_CTOR
// NOTE: MSVC needs templated versions first
// Creates a deep copy of another convertible optional<U>
// Requires a valid conversion from U to T.
// Can throw if T::T(U const&) does
template<class U>
explicit optional ( optional<U> const& rhs )
:
base()
{
if ( rhs.is_initialized() )
this->construct(rhs.get());
}
#endif
#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
// Creates an optional<T> with an expression which can be either
// (a) An instance of InPlaceFactory (i.e. in_place(a,b,...,n);
// (b) An instance of TypedInPlaceFactory ( i.e. in_place<T>(a,b,...,n);
// (c) Any expression implicitely convertible to the single type
// of a one-argument T's constructor.
// (d*) Weak compilers (BCB) might also resolved Expr as optional<T> and optional<U>
// even though explicit overloads are present for these.
// Depending on the above some T ctor is called.
// Can throw is the resolved T ctor throws.
template<class Expr>
explicit optional ( Expr const& expr ) : base(expr,&expr) {}
#endif
// Creates a deep copy of another optional<T>
// Can throw if T::T(T const&) does
optional ( optional const& rhs ) : base(rhs) {}
// No-throw (assuming T::~T() doesn't)
~optional() {}
#if !defined(BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT) && !defined(BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION)
// Assigns from an expression. See corresponding constructor.
// Basic Guarantee: If the resolved T ctor throws, this is left UNINITIALIZED
template<class Expr>
optional& operator= ( Expr expr )
{
this->assign_expr(expr,&expr);
return *this ;
}
#endif
#ifndef BOOST_OPTIONAL_NO_CONVERTING_ASSIGNMENT
// Assigns from another convertible optional<U> (converts && deep-copies the rhs value)
// Requires a valid conversion from U to T.
// Basic Guarantee: If T::T( U const& ) throws, this is left UNINITIALIZED
template<class U>
optional& operator= ( optional<U> const& rhs )
{
this->destroy(); // no-throw
if ( rhs.is_initialized() )
{
// An exception can be thrown here.
// It it happens, THIS will be left uninitialized.
this->assign(rhs.get());
}
return *this ;
}
#endif
// Assigns from another optional<T> (deep-copies the rhs value)
// Basic Guarantee: If T::T( T const& ) throws, this is left UNINITIALIZED
// (NOTE: On BCB, this operator is not actually called and left is left UNMODIFIED in case of a throw)
optional& operator= ( optional const& rhs )
{
this->assign( rhs ) ;
return *this ;
}
// Assigns from a T (deep-copies the rhs value)
// Basic Guarantee: If T::( T const& ) throws, this is left UNINITIALIZED
optional& operator= ( argument_type val )
{
this->assign( val ) ;
return *this ;
}
// Assigns from a "none"
// Which destroys the current value, if any, leaving this UNINITIALIZED
// No-throw (assuming T::~T() doesn't)
optional& operator= ( detail::none_t const& none_ )
{
this->assign( none_ ) ;
return *this ;
}
// Returns a reference to the value if this is initialized, otherwise,
// the behaviour is UNDEFINED
// No-throw
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 pointer to the value if this is initialized, otherwise,
// the behaviour is UNDEFINED
// No-throw
pointer_const_type operator->() const { BOOST_ASSERT(this->is_initialized()) ; return this->get_ptr_impl() ; }
pointer_type operator->() { BOOST_ASSERT(this->is_initialized()) ; return this->get_ptr_impl() ; }
// Returns a reference to the value if this is initialized, otherwise,
// the behaviour is UNDEFINED
// No-throw
reference_const_type operator *() const { return this->get() ; }
reference_type operator *() { return this->get() ; }
// implicit conversion to "bool"
// No-throw
operator unspecified_bool_type() const { return this->safe_bool() ; }
// This is provided for those compilers which don't like the conversion to bool
// on some contexts.
bool operator!() const { return !this->is_initialized() ; }
} ;
// 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<T> const& opt )
{
return opt.get() ;
}
template<class T>
inline
BOOST_DEDUCED_TYPENAME optional<T>::reference_type
get ( optional<T>& opt )
{
return opt.get() ;
}
// Returns a pointer to the value if this is initialized, otherwise, returns NULL.
// No-throw
template<class T>
inline
BOOST_DEDUCED_TYPENAME optional<T>::pointer_const_type
get ( optional<T> const* opt )
{
return opt->get_ptr() ;
}
template<class T>
inline
BOOST_DEDUCED_TYPENAME optional<T>::pointer_type
get ( optional<T>* opt )
{
return opt->get_ptr() ;
}
// Returns a pointer to the value if this is initialized, otherwise, returns NULL.
// No-throw
template<class T>
inline
BOOST_DEDUCED_TYPENAME optional<T>::pointer_const_type
get_pointer ( optional<T> const& opt )
{
return opt.get_ptr() ;
}
template<class T>
inline
BOOST_DEDUCED_TYPENAME optional<T>::pointer_type
get_pointer ( optional<T>& opt )
{
return opt.get_ptr() ;
}
// optional's relational operators ( ==, !=, <, >, <=, >= ) have deep-semantics (compare values).
// WARNING: This is UNLIKE pointers. Use equal_pointees()/less_pointess() in generic code instead.
template<class T>
inline
bool operator == ( optional<T> const& x, optional<T> const& y )
{ return equal_pointees(x,y); }
template<class T>
inline
bool operator < ( optional<T> const& x, optional<T> const& y )
{ return less_pointees(x,y); }
template<class T>
inline
bool operator != ( optional<T> const& x, optional<T> const& y )
{ return !( x == y ) ; }
template<class T>
inline
bool operator > ( optional<T> const& x, optional<T> const& y )
{ return y < x ; }
template<class T>
inline
bool operator <= ( optional<T> const& x, optional<T> const& y )
{ return !( y < x ) ; }
template<class T>
inline
bool operator >= ( optional<T> const& x, optional<T> const& y )
{ return !( x < y ) ; }
template<class T>
inline
bool operator == ( optional<T> const& x, detail::none_t const& )
{ return equal_pointees(x, optional<T>() ); }
template<class T>
inline
bool operator < ( optional<T> const& x, detail::none_t const& )
{ return less_pointees(x,optional<T>() ); }
template<class T>
inline
bool operator != ( optional<T> const& x, detail::none_t const& y )
{ return !( x == y ) ; }
template<class T>
inline
bool operator > ( optional<T> const& x, detail::none_t const& y )
{ return y < x ; }
template<class T>
inline
bool operator <= ( optional<T> const& x, detail::none_t const& y )
{ return !( y < x ) ; }
template<class T>
inline
bool operator >= ( optional<T> const& x, detail::none_t const& y )
{ return !( x < y ) ; }
template<class T>
inline
bool operator == ( detail::none_t const& x, optional<T> const& y )
{ return equal_pointees(optional<T>() ,y); }
template<class T>
inline
bool operator < ( detail::none_t const& x, optional<T> const& y )
{ return less_pointees(optional<T>() ,y); }
template<class T>
inline
bool operator != ( detail::none_t const& x, optional<T> const& y )
{ return !( x == y ) ; }
template<class T>
inline
bool operator > ( detail::none_t const& x, optional<T> const& y )
{ return y < x ; }
template<class T>
inline
bool operator <= ( detail::none_t const& x, optional<T> const& y )
{ return !( y < x ) ; }
template<class T>
inline
bool operator >= ( detail::none_t const& x, optional<T> const& y )
{ return !( x < y ) ; }
//
// The following swap implementation follows the GCC workaround as found in
// "boost/detail/compressed_pair.hpp"
//
namespace optional_detail {
// GCC < 3.2 gets the using declaration at namespace scope (FLC, DWA)
#if BOOST_WORKAROUND(__GNUC__, < 3) \
|| BOOST_WORKAROUND(__GNUC__, == 3) && __GNUC_MINOR__ <= 2
using std::swap;
#define BOOST_OPTIONAL_STD_SWAP_INTRODUCED_AT_NS_SCOPE
#endif
// optional's swap:
// If both are initialized, calls swap(T&, T&), with whatever exception guarantess are given there.
// If only one is initialized, calls I.reset() and U.reset(*I), with the Basic Guarantee
// If both are uninitialized, do nothing (no-throw)
template<class T>
inline
void optional_swap ( optional<T>& x, optional<T>& y )
{
if ( !x && !!y )
{
x.reset(*y); // Basic guarantee.
y.reset();
}
else if ( !!x && !y )
{
y.reset(*x); // Basic guarantee.
x.reset();
}
else if ( !!x && !!y )
{
// GCC > 3.2 and all other compilers have the using declaration at function scope (FLC)
#ifndef BOOST_OPTIONAL_STD_SWAP_INTRODUCED_AT_NS_SCOPE
// allow for Koenig lookup
using std::swap ;
#endif
swap(*x,*y);
}
}
} // namespace optional_detail
template<class T> inline void swap ( optional<T>& x, optional<T>& y )
{
optional_detail::optional_swap(x,y);
}
} // namespace boost
#endif

View File

@ -9,15 +9,14 @@
// You are welcome to contact the author at:
// fernando_cacciola@hotmail.com
//
#ifndef BOOST_UTILITY_INPLACE_FACTORY_SUFFIX_25AGO2003_HPP
#define BOOST_UTILITY_INPLACE_FACTORY_SUFFIX_25AGO2003_HPP
#ifndef BOOST_OPTIONAL_OPTIONAL_FWD_FLC_19NOV2002_HPP
#define BOOST_OPTIONAL_OPTIONAL_FWD_FLC_19NOV2002_HPP
#undef BOOST_DEFINE_INPLACE_FACTORY_CLASS_MEMBER_INIT
#undef BOOST_DEFINE_INPLACE_FACTORY_CLASS_MEMBER_DECL
#undef BOOST_DEFINE_INPLACE_FACTORY_CLASS_MEMBER_ARG
#undef BOOST_MAX_INPLACE_FACTORY_ARITY
namespace boost {
#undef BOOST_UTILITY_INPLACE_FACTORY_PREFIX_25AGO2003_HPP
template<class T> class optional ;
} // namespace boost
#endif

View File

@ -21,7 +21,7 @@
#pragma hdrstop
#endif
#include "boost/detail/none.hpp"
#include "boost/none.hpp"
#include "boost/test/minimal.hpp"

View File

@ -15,11 +15,11 @@
#define BOOST_ENABLE_ASSERT_HANDLER
#include "boost/optional.hpp"
#include "boost/optional/optional.hpp"
#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
#include "boost/detail/in_place_factory.hpp"
#include "boost/detail/typed_in_place_factory.hpp"
#include "boost/utility/in_place_factory.hpp"
#include "boost/utility/typed_in_place_factory.hpp"
#endif
#ifdef __BORLANDC__
@ -60,12 +60,16 @@ int test_main( int, char* [] )
BOOST_CHECK( opt2 == opt2 ) ;
BOOST_CHECK( *opt2 == a0 ) ;
#ifndef BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION
opt2 = boost::in_place(a10,a11);
BOOST_CHECK( *opt2 == a1 ) ;
opt3 = boost::in_place<A>(a10,a11);
BOOST_CHECK( *opt3 == a1 ) ;
#endif
return 0;
}
#else

View File

@ -15,10 +15,10 @@
#define BOOST_ENABLE_ASSERT_HANDLER
#include "boost/optional.hpp"
#include "boost/optional/optional.hpp"
#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
#include "boost/detail/in_place_factory.hpp"
#include "boost/utility/in_place_factory.hpp"
#endif
#ifdef __BORLANDC__

View File

@ -15,10 +15,10 @@
#define BOOST_ENABLE_ASSERT_HANDLER
#include "boost/optional.hpp"
#include "boost/optional/optional.hpp"
#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
#include "boost/detail/typed_in_place_factory.hpp"
#include "boost/utility/typed_in_place_factory.hpp"
#endif
#ifdef __BORLANDC__

View File

@ -21,7 +21,7 @@
#pragma hdrstop
#endif
#include "boost/detail/none.hpp"
#include "boost/none.hpp"
#include "boost/test/minimal.hpp"

View File

@ -17,8 +17,8 @@
void optional_reference__test_no_converting_assignment()
{
boost::optional<int&> opt ;
short v = 1 ;
short& r = v ;
double v = 1 ;
double& r = v ;
opt = r ;
}