forked from boostorg/optional
Compare commits
11 Commits
svn-tags/m
...
boost-1.32
Author | SHA1 | Date | |
---|---|---|---|
bf1efe99e0 | |||
9dfbbef796 | |||
d61baf2a94 | |||
1412c04b24 | |||
24c5f92413 | |||
07a80c1b9b | |||
7717a785de | |||
3db413cc30 | |||
46fafdb7c9 | |||
9aa4943b7a | |||
7cacecb6f9 |
@ -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 <<A
|
||||
HREF="../../../boost/optional.hpp">boost/optional.hpp</A>> </H2>
|
||||
<H2><IMG SRC="../../../boost.png" WIDTH="276" HEIGHT="86">Header <<A
|
||||
HREF="../../../boost/optional/optional.hpp">boost/optional/optional.hpp</A>> </H2>
|
||||
|
||||
<H2>Contents</H2>
|
||||
<DL CLASS="page-index">
|
||||
@ -33,28 +33,28 @@ HREF="../../../boost/optional.hpp">boost/optional.hpp</A>> </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<T> 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>—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>—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<T> 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—i.e. possibly uninitialized—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<T> 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<T> 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<T> 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<T> itself is merely a T wrapper (modeling a T
|
||||
supertype), any attempt to define such operations upon uninitialized optionals
|
||||
Furthermore, since optional<T> 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 -></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 -></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—from the days of C APIs to modern C++ libraries—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<T> as a model of OptionalPointee</h4>
|
||||
<P>For value access operations optional<> uses operators * and -> to lexically
|
||||
warn about the possibliy uninitialized state appealing to the familiar pointer
|
||||
<P>For value access operations optional<> uses operators * and -> 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<>
|
||||
<u><b>However, it is particularly important to note that optional<> objects are not pointers. optional<>
|
||||
is not, and does not model, a pointer</b></u><b>.</b>
|
||||
<P>For instance, optional<> 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<T> 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& v ) ;
|
||||
optional ( T const& v ) ;
|
||||
|
||||
optional ( optional const& rhs ) ;
|
||||
optional ( optional const& rhs ) ;
|
||||
|
||||
template<class U> explicit optional ( optional<U> const& rhs ) ;
|
||||
|
||||
|
||||
template<class InPlaceFactory> explicit optional ( InPlaceFactory const& f ) ;
|
||||
|
||||
|
||||
template<class TypedInPlaceFactory> explicit optional ( TypedInPlaceFactory const& f ) ;
|
||||
|
||||
optional& operator = ( detail::none_t ) ;
|
||||
|
||||
optional& operator = ( T const& v ) ;
|
||||
|
||||
optional& operator = ( T const& v ) ;
|
||||
|
||||
optional& operator = ( optional const& rhs ) ;
|
||||
|
||||
template<class U> optional& operator = ( optional<U> const& rhs ) ;
|
||||
|
||||
template<class InPlaceFactory> optional& operator = ( InPlaceFactory const& f ) ;
|
||||
|
||||
|
||||
template<class TypedInPlaceFactory> optional& operator = ( TypedInPlaceFactory const& f ) ;
|
||||
|
||||
T const& get() const ;
|
||||
T& get() ;
|
||||
|
||||
T const& get() const ;
|
||||
T& get() ;
|
||||
|
||||
T const* operator ->() const ;
|
||||
T* operator ->() ;
|
||||
@ -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& ) ; (deprectated)
|
||||
bool is_initialized() const ; (deprectated)
|
||||
|
||||
<i><u>deprecated methods</u></i>
|
||||
|
||||
void reset() ; (deprecated)
|
||||
void reset ( T const& ) ; (deprecated)
|
||||
bool is_initialized() const ; (deprecated)
|
||||
|
||||
} ;
|
||||
|
||||
@ -396,18 +396,18 @@ template<class T> inline void swap( optional<T>& x, optional<T>
|
||||
|
||||
<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<T (not a ref)>, the description corresponds only to
|
||||
If the entry reads: optional<T (not a ref)>, the description corresponds only to
|
||||
the case where T is not of reference type.<br>
|
||||
If the entry reads: optional<T&>, the description corresponds only to the case
|
||||
If the entry reads: optional<T&>, the description corresponds only to the case
|
||||
where T is of reference type. <br>
|
||||
If the entry reads: optional<T>, 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<T&>::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<<i>TypedInPlaceFactory</i>> explicit optional<T <i>(not a ref)</i>>::optional( <i>TypedInPlaceFactory</i> const& 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> <b>*this</b> is <u>initialized</u> and its value is
|
||||
<p><b>Postconditions:</b> <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<T>::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 < ( optional<T> const& x, optional<T> const& 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 < *y)</code>.
|
||||
</p>
|
||||
@ -991,8 +991,8 @@ assert ( optX != optZ ) ;
|
||||
<HR>
|
||||
|
||||
<pre>void swap ( optional<T>& x, optional<T>& 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("employer's name not found!");
|
||||
|
||||
};
|
||||
</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&, and
|
||||
<p>This library allow the template parameter T to be of reference type: T&, and
|
||||
to some extent, T const&.</p>
|
||||
|
||||
<p>However, since references are not real objects some restrictions apply and
|
||||
<p>However, since references are not real objects some restrictions apply and
|
||||
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<T&> treats it wrapped pseudo-object much as a real
|
||||
<p>Also, even though optional<T&> 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<T&> will copy the references but all these references
|
||||
<li>Copies of optional<T&> 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<X,int,std::string&rt;(123,"hello")) ;
|
||||
W ( TypedInPlaceFactory2<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<class A0,...,class AN>
|
||||
<pre>template<class A0,...,class AN>
|
||||
InPlaceFactory<i>N </i><A0,...,AN> <b>in_place</b> ( A0 const& a0, ..., AN const& aN) ;
|
||||
|
||||
template<class T,class A0,...,class AN>
|
||||
template<class T,class A0,...,class AN>
|
||||
TypedInPlaceFactory<i>N </i><T,A0,...,AN> <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 <X>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<bool>.<br>
|
||||
It should be carefully considered if an optional bool instead of a tribool is really needed</p>
|
||||
<p>Second, optional<> provides an implicit conversion to bool. This conversion
|
||||
<p>Second, optional<> provides an implicit conversion to bool. This conversion
|
||||
refers to the initialization state and not to the contained value.<br>
|
||||
Using optional<bool> 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<T>::operator= ( optional<T> const& ) </code>
|
||||
@ -1299,9 +1299,9 @@ of the assignment methods:</p>
|
||||
<li> <code>optional<T>::operator= ( T const& ) </code></li>
|
||||
<li> <code>template<class U> optional<T>::operator= ( optional<U> const& ) </code>
|
||||
</li>
|
||||
<li> <code>template<class InPlaceFactory> optional<T>::operator= (
|
||||
<li> <code>template<class InPlaceFactory> optional<T>::operator= (
|
||||
InPlaceFactory const& ) </code></li>
|
||||
<li> <code>template<class TypedInPlaceFactory> optional<T>::operator= (
|
||||
<li> <code>template<class TypedInPlaceFactory> optional<T>::operator= (
|
||||
TypedInPlaceFactory const& ) </code></li>
|
||||
<li> <code>optional<T>:::reset ( T const&)</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<>/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<>/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<> and a pointer and developed the OptionalPointee concept as
|
||||
Augustus Saunders also explored the different relational semantics between
|
||||
optional<> and a pointer and developed the OptionalPointee concept as
|
||||
an aid against potential conflicts on generic code.<br>
|
||||
Joel de Guzman noticed that optional<> can be seen as an API on top
|
||||
Joel de Guzman noticed that optional<> can be seen as an API on top
|
||||
of variant<T,nil_t>.<br>
|
||||
Dave Gomboc explained the meaning and usage of the Haskell analog to optional<>:
|
||||
Dave Gomboc explained the meaning and usage of the Haskell analog to optional<>:
|
||||
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 "none".</p>
|
||||
</blockquote>
|
||||
<HR>
|
||||
|
||||
<P>Revised Jannuary 30, 2004</P>
|
||||
<P>© 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 "as is" 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>
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
||||
|
720
include/boost/optional/optional.hpp
Normal file
720
include/boost/optional/optional.hpp
Normal 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
|
||||
|
@ -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
|
||||
|
@ -21,7 +21,7 @@
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#include "boost/detail/none.hpp"
|
||||
#include "boost/none.hpp"
|
||||
|
||||
#include "boost/test/minimal.hpp"
|
||||
|
||||
|
@ -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
|
||||
|
@ -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__
|
||||
|
@ -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__
|
||||
|
@ -21,7 +21,7 @@
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#include "boost/detail/none.hpp"
|
||||
#include "boost/none.hpp"
|
||||
|
||||
#include "boost/test/minimal.hpp"
|
||||
|
||||
|
@ -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 ;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user