2003-01-22 17:54:11 +00:00
<!DOCTYPE HTML PUBLIC "-//SoftQuad Software//DTD HoTMetaL PRO 5.0::19981217::extensions to HTML 4.0//EN" "hmpro5.dtd">
< HTML >
< HEAD >
< META HTTP-EQUIV = "Content-Type" CONTENT = "text/html; charset=iso-8859-1" >
2003-01-24 13:38:20 +00:00
< LINK REL = "stylesheet" TYPE = "text/css" HREF = "../../../boost.css" >
2003-01-22 17:54:11 +00:00
< TITLE > Header < / TITLE >
< / 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 > Contents< / H2 >
< DL CLASS = "page-index" >
< DT > < A HREF = "#mot" > Motivation< / A > < / DT >
< DT > < A HREF = "#dev" > Development< / A > < / DT >
< DT > < A HREF = "#synopsis" > Synopsis< / A > < / DT >
< DT > < A HREF = "#semantics" > Semantics< / A > < / DT >
< DT > < A HREF = "#examples" > Examples< / A > < / DT >
2003-12-04 01:45:19 +00:00
< DT > < A HREF = "#ref" > Optional references< / A > < / DT >
< DT > < A HREF = "#inplace" > In-Place Factories< / A > < / DT >
2003-01-22 17:54:11 +00:00
< DT > < A HREF = "#bool" > A note about optional< bool> < / A > < / DT >
< DT > < A HREF = "#exsafety" > Exception Safety Guarantees< / A > < / DT >
< DT > < A HREF = "#requirements" > Type requirements< / A > < / DT >
< DT > < A HREF = "#impl" > Implementation Notes< / A > < / DT >
< DT > < A HREF = "#porta" > Dependencies and Portability< / A > < / DT >
< DT > < A HREF = "#credits" > Acknowledgment< / A > < / DT >
< / DL >
< HR >
< H2 > < A NAME = "mot" > < / A > Motivation< / H2 >
< 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
parameters in a valid domain for execution to continue normally.< / P >
< 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
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
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
is no such point is used.< / P >
< P > There are various mechanisms to let functions communicate that the returned
value is not valid. One such mechanism, which is quite common since it has zero
or negligible overhead, is to use a special value which is reserved to communicate
this. Classical examples of such special values are EOF, string::npos, points
at infinity, etc...< / P >
< P > When those values exist, i.e. the return type can hold all meaningful values
< i > plus< / i > the < i > signal< / i > value, this mechanism is quite appropriate and
well known. Unfortunately, there are cases when such values do not exist. In
these cases, the usual alternative is either to use a wider type, such as 'int'
in place of 'char'; or a compound type, such as std::pair< point,bool> .
< / P >
< P > Returning a std::pair< T,bool> , thus attaching a boolean flag to the result
which indicates if the result is meaningful, has the advantage that can be turned
into a consistent idiom since the first element of the pair can be whatever
the function would conceptually return. For example, the last two functions
could have the following interface:< / P >
< pre > std::pair< char,bool> get_async_input();
std::pair< point,bool> polygon::get_any_point_effectively_inside();< / pre >
< p > These functions use a consistent interface for dealing with possibly inexistent
results:< / p >
< pre > std::pair< point,bool> p = poly.get_any_point_effectively_inside();
if ( p.second )
flood_fill(p.first);
< / pre >
< P > However, not only is this quite a burden syntactically, it is also error
prone since the user can easily use the function result (first element of the
pair) without ever checking if it has a valid value.< / P >
< P > Clearly, we need a better idiom.< / P >
< H2 > < A NAME = "dev" > < / A > Development< / H2 >
2003-12-04 01:45:19 +00:00
< h3 > < u > The models:< / u > < / h3 >
2003-01-22 17:54:11 +00:00
< P > In C++, we can < i > declare< / i > an object (a variable) of type T, and we can give this variable
an < i > initial value< / i > (through an < i > initializer< / i > . (c.f. 8.5)).< br >
2003-01-24 13:38:20 +00:00
When a declaration includes a non-empty initializer (an initial value is given), it is said that
2003-01-22 17:54:11 +00:00
the object has been < i > < b > initialized< / b > < / i > .< br >
If the declaration uses an empty initializer (no initial value is given),
and neither default nor value initialization applies, it is said that the object is
< i > < b > uninitialized< / b > < / i > . Its actual value exist but has an
< i > indeterminate inital value< / i > (c.f. 8.5.9).< br >
< code > optional< T> < / code > intends to formalize the notion of initialization/no-initialization
allowing a program to test whether an object has been initialized and stating that access to
the value of an uninitialized object is undefined behaviour. That is,
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
2003-01-24 13:38:20 +00:00
no value at all and this situation can be tested at runtime. It is formally < i > undefined behaviour< / i >
2003-12-04 01:45:19 +00:00
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 >
2003-01-22 17:54:11 +00:00
< P > In C++ there is no formal notion of uninitialized objects, which
means that objects always have an initial value even if indeterminate.< br >
As discussed on the previous section, this has a drawback because you need additional
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
2003-12-04 01:45:19 +00:00
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<4F> 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 >
Using the < a href = "../../variant/doc/index.html" > Boost.Variant< / a > library, this model can be implemented
in terms of < code > boost::variant< T,nil_t> < / code > .< br >
There is precedence for a discriminated union as a model for an optional value: the
< a href = "http://www.haskell.org/" > < u > Haskell< / u > < / a > < b > Maybe< / b > builtin type constructor,
thus a discriminated union < code > T+nil_t< / code > serves as a conceptual foundation.< / p >
< p > A < code > variant< T,nil_t> < / code > follows naturally from the traditional idiom of extending
the range of possible values adding an additional sentinel value with the special meaning of < i > Nothing. < / i >
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
< 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
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 >
For instance, these models show the < i > exact< / i > semantics required for a wrapper of optional values:< / p >
< p > Discriminated-union:< / p >
< blockquote >
< li > < b > deep-copy< / b > semantics: copies of the variant implies copies of the value.< / li >
2003-01-24 13:38:20 +00:00
< li > < b > deep-relational< / b > semantics: comparisons between variants matches both current types and values< / li >
2003-01-22 17:54:11 +00:00
< li > If the variant's current type is T, it is modeling an < i > initialized< / i > optional.< / li >
< li > If the variant's current type is not T, it is modeling an < i > uninitialized< / i > optional.< / li >
< li > Testing if the variant's current type is T models testing if the optional is initialized< / li >
< li > Trying to extract a T from a variant when its current type is not T, models the undefined behaviour
of trying to access the value of an uninitialized optional< / li >
2003-12-04 01:45:19 +00:00
< / blockquote >
< p > Single-element container:< / p >
< blockquote >
< li > < b > deep-copy< / b > semantics: copies of the container implies copies of the value.< / li >
< li > < b > deep-relational< / b > semantics: comparisons between containers compare container size and if match, contained value< / li >
< li > If the container is not empty (contains an object of type T), it is modeling an < i > initialized< / i > optional.< / li >
< li > If the container is empty, it is modeling an < i > uninitialized< / i > optional.< / li >
< li > Testing if the container is empty models testing if the optional is initialized< / li >
< li > Trying to extract a T from an empty container models the undefined behaviour
of trying to access the value of an uninitialized optional< / li >
< / blockquote >
< h3 > < u > The semantics:< / u > < / h3 >
< p > Objects of type < code > optional< T> < / code > are intended to be used in places where objects of type T would
but which might be uninitialized. Hence, < code > optional< T> < / code > 's purpose is to formalize the
additional possibly uninitialized state.< br >
From the perspective of this role, < code > optional< T> < / code > can have the same operational semantics of T
plus the additional semantics corresponding to this special state.< br >
As such, < code > optional< T> < / code > could be thought of as a < i > supertype< / i > of T. Of course,
we can't do that in C++, so we need to compose the desired semantics using a different mechanism.< br >
Doing it the other way around, that is, making < code > optional< T> < / code > a < i > subtype< / i > of T is not only
conceptually wrong but also impractical: it is not allowed to derive from a non-class type, such as a builtin type.< / p >
< 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
object.< / p >
< 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
object.< / p >
< 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
as a copy of some object.< / p >
< 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
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
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
initialized or not.< / p >
< 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
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
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
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
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
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,
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
explained next).< br >
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
optional objects: The operators * and -> < / h3 >
< p > A relevant feature of a pointer is that it can have a < b > null
2003-01-22 17:54:11 +00:00
pointer value< / b > . This is a < i > special< / i > value which is used to indicate that the
pointer is not referring to any object at all. In other words, null pointer
2003-01-24 13:38:20 +00:00
values convey the notion of inexistent objects.< / P >
2003-12-04 01:45:19 +00:00
< P > This meaning of the null pointer value allowed pointers to became a < i > de facto< / i > standard
2003-01-22 17:54:11 +00:00
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.
2003-03-14 20:40:08 +00:00
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
2003-01-22 17:54:11 +00:00
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
and access operators, such as: < code > ( *p = 2 )< / code > and < code > ( p-> foo())< / code > ,
2003-01-24 13:38:20 +00:00
implicitly convey the notion of optionality, and this information is tied to
2003-01-22 17:54:11 +00:00
the < i > syntax< / i > of the expressions. That is, the presence of operators * and -> tell by
2003-03-14 20:40:08 +00:00
themselves— without any additional context— that the expression will be undefined unless
2003-12-04 01:45:19 +00:00
the implied pointee actually exist.< / P >
< P > Such a < i > de facto< / i > idiom for referring to optional objects can be formalized in the form of a
2003-01-22 17:54:11 +00:00
concept: the < a href = "../../utility/OptionalPointee.html" > OptionalPointee< / a > concept.< br >
2003-01-24 13:38:20 +00:00
This concept captures the syntactic usage of operatos *, -> and conversion to bool to convey
2003-12-04 01:45:19 +00:00
the notion of optionality.< / P >
2003-01-22 17:54:11 +00:00
< P > However, pointers are good to < u > refer< / u > to optional objects, but not particularly good
to handle the optional objects in all other respects, such as initializing or moving/copying
them. The problem resides in the shallow-copy of pointer semantics: if you need to
effectively move or copy the object, pointers alone are not enough. The problem
is that copies of pointers do not imply copies of pointees. For example, as
was discussed in the motivation, pointers alone cannot be used to return optional
objects from a function because the object must move outside from the function and
into the caller's context.< br >
A solution to the shallow-copy problem that is often used is to resort to dynamic
allocation and use a smart pointer to automatically handle the details of this.
For example, if a function is to optionally return an object X, it can use shared_ptr< X>
as the return value. However, this requires dynamic allocation of X. If X is
a builtin or small POD, this technique is very poor in terms of required resources.
Optional objects are essentially values so it is very convenient to be able to use automatic
storage and deep-copy semantics to manipulate optional values just as we do with ordinary
2003-02-25 10:29:21 +00:00
values. Pointers do not have this semantics, so are unappropriate for the initialization and
2003-01-22 17:54:11 +00:00
transport of optional values, yet are quite convenient for handling the access to the
possible undefined value because of the idiomatic aid present in the OptionalPointee
2003-12-04 01:45:19 +00:00
concept incarnated by pointers.
2003-01-22 17:54:11 +00:00
< / p >
2003-12-04 01:45:19 +00:00
< 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
semantics w.r.t. to null pointers.< br >
< 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 >
2003-01-22 17:54:11 +00:00
The difference between an optional< T> and a pointer must be kept in mind, particularly
because the semantics of relational operators are different: since optional< T>
is a value-wrapper, relational operators are deep: they compare optional values;
but relational operators for pointers are shallow: they do not compare pointee values.< br >
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
2003-12-04 01:45:19 +00:00
operators directly, and must use the template functions
< a href = "../../utility/OptionalPointee.html#equal" > equal_pointees()< / a > and
< a href = "../../utility/OptionalPointee.html#less" > less_pointees()< / a > instead.
2003-01-22 17:54:11 +00:00
< HR >
< H2 > < A NAME = "synopsis" > Synopsis< / A > < / H2 >
< PRE > namespace boost {
template< class T>
class optional
{
public :
2003-12-04 01:45:19 +00:00
< i > < u > (If T is of referennce type, the parameters and results by reference are by value)< / u > < / i >
2003-01-22 17:54:11 +00:00
optional () ;
2003-12-04 01:45:19 +00:00
optional ( detail::none_t ) ;
2003-01-22 17:54:11 +00:00
2003-12-04 01:45:19 +00:00
optional ( T const& v ) ;
optional ( optional const& rhs ) ;
2003-01-22 17:54:11 +00:00
template< class U> explicit optional ( optional< U> const& rhs ) ;
2003-12-04 01:45:19 +00:00
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 ) ;
2003-01-22 17:54:11 +00:00
optional& operator = ( optional const& rhs ) ;
template< class U> optional& operator = ( optional< U> const& amp rhs ) ;
2003-12-04 01:45:19 +00:00
template< class InPlaceFactory> optional& operator = ( InPlaceFactory const& amp f ) ;
template< class TypedInPlaceFactory> optional& operator = ( TypedInPlaceFactory const& amp f ) ;
T const& get() const ;
T& get() ;
2003-01-22 17:54:11 +00:00
T const* operator -> () const ;
T* operator -> () ;
T const& operator *() const ;
T& operator *() ;
2003-12-04 01:45:19 +00:00
T const* get_ptr() const ;
T* get_ptr() ;
2003-01-22 17:54:11 +00:00
operator < i > unspecified-bool-type< / i > () const ;
bool operator!() const ;
2003-12-04 01:45:19 +00:00
< i > < u > deprectated methods< / u > < / i >
void reset() ; (deprectated)
void reset ( T const& ) ; (deprectated)
bool is_initialized() const ; (deprectated)
2003-01-22 17:54:11 +00:00
} ;
template< class T> inline bool operator == ( optional< T> const& x, optional< T> const& y ) ;
template< class T> inline bool operator != ( optional< T> const& x, optional< T> const& y ) ;
2003-12-04 01:45:19 +00:00
template< class T> inline bool operator < ( optional< T> const& x, optional< T> const& y ) ;
template< class T> inline bool operator > ( optional< T> const& x, optional< T> const& y ) ;
template< class T> inline bool operator < = ( optional< T> const& x, optional< T> const& y ) ;
template< class T> inline bool operator >= ( optional< T> const& x, optional< T> const& y ) ;
template< class T> inline T const& get ( optional< T> const& opt ) ;
template< class T> inline T& get ( optional< T> & opt ) ;
template< class T> inline T const* get ( optional< T> const* opt ) ;
template< class T> inline T* get ( optional< T> * opt ) ;
template< class T> inline T const* get_pointer ( optional< T> const& opt ) ;
template< class T> inline T* get_pointer ( optional< T> & opt ) ;
2003-01-22 17:54:11 +00:00
template< class T> inline void swap( optional< T> & x, optional< T> & y ) ;
} // namespace boost
< / PRE >
< HR >
2003-12-04 01:45:19 +00:00
< h2 > < A NAME = "semantics" > Detailed Semantics< / a > < / h2 >
< 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
the following convention:< br >
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
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
implied condition holds.< / i > < / p >
2003-01-22 17:54:11 +00:00
< hr >
< pre > optional< T> ::optional();< / pre >
< blockquote >
< p > < b > Effect:< / b > Default-Constructs an < b > optional< / b > .< / p >
< p > < b > Postconditions:< / b > < b > *this< / b > is < u > uninitialized< / u > .< / p >
< p > < b > Throws:< / b > Nothing.< / p >
< p > < b > Notes:< / b > T's default constructor < u > < i > is not< / i > < / u > called.< / p >
< p > < b > Example:< / b > < / p >
< blockquote >
< pre > optional< T> def ;
assert ( !def ) ;< / pre >
< / blockquote >
< / blockquote >
< HR >
2003-12-04 01:45:19 +00:00
< pre > optional< T> ::optional( detail::none_t );< / pre >
< blockquote >
< p > < b > Effect:< / b > Constructs an < b > optional < / b > uninitialized.< / p >
< p > < b > Postconditions:< / b > < b > *this< / b > is < u > uninitialized< / u > .< / p >
< p > < b > Throws:< / b > Nothing.< / p >
< p > < b > Notes:< / b > < / p >
< 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
used as the parameter.< / p >
< / blockquote >
< p > < b > Example:< / b > < / p >
< blockquote >
< pre > optional< T> n(none) ;
assert ( !n ) ;< / pre >
< / blockquote >
< / blockquote >
< HR >
< pre > optional< T < i > (not a ref)< / i > > ::optional( T const& v )< / pre >
2003-01-22 17:54:11 +00:00
< blockquote >
< p > < b > Effect:< / b > Directly-Constructs an < b > optional< / b > .< / p >
2003-12-04 01:45:19 +00:00
<!-- TemplateName: general/sy_footer_inc.isml -->
2003-01-22 17:54:11 +00:00
< p > < b > Postconditions:< / b > < b > *this< / b > is < u > initialized< / u > and its value is a < i > copy< / i > of 'v'.< / p >
< p > < b > Throws:< / b > Whatever T::T( T const& ) throws.< / p >
2003-12-04 01:45:19 +00:00
< p > < b > Notes: < / b > T::T( T const& ) is called.< / p >
2003-01-22 17:54:11 +00:00
< p > < b > Exception Safety:< / b > Exceptions can only be thrown during T::T( T const& );
in that case, this constructor has no effect.
< / p >
< p > < b > Example:< / b > < / p >
< blockquote >
2003-12-04 01:45:19 +00:00
< pre > T v;
2003-01-22 17:54:11 +00:00
optional< T> opt(v);
2003-12-04 01:45:19 +00:00
assert ( *opt == v ) ;< / pre >
< / blockquote >
< / blockquote >
< HR >
< 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
instance of an internal type wrapping the reference 'ref'.< / p >
< p > < b > Throws:< / b > Nothing.< / p >
< p > < b > Example:< / b > < / p >
< blockquote >
< pre > T v;
T& vref = v ;
optional< T& > opt(vref);
2003-01-22 17:54:11 +00:00
assert ( *opt == v ) ;
2003-12-04 01:45:19 +00:00
++ v ; // mutate referee
assert (*opt == v); < / pre >
2003-01-22 17:54:11 +00:00
< / blockquote >
< / blockquote >
< HR >
2003-12-04 01:45:19 +00:00
< pre > optional< T < i > (not a ref)< / i > > ::optional( optional const& rhs );< / pre >
2003-01-22 17:54:11 +00:00
< blockquote >
< p > < b > Effect:< / b > Copy-Constructs an < b > optional< / b > .< / p >
< p > < b > Postconditions:< / b > If < b > rhs< / b > is initialized, < b > *this< / b > is initialized
and its value is a < i > copy< / i > of the value of < b > rhs< / b > ; else < b > *this< / b >
is uninitialized.< / p >
< p > < b > Throws:< / b > Whatever T::T( T const& ) throws.< / p >
2003-12-04 01:45:19 +00:00
< p > < b > Notes:< / b > If < b > rhs< / b > is initialized, T::T(T const& ) is called.< / p >
2003-01-22 17:54:11 +00:00
< p > < b > Exception Safety:< / b > Exceptions can only be thrown during T::T( T const& );
in that case, this constructor has no effect.
< / p >
< p > < b > Example:< / b > < / p >
< blockquote >
< pre > optional< T> uninit ;
assert (!uninit);
optional< T> uinit2 ( uninit ) ;
assert ( uninit2 == uninit );
optional< T> init( T(2) );
assert ( *init == T(2) ) ;
optional< T> init2 ( init ) ;
assert ( init2 == init ) ;
< / pre >
< / blockquote >
< / blockquote >
< HR >
2003-12-04 01:45:19 +00:00
< pre > optional< T& > ::optional( optional const& rhs );< / pre >
< blockquote >
< p > < b > Effect:< / b > Copy-Constructs an < b > optional< / b > .< / p >
< p > < b > Postconditions:< / b > If < b > rhs< / b > is initialized, < b > *this< / b > is initialized
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
referr to the same object< b > < / b > (will alias).< / p >
< p > < b > Example:< / b > < / p >
< blockquote >
< pre > optional< T& > uninit ;
assert (!uninit);
optional< T& > uinit2 ( uninit ) ;
assert ( uninit2 == uninit );
T v = 2 ; T& ref = v ;
optional< T> init(ref);
assert ( *init == v ) ;
optional< T> init2 ( init ) ;
assert ( *init2 == v ) ;
< / pre >
< / blockquote >
< / blockquote >
< HR >
< pre > template< U> explicit optional< T < i > (not a ref)< / i > > ::optional( optional< U> const& rhs );< / pre >
2003-01-22 17:54:11 +00:00
< blockquote >
< p > < b > Effect:< / b > Copy-Constructs an < b > optional< / b > .< / p >
< p > < b > Postconditions:< / b > If < b > rhs< / b > is initialized, < b > *this< / b > is initialized
and its value is a < i > copy< / i > of the value of < b > rhs< / b > < i > converted< / i >
to type T; else < b > *this< / b > is uninitialized.
< / p >
< p > < b > Throws:< / b > Whatever T::T( U const& ) throws.< / p >
< p > < b > Notes:< / b > T::T( U const& ) is called if < b > rhs< / b > is initialized, which requires
a valid conversion from U to T.
< / p >
< p > < b > Exception Safety:< / b > Exceptions can only be thrown during T::T( U const& );
in that case, this constructor has no effect.
< / p >
< p > < b > Example:< / b > < / p >
< blockquote >
< pre > optional< double> x(123.4);
assert ( *x == 123.4 ) ;
optional< int> y(x) ;
assert( *y == 123 ) ;
< / pre >
< / blockquote >
< / blockquote >
< HR >
2003-12-04 01:45:19 +00:00
< pre > template< < i > InPlaceFactory< / i > > explicit optional< T < i > (not a ref)< / i > > ::optional( < i > InPlaceFactory< / i > const& f );< / pre >
< 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
the factory.< / p >
< 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
T constructor used by the factory;
in that case, this constructor has no effect.
< / p >
< p > < b > Example:< / b > < / p >
< blockquote >
< pre > class C { C ( char, double, std::string ) ; } ;
C v('A',123.4," hello" );
optional< C> x( in_place ('A', 123.4, " hello" ) ); // InPlaceFactory used
optional< C> y( in_place< C> ('A', 123.4, " hello" ) ); // TypedInPlaceFactory used
assert ( *x == v ) ;
assert ( *y == v ) ;
< / pre >
< / blockquote >
< / blockquote >
< HR >
< pre > optional& optional< T < i > (not a ref)< / i > > ::operator= ( T const& rhs ) ;< / pre >
< blockquote >
< p > < b > Effect:< / b > Assigns the value 'rhs' to an < b > optional< / b > .< / p >
< p > < b > Postconditions:< / b > < b > *this< / b > is initialized
and its value is a < i > copy< / i > of < b > rhs.< / b > < / p >
< p > < b > Throws:< / b > Whatever T::T( T const& ) throws.< / p >
< p > < b > Notes:< / b > If < b > *this< / b > was initialized, it is first reset to uninitialized
using T::~T(), then T::T(< b > rhs< / b > ) is called.< / p >
< p > < b > Exception Safety:< / b > < u > Basic:< / u > Exceptions can only be thrown during T::T( T const& );
in that case, < b > *this< / b > is left < u > uninitialized< / u > .
< / p >
< p > < b > Example:< / b > < / p >
< blockquote >
< pre > T x;
optional< T> opt(x) ;
T y;
opt = y ;
assert ( *opt == y ) ;
// previous value (copy of 'v') destroyed from within 'opt'.
< / pre >
< / blockquote >
< / blockquote >
< HR >
< pre > optional& optional< T < i > (not a ref)< / i > > ::operator= ( optional const& rhs ) ;< / pre >
2003-01-22 17:54:11 +00:00
< blockquote >
< p > < b > Effect:< / b > Assigns another < b > optional< / b > to an < b > optional< / b > .< / p >
< p > < b > Postconditions:< / b > If < b > rhs< / b > is initialized, < b > *this< / b > is initialized
and its value is a < i > copy< / i > of the value of < b > rhs< / b > ; else < b > *this< / b >
is uninitialized.
< / p >
< p > < b > Throws:< / b > Whatever T::T( T const& ) throws.< / p >
< p > < b > Notes:< / b > If < b > *this< / b > was initialized, it is first reset to uninitialized
using T::~T(), then T::T( T const& ) is called if < b > rhs< / b > is initialized.
< / p >
< p > < b > Exception Safety:< / b > < u > Basic:< / u > Exceptions can only be thrown during T::T( T const& );
in that case, < b > *this< / b > is left < u > uninitialized< / u > .
< / p >
< p > < b > Example:< / b > < / p >
< blockquote >
2003-12-04 01:45:19 +00:00
< pre > T v;
2003-01-22 17:54:11 +00:00
optional< T> opt(v);
optional< T> uninit ;
opt = uninit ;
assert ( !opt ) ;
// previous value (copy of 'v') destroyed from within 'opt'.
< / pre >
< / blockquote >
< / blockquote >
< HR >
2003-12-04 01:45:19 +00:00
< pre > template< U> optional& optional< T < i > (not a ref)< / i > > ::operator= ( optional< U> const& rhs ) ;< / pre >
2003-01-22 17:54:11 +00:00
< blockquote >
< p > < b > Effect:< / b > Assigns another < i > convertible< / i > < b > optional< / b > to an < b > optional< / b > .< / p >
< p > < b > Postconditions:< / b > If < b > rhs< / b > is initialized, < b > *this< / b > is initialized
and its value is a < i > copy< / i > of the value of < b > rhs< / b > < i > converted< / i >
to type T; else < b > *this< / b > is uninitialized.
< / p >
< p > < b > Throws:< / b > Whatever T::T( U const& ) throws.< / p >
< p > < b > Notes:< / b > If < b > *this< / b > was initialized, it is first reset to uninitialized
using T::~T(), then T::T( U const& ) is called if < b > rhs< / b > is initialized,
which requires a valid conversion from U to T.
< / p >
< p > < b > Exception Safety:< / b > < u > Basic:< / u > Exceptions can only be thrown during T::T( U const& );
in that case, < b > *this< / b > is left < u > uninitialized< / u > .
< / p >
< p > < b > Example:< / b > < / p >
< blockquote >
2003-12-04 01:45:19 +00:00
< pre > T v;
2003-01-22 17:54:11 +00:00
optional< T> opt0(v);
optional< U> opt1;
opt1 = opt0 ;
assert ( *opt1 == static_cast< U> (v) ) ;
< / pre >
< / blockquote >
< / blockquote >
< HR >
2003-12-04 01:45:19 +00:00
< pre > void optional< T < i > (not a ref)< / i > > ::reset( T const& amp v ) ;< / pre >
2003-01-22 17:54:11 +00:00
< blockquote >
2003-12-04 01:45:19 +00:00
< p > < b > Deprecated:< / b > same as operator= ( T const& v) ;< / p >
2003-01-22 17:54:11 +00:00
< / blockquote >
< HR >
< pre > void optional< T> ::reset() ;< / pre >
< blockquote >
2003-12-04 01:45:19 +00:00
< p > < b > Deprecated: < / b > Same as operator=( detail::none_t );< / p >
< / blockquote >
< HR >
< pre > T const& optional< T < i > (not a ref)< / i > > ::operator*() const ;
T& optional< T< i > (not a ref)< / i > > ::operator*();< / pre >
< pre > T const& optional< T < i > (not a ref)< / i > > ::get() const ;
T& optional< T < i > (not a ref)< / i > > ::get() ;
inline T const& get ( optional< T< i > (not a ref)< / i > > const& ) ;
inline T& get ( optional< T < i > (not a ref)< / i > > & ) ;
< / pre >
< blockquote >
< p > < b > Requirements: *this< / b > is initialized< / p >
< p > < b > Returns:< / b > A reference to the contained value< / p >
2003-01-22 17:54:11 +00:00
< p > < b > Throws:< / b > Nothing.< / p >
2003-12-04 01:45:19 +00:00
< p > < b > Notes:< / b > The requirement is asserted via BOOST_ASSERT().< / p >
2003-01-22 17:54:11 +00:00
< p > < b > Example:< / b > < / p >
< blockquote >
2003-12-04 01:45:19 +00:00
< pre > T v ;
optional< T> opt ( v );
T const& u = *opt;
assert ( u == v ) ;
T w ;
*opt = w ;
assert ( *opt == w ) ;
2003-01-22 17:54:11 +00:00
< / pre >
2003-12-04 01:45:19 +00:00
< / blockquote >
< pre > < / pre >
2003-01-22 17:54:11 +00:00
< / blockquote >
2003-12-04 01:45:19 +00:00
< HR >
< pre > T const& optional< T& > ::operator*() const ;
T & optional< T< i > & < / i > > ::operator*();< / pre >
< pre > T const& optional< T& > ::get() const ;
T& optional< T& > ::get() ;
inline T const& get ( optional< T< i > & < / i > > const& ) ;
inline T& get ( optional< T& > & ) ;
< / pre >
< blockquote >
< p > < b > Requirements: *this< / b > is initialized< / p >
< p > < b > Returns:< / b > < u > The< / u > reference contained.< / p >
< p > < b > Throws:< / b > Nothing.< / p >
< p > < b > Notes:< / b > The requirement is asserted via BOOST_ASSERT().< / p >
< p > < b > Example:< / b > < / p >
< blockquote >
< pre > T v ;
T& vref = v ;
optional< T& > opt ( vref );
T const& vref2 = *opt;
assert ( vref2 == v ) ;
++ v ;
assert ( *opt == v ) ;< / pre >
< / blockquote >
2003-01-22 17:54:11 +00:00
< / blockquote >
< HR >
2003-12-04 01:45:19 +00:00
< pre > T const* optional< T < i > (not a ref)< / i > > ::get_ptr() const ;
T* optional< T < i > (not a ref)< / i > > ::get_ptr() ;
2003-01-22 17:54:11 +00:00
2003-12-04 01:45:19 +00:00
inline T const* get_pointer ( optional< T < i > (not a ref)< / i > > const& ) ;
inline T* get_pointer ( optional< T < i > (not a ref)< / i > > & ) ;
2003-01-22 17:54:11 +00:00
< / pre >
< blockquote >
< p > < b > Returns:< / b > If < b > *this< / b > is initialized, a pointer to the contained
value; else 0 (< i > null< / i > ).
< / p >
< p > < b > Throws:< / b > Nothing.< / p >
< p > < b > Notes:< / b > The contained value is permanently stored within *this, so
you should not hold nor delete this pointer
< / p >
< p > < b > Example:< / b > < / p >
< blockquote >
2003-12-04 01:45:19 +00:00
< pre > T v;
2003-01-22 17:54:11 +00:00
optional< T> opt(v);
optional< T> const copt(v);
2003-12-04 01:45:19 +00:00
T* p = opt.get_ptr() ;
T const* cp = copt.get_ptr();
2003-01-22 17:54:11 +00:00
assert ( p == get_pointer(opt) );
assert ( cp == get_pointer(copt) ) ;
< / pre >
< / blockquote >
< / blockquote >
< HR >
2003-12-04 01:45:19 +00:00
< pre > T const* optional< T < i > (not a ref)< / i > > ::operator -> () const ;
T* optional< T < i > (not a ref)< / i > > ::operator -> () ;
2003-01-22 17:54:11 +00:00
< / pre >
< blockquote >
< p > < b > Requirements: *this< / b > is initialized.< / p >
< p > < b > Returns:< / b > A pointer to the contained value.< / p >
< p > < b > Throws:< / b > Nothing.< / p >
< p > < b > Notes:< / b > The requirement is asserted via BOOST_ASSERT().< / p >
< p > < b > Example:< / b > < / p >
< blockquote >
2003-12-04 01:45:19 +00:00
< pre > struct X { int mdata ; } ;
2003-01-22 17:54:11 +00:00
X x ;
optional< X> opt (x);
opt-> mdata = 2 ;
< / pre >
< / blockquote >
< / blockquote >
< HR >
< pre > optional< T> ::operator < i > unspecified-bool-type< / i > () const ;< / pre >
< blockquote >
< p > < b > Returns:< / b > An unspecified value which if used on a boolean context is equivalent to (get() != 0)< / p >
< p > < b > Throws:< / b > Nothing.< / p >
< blockquote >
< pre > optional< T> def ;
assert ( def == 0 );
optional< T> opt ( v ) ;
assert ( opt );
assert ( opt != 0 );
< / pre >
< / blockquote >
< / blockquote >
< HR >
< pre > bool optional< T> ::operator!() ;< / pre >
< blockquote >
< p > < b > Returns:< / b > If < b > *this< / b > is uninitialized, < code > true< / code > ; else < code > false.< / code > < / p >
< p > < b > Throws:< / b > Nothing.< / p >
< p > < b > Notes:< / b > This operator is provided for those compilers which can't use
the < i > unspecified-bool-type< / i > operator in certain boolean contexts.
< / p >
< p > < b > Example:< / b > < / p >
< blockquote >
< pre > optional< T> opt ;
assert ( !opt );
*opt = some_T ;
// Notice the " double-bang" idiom here.
assert ( !!opt ) ;
< / pre >
< / blockquote >
< / blockquote >
2003-12-04 01:45:19 +00:00
< HR >
< 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 >
otherwise.< / p >
< p > < b > Throws:< / b > Nothing.< / p >
< blockquote >
< pre > optional< T> def ;
assert ( !def.is_initialized() );
optional< T> opt ( v ) ;
assert ( opt.is_initialized() );< / pre >
< / blockquote >
< / blockquote >
2003-01-22 17:54:11 +00:00
< HR >
< pre > bool operator == ( optional< T> const& amp x, optional< T& gt const& amp y );< / pre >
< blockquote >
< p > < b > Returns:< / b > If both < b > x< / b > and < b > y< / b > are initialied, < code > (*x == *y)< / code > .
If only x or y is initialized, < code > false< / code > . If both are uninitialized, < code > true< / code > .
< / p >
< p > < b > Throws:< / b > Nothing.< / p >
< p > < b > Notes:< / b > Pointers have shallow relational operators while < b > optional< / b > has
deep relational operators. Do not use operator == directly in generic code
which expect to be given either an optional< T> or a pointer;
use < a href = "../../utility/OptionalPointee.html#equal" > equal_pointees()< / a > instead
< / p >
< p > < b > Example:< / b > < / p >
< blockquote >
2003-12-04 01:45:19 +00:00
< pre > T x(12);
2003-01-22 17:54:11 +00:00
T y(12);
T z(21);
optional< T> def0 ;
optional< T> def1 ;
optional< T> optX(x);
optional< T> optY(y);
optional< T> optZ(z);
// Identity always hold
assert ( def0 == def0 );
assert ( optX == optX );
// Both uninitialized compare equal
assert ( def0 == def1 );
// Only one initialized compare unequal.
assert ( def0 != optX );
// Both initialized compare as (*lhs == *rhs)
assert ( optX == optY ) ;
assert ( optX != optZ ) ;
< / pre >
< / blockquote >
< / blockquote >
2003-12-04 01:45:19 +00:00
< HR >
< pre > bool operator < ( optional< T> const& amp x, optional< T& gt const& amp y );< / pre >
< blockquote >
< p > < b > Returns:< / b > If both < b > x< / b > and < b > y< / b > are initialied, < code > (*x < *y)< / code > .
If only x or y is initialized, < code > false< / code > . If both are uninitialized,
< code > false< / code > .
< / p >
< p > < b > Throws:< / b > Nothing.< / p >
< p > < b > Notes:< / b > Pointers have shallow relational operators while < b > optional< / b > has
deep relational operators. Do not use operator < directly in generic code
which expect to be given either an optional< T> or a pointer;
use < a href = "../../utility/OptionalPointee.html#less" > less_pointees()< / a > instead
< / p >
< p > < b > Example:< / b > < / p >
< blockquote >
< pre > T x(12);
T y(34);
optional< T> def ;
optional< T> optX(x);
optional< T> optY(y);
// Identity always hold
assert ( !(def < def) );
assert ( optX == optX );
// Both uninitialized compare equal
assert ( def0 == def1 );
// Only one initialized compare unequal.
assert ( def0 != optX );
// Both initialized compare as (*lhs == *rhs)
assert ( optX == optY ) ;
assert ( optX != optZ ) ;
< / pre >
< / blockquote >
< / blockquote >
2003-01-22 17:54:11 +00:00
< HR >
< pre > bool operator != ( optional< T> const& amp x, optional< T& gt const& amp y );
< / pre >
< blockquote >
< p > < b > Returns:< / b > !( x == y );< / p >
< p > < b > Throws:< / b > Nothing.< / p >
< / blockquote >
2003-12-04 01:45:19 +00:00
< HR >
< pre > bool operator > ( optional< T> const& amp x, optional< T& gt const& amp y );
< / pre >
< blockquote >
< p > < b > Returns:< / b > !( y < x );< / p >
< p > < b > Throws:< / b > Nothing.< / p >
< / blockquote >
< HR >
< pre > bool operator < = ( optional< T> const& amp x, optional< T& gt const& amp y );
< / pre >
< blockquote >
< p > < b > Returns:< / b > !( y< x );< / p >
< p > < b > Throws:< / b > Nothing.< / p >
< / blockquote >
< HR >
< pre > bool operator > = ( optional< T> const& amp x, optional< T& gt const& amp y );
< / pre >
< blockquote >
< p > < b > Returns:< / b > !( x< y );< / p >
< p > < b > Throws:< / b > Nothing.< / p >
< / blockquote >
2003-01-22 17:54:11 +00:00
< HR >
< pre > void swap ( optional< T> & amp x, optional< T& gt& amp y );< / pre >
< blockquote >
< p > < b > Effect:< / b > If both < b > x< / b > and < b > y< / b > are initialized, calls < code > swap(*x,*y)< / code >
using std::swap.< br >
If only one is initialized, say x, calls: < code > y.reset(*x); x.reset();< / code > < br >
If none is initialized, does nothing.
< / p >
< p > < b > Postconditions:< / b > The states of x and y interchanged.< / p >
< p > < b > Throws:< / b > If both are initialized, whatever swap(T& ,T& ) throws.
If only one is initialized, whatever T::T ( T const& ) throws.
< / p >
< p > < b > Notes:< / b > If both are initialized, swap(T& ,T& ) is used < i > unqualified< / i >
but with std::swap introduced in scope.< br >
If only one is initialized, T::~T() and T::T( T const& ) is called.
< / p >
< p > < b > Exception Safety:< / b > If both are initialized, this operation has the exception
safety guarantees of swap(T& ,T& ).< br >
If only one is initialized, it has the same < b > basic< / b > guarantee as optional< T> ::reset( T const& ).
< / p >
< p > < b > Example:< / b > < / p >
< blockquote >
2003-12-04 01:45:19 +00:00
< pre > T x(12);
2003-01-22 17:54:11 +00:00
T y(21);
optional< T> def0 ;
optional< T> def1 ;
optional< T> optX(x);
optional< T> optY(y);
boost::swap(def0,def1); // no-op
boost::swap(def0,optX);
assert ( *def0 == x );
assert ( !optX );
boost::swap(def0,optX); // Get back to original values
boost::swap(optX,optY);
assert ( *optX == y );
assert ( *optY == x );
< / pre >
< / blockquote >
< / blockquote >
< HR >
< H2 > < A NAME = "examples" > Examples< / A > < / H2 >
< h3 > Optional return values< / h3 >
< PRE > optional< char> get_async_input()
{
2003-12-04 01:45:19 +00:00
if ( !queue.empty() )
return optional< char> (queue.top());
else return optional< char> (); // uninitialized
2003-01-22 17:54:11 +00:00
}
2003-12-04 01:45:19 +00:00
void receive_async_message()
2003-01-22 17:54:11 +00:00
{
2003-12-04 01:45:19 +00:00
optional< char> rcv ;
// The safe boolean conversion from 'rcv' is used here.
while ( (rcv = get_async_input()) & & !timeout() )
output(*rcv);
2003-01-22 17:54:11 +00:00
}
< / pre >
< h3 > Optional local variables< / h3 >
< pre > optional< string> name ;
if ( database.open() )
{
2003-12-04 01:45:19 +00:00
name.reset ( database.lookup(employer_name) ) ;
2003-01-22 17:54:11 +00:00
}
else
{
2003-12-04 01:45:19 +00:00
if ( can_ask_user )
name.reset ( user.ask(employer_name) ) ;
2003-01-22 17:54:11 +00:00
}
if ( name )
2003-12-04 01:45:19 +00:00
print(*name);
2003-01-22 17:54:11 +00:00
else print(" employer's name not found!" );
< / pre >
< h3 > Optional data members< / h3 >
< pre > class figure
{
2003-12-04 01:45:19 +00:00
public:
2003-01-22 17:54:11 +00:00
2003-12-04 01:45:19 +00:00
figure()
{
// data member 'm_clipping_rect' is uninitialized at this point.
}
2003-01-22 17:54:11 +00:00
2003-12-04 01:45:19 +00:00
void clip_in_rect ( rect const& rect )
{
....
m_clipping_rect.reset ( rect ) ; // initialized here.
}
2003-01-22 17:54:11 +00:00
2003-12-04 01:45:19 +00:00
void draw ( canvas& cvs )
{
if ( m_clipping_rect )
do_clipping(*m_clipping_rect);
2003-01-22 17:54:11 +00:00
2003-12-04 01:45:19 +00:00
cvs.drawXXX(..);
}
2003-01-22 17:54:11 +00:00
2003-12-04 01:45:19 +00:00
// this can return NULL.
rect const* get_clipping_rect() { return get_pointer(m_clipping_rect); }
2003-01-22 17:54:11 +00:00
2003-12-04 01:45:19 +00:00
private :
2003-01-22 17:54:11 +00:00
2003-12-04 01:45:19 +00:00
optional< rect> m_clipping_rect ;
2003-01-22 17:54:11 +00:00
};
< / pre >
< h3 > Bypassing expensive unnecesary default construction< / h3 >
< pre > class ExpensiveCtor { ... } ;
class Fred
{
2003-12-04 01:45:19 +00:00
Fred() : mLargeVector(10000) {}
std::vector< optional & lt ; ExpensiveCtor & gt ; > mLargeVector ;
} ;
< / pre >
< HR >
< H2 > < A NAME = "ref" > Optional references< / A > < / H2 >
< 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
some operations are not available in this case:< / p >
< ul >
< li > Converting constructors< / li >
< li > Converting assignment< / li >
< li > InPlace construction< / li >
< 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
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
will nonetheless refeer to the same object.< / li >
< li > Value-access will actually provide access to the referenced object rather
than the reference itself.< / li >
< / ul >
< HR >
< 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
constructed object, often temporary, just to follow the copy from:< / p >
< pre > struct X
{
X ( int, std:::string ) ;
} ;< / pre >
< pre > class W
{
X wrapped_ ;
public:
W ( X const& x ) : wrapped_(x) {}
} ;< / pre >
< pre > void foo()
{
// Temporary object created.
W ( X(123,"hello") ) ;
}
< / pre >
< 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
to use in the wrapped object construction.< / p >
< pre > class W
{
X wrapped_ ;
public:
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") ;
}
< / 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
< b > TypedInPlaceFactories< / b > .< br >
These factories are a family of classes which encapsulate an increasing number of arbitrary
constructor parameters and supply a method to construct an object of a given type using those
parameters at an address specified by the user via placement new.< / p >
< p > For example, one member of this familiy looks like:< / p >
< pre > template< class T,class A0, class A1>
class TypedInPlaceFactory2
{
A0 m_a0 ; A1 m_a1 ;
public:
2003-01-22 17:54:11 +00:00
2003-12-04 01:45:19 +00:00
TypedInPlaceFactory2( A0 const& a0, A1 const& a1 ) : m_a0(a0), m_a1(a1) {}
void construct ( void* p ) { new (p) T(m_a0,m_a1) ; }
2003-01-22 17:54:11 +00:00
} ;
< / pre >
2003-12-04 01:45:19 +00:00
< 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 ( 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")) ;
}
< / pre >
< p > The factories are divided in two groups:< ul >
< li > < u > TypedInPlaceFactories< / u > : those which take the target type as a primary template parameter.< / li >
< li > < u > InPlaceFactories< / u > : those with a template < code > construct(void*)< / code > member function taking the target type.< / li >
< / ul >
< p > Within each group, all the family members differ only in the number of parameters allowed.< / p >
< 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>
InPlaceFactory< i > N < / i > < A0,...,AN> < b > in_place< / b > ( A0 const& a0, ..., AN const& 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) {}
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") ) ;
}
< / 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 >
< / p >
2003-01-22 17:54:11 +00:00
< HR >
< H2 > < A NAME = "bool" > A note about optional< bool> < / A > < / H2 >
2003-02-25 10:29:21 +00:00
< p > < code > optional< bool> < / code > should be used with special caution and consideration.< / p >
2003-12-04 01:45:19 +00:00
< p > First, it is functionally similar to a tristate boolean (false,maybe,true) — such as < u > boost::tribool< / u > (not yet formally in boost)— except that in a tristate boolean,
2003-03-14 20:40:08 +00:00
the < i > maybe< / i > state < u > represents a valid value< / u > , unlike the corresponding state
2003-01-22 17:54:11 +00:00
of an uninitialized optional< bool> .< br >
It should be carefully considered if an optional bool instead of a tribool is really needed< / p >
2003-03-14 20:40:08 +00:00
< p > Second, optional< > provides an implicit conversion to bool. This conversion
refers to the initialization state and not to the contained value.< br >
2003-01-22 17:54:11 +00:00
Using optional< bool> can lead to subtle errors due to the implicit bool conversion:< / p >
2003-12-04 01:45:19 +00:00
< pre > void foo ( bool v ) ;
2003-01-22 17:54:11 +00:00
void bar()
{
2003-12-04 01:45:19 +00:00
optional< bool> v = try();
2003-01-22 17:54:11 +00:00
2003-12-04 01:45:19 +00:00
// The following intended to pass the < b > value< / b > of 'v' to foo():
foo(v);
// But instead, the < i > initialization state< / i > is passed
// due to a typo: it should have been foo(< b > *< / b > v).
2003-01-22 17:54:11 +00:00
}
< / pre >
< p > The only implicit conversion is to bool, and it is < i > safe< / i > in the sense that typical
2003-12-04 01:45:19 +00:00
integral promotions don't apply (i.e. if foo() takes an 'int' instead, it won't compile). < HR >
2003-01-22 17:54:11 +00:00
< H2 > < A NAME = "exsafety" > Exception Safety Guarantees< / A > < / H2 >
< H3 > < u > Assignment and Reset:< / u > < / H3 >
2003-12-04 01:45:19 +00:00
< 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 >
< / li >
< 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= (
InPlaceFactory const& ) < / code > < / li >
< li > < code > template< class TypedInPlaceFactory> optional< T> ::operator= (
TypedInPlaceFactory const& ) < / code > < / li >
< li > < code > optional< T> :::reset ( T const& )< / code > < / li >
< / ul >
< p > Can only < i > guarantee< / i > the < u > basic exception safety< / u > : The lvalue optional is left < u > uninitialized< / u >
if an exception is thrown (any previous value is < i > first< / i > destroyed using T::~T())< / p >
< p > On the other hand, the < i > uninitializing< / i > methods:< / p >
< ul >
< li > < code > optional< T> ::operator= ( detail::none_t ) < / code > < / li >
< li > < code > optional< T> ::reset()< / code > < / li >
< / ul >
< p > Provide the no-throw guarantee (assuming a no-throw T::~T())< / p >
2003-01-22 17:54:11 +00:00
< p > However, since < code > optional& lt& gt< / code > itself doesn't throw any exceptions,
2003-12-04 01:45:19 +00:00
the only source for exceptions here are T's constructor, so if you know the exception guarantees
2003-01-22 17:54:11 +00:00
for T::T ( T const& ), you know that optional's assignment and reset has the same guarantees.< / p >
< pre > //
// Case 1: Exception thrown during assignment.
//
T v0(123);
optional& ltT& gt opt0(v0);
try
{
2003-12-04 01:45:19 +00:00
T v1(456);
optional& ltT& gt opt1(v1);
opt0 = opt1 ;
2003-01-22 17:54:11 +00:00
2003-12-04 01:45:19 +00:00
// If no exception was thrown, assignment succeeded.
assert( *opt0 == v1 ) ;
2003-01-22 17:54:11 +00:00
}
catch(...)
{
2003-12-04 01:45:19 +00:00
// If any exception was thrown, 'opt0' is reset to uninitialized.
assert( !opt0 ) ;
2003-01-22 17:54:11 +00:00
}
//
// Case 2: Exception thrown during reset(v)
//
T v0(123);
optional& ltT& gt opt(v0);
try
{
2003-12-04 01:45:19 +00:00
T v1(456);
opt.reset ( v1 ) ;
2003-01-22 17:54:11 +00:00
2003-12-04 01:45:19 +00:00
// If no exception was thrown, reset succeeded.
assert( *opt == v1 ) ;
2003-01-22 17:54:11 +00:00
}
catch(...)
{
2003-12-04 01:45:19 +00:00
// If any exception was thrown, 'opt' is reset to uninitialized.
assert( !opt ) ;
2003-01-22 17:54:11 +00:00
}
< / pre >
< H3 > < u > Swap:< / u > < / H3 >
2003-12-04 01:45:19 +00:00
< p > < code > void swap( optional< T> & , optional< T> & )< / code > has the same exception guarantee as < code > swap(T& ,T& )< / code > when both optionals are initialized.< br >
If only one of the optionals is initialized, it gives the same < i > basic< / i > exception guarantee as < code > optional< T> ::reset( T const& )< / code > (since < code > optional< T> ::reset()< / code > doesn't throw).< br >
If none of the optionals is initialized, it has no-throw guarantee since it is a no-op. < / p >
2003-01-22 17:54:11 +00:00
< HR >
< H2 > < A NAME = "requirements" > Type requirements< / A > < / H2 >
2003-12-04 01:45:19 +00:00
< 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 >
2003-01-22 17:54:11 +00:00
< HR >
< H2 > < A NAME = "impl" > Implementation Notes< / A > < / H2 >
< p > optional< T> is currently implemented
2003-12-04 01:45:19 +00:00
using a custom aligned storage facility built from < code > alignment_of< / code > and < code > type_with_alignment< / code > (both from Type Traits).
2003-01-22 17:54:11 +00:00
It uses a separate boolean flag to indicate the initialization state.< br >
Placement new with T's copy constructor and T's destructor
2003-01-24 13:38:20 +00:00
are explicitly used to initialize,copy and destroy optional values.< br >
2003-01-22 17:54:11 +00:00
As a result, T's default constructor is effectively by-passed, but the exception
2003-01-24 13:38:20 +00:00
guarantees are basic.< br >
2003-01-22 17:54:11 +00:00
It is planned to replace the current implementation with another with
2003-12-04 01:45:19 +00:00
stronger exception safety, such as a future boost::variant< T , nil_t > . < / p >
2003-01-22 17:54:11 +00:00
< HR >
< H2 > < A NAME = "porta" > Dependencies and Portability< / A > < / H2 >
2003-12-04 01:45:19 +00:00
< p > The implementation uses < code > type_traits/alignment_of.hpp< / code > and < code > type_traits/type_with_alignment.hpp< / code > < / p >
2003-01-22 17:54:11 +00:00
< HR >
< H2 > < A NAME = "credits" > Acknowledgments< / A > < / H2 >
< p > Pre-formal review:< / p >
< blockquote >
< p > Peter Dimov suggested the name 'optional', and was the first to point out the
need for aligned storage< br >
Douglas Gregor developed 'type_with_alignment', and later Eric Friedman coded
'aligned_storage', which are the core of the optional class implementation.< br >
Andrei Alexandrescu and Brian Parker also worked with aligned storage techniques
and their work influenced the current implementation.< br >
Gennadiy Rozental made extensive and important comments which shaped the design.< br >
Vesa Karvonen and Douglas Gregor made quite useful comparisons between optional,
variant and any; and made other relevant comments. Douglas Gregor and Peter
Dimov commented on comparisons and evaluation in boolean contexts.< br >
Eric Friedman helped understand the issues involved with aligned storage, move/copy
operations and exception safety.< br >
Many others have participated with useful comments: Aleksey Gurotov, Kevlin
2003-12-04 01:45:19 +00:00
Henney, David Abrahams, and others I can't recall. < / p >
2003-01-22 17:54:11 +00:00
< / blockquote >
< p > Post-formal review:< / p >
< blockquote >
2003-01-24 13:38:20 +00:00
< p > William Kempf carefully considered the originally proposed interface
2003-01-22 17:54:11 +00:00
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 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 an aid against potential conflicts on generic code.< br >
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< > :
the Maybe type constructor (analogy originally pointed out by David Sankel).< br >
Other comments were posted by Vincent Finn, Anthony Williams, Ed Brey, Rob Stewart,
2003-12-04 01:45:19 +00:00
and others.< br >
Joel de Guzman made the case for the support of references and helped with the
proper semantics.< / p >
2003-01-22 17:54:11 +00:00
< / blockquote >
< HR >
2003-12-04 01:45:19 +00:00
< P > Revised December 3, 2003< / P >
2003-01-22 17:54:11 +00:00
< 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 > Developed by < A HREF = "mailto:fernando_cacciola@hotmail.com" > Fernando Cacciola< / A > ,
the latest version of this file can be found at < A
2003-12-04 01:45:19 +00:00
HREF="http://www.boost.org">www.boost.org< / A > , and the boost discussion list at < A
HREF="http://www.yahoogroups.com/list/boost">www.yahoogroups.com/list/boost< / A > . < / P >
2003-03-14 20:40:08 +00:00
< / BODY >
2003-12-04 01:45:19 +00:00
< / HTML >