mirror of
https://github.com/boostorg/optional.git
synced 2025-06-25 12:01:38 +02:00
Compare commits
122 Commits
boost-1.30
...
svn-branch
Author | SHA1 | Date | |
---|---|---|---|
d78a605876 | |||
f921762bf6 | |||
f9c46f9a86 | |||
c1d2381a9b | |||
960631e201 | |||
e9989b260e | |||
646488e0e2 | |||
64d8062621 | |||
d39627c5b6 | |||
f88c8ae423 | |||
ab01dfff7e | |||
8608ad1497 | |||
c93e5a88c7 | |||
425d141cbf | |||
57c07c7a57 | |||
97e314f03a | |||
bccd75c72f | |||
16f0a0aaaf | |||
a63dbe0f14 | |||
066dd6f345 | |||
4e628ed4a6 | |||
8682f2bbaa | |||
fea89e84f3 | |||
2772bfc08d | |||
361943e033 | |||
20c9fc8ebe | |||
fd38be1636 | |||
9f655c6932 | |||
e7d7b014d2 | |||
2af3ec341b | |||
3ebabcb2d8 | |||
63f6e7f45e | |||
43eac5bb12 | |||
74674531c8 | |||
a4572497be | |||
951b49f992 | |||
1afed544db | |||
66c366d18a | |||
472a68c920 | |||
3e33d4a200 | |||
95c864e119 | |||
9afdbe65e7 | |||
f6518df0c4 | |||
05a685b035 | |||
3b5b5d82a0 | |||
06ba35cd42 | |||
3499d477dc | |||
a690c8e7a2 | |||
c8e54ef488 | |||
07ce2fc860 | |||
be7249b537 | |||
1b7002f663 | |||
16a8ccbecc | |||
734e5b5283 | |||
a77dff3e11 | |||
9516a779fe | |||
c7e74ce372 | |||
91bdde095d | |||
0e10374194 | |||
d3f9e112c4 | |||
864adf2e87 | |||
0be943c2f6 | |||
04bec76068 | |||
f89c517fa8 | |||
b831e5f88d | |||
88d002a7be | |||
dda39772ad | |||
ed504fae7b | |||
9a0013d668 | |||
361d945b5c | |||
d61baf2a94 | |||
1412c04b24 | |||
24c5f92413 | |||
07a80c1b9b | |||
7717a785de | |||
3db413cc30 | |||
46fafdb7c9 | |||
9aa4943b7a | |||
7cacecb6f9 | |||
0109fabef4 | |||
dce592e3b2 | |||
05045f5be7 | |||
8d85b4c47b | |||
3ca0557a7c | |||
50d7c315d5 | |||
24416ae806 | |||
44f140f961 | |||
943df2a9aa | |||
c18e5d9464 | |||
7bd27ccace | |||
855d343cd1 | |||
1fc75ce00e | |||
d469aff043 | |||
2a85470f49 | |||
f8fe66e289 | |||
6c70e16379 | |||
51975011a9 | |||
38c609e126 | |||
d0cf7efaf0 | |||
9adda8450b | |||
65464ceffd | |||
3b7d49e4aa | |||
e8a91e1ce3 | |||
3468bfb07f | |||
faa3c1962a | |||
b64b2cb0be | |||
6b70058cf0 | |||
18b8685e5d | |||
920820c1d0 | |||
52896b097e | |||
161540a0eb | |||
3568ed7d0e | |||
cd5ccd166b | |||
a1d8949039 | |||
d888dd2454 | |||
a2f8c2fd41 | |||
0ba0ff8ce3 | |||
5a595a9a92 | |||
042d3e08b8 | |||
7d8ab81d48 | |||
0267424bfe | |||
1e7b26738e |
35
doc/Jamfile.v2
Normal file
35
doc/Jamfile.v2
Normal file
@ -0,0 +1,35 @@
|
||||
# Boost.Optional
|
||||
#
|
||||
# Copyright (c) 2003-2007 Fernando Luis Cacciola Carballal
|
||||
#
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (See accompanying file LICENSE_1_0.txt or copy at
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
|
||||
# Quickbook
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
import quickbook ;
|
||||
|
||||
path-constant images : html ;
|
||||
|
||||
xml optional
|
||||
:
|
||||
optional.qbk
|
||||
;
|
||||
|
||||
boostbook standalone
|
||||
:
|
||||
optional
|
||||
:
|
||||
<xsl:param>boost.root=../../../..
|
||||
<xsl:param>html.stylesheet=boostbook.css
|
||||
<xsl:param>toc.max.depth=2
|
||||
<xsl:param>toc.section.depth=2
|
||||
<xsl:param>chunk.section.depth=1
|
||||
<format>pdf:<xsl:param>img.src.path=$(images)/
|
||||
<format>pdf:<xsl:param>boost.url.prefix=http://www.boost.org/doc/libs/release/libs/optional/doc/html
|
||||
;
|
||||
|
||||
|
60
doc/acknowledgments.qbk
Normal file
60
doc/acknowledgments.qbk
Normal file
@ -0,0 +1,60 @@
|
||||
[/
|
||||
Boost.Optional
|
||||
|
||||
Copyright (c) 2003-2007 Fernando Luis Cacciola Carballal
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt)
|
||||
]
|
||||
|
||||
|
||||
[section Acknowledgments]
|
||||
|
||||
[heading Pre-formal review]
|
||||
|
||||
* Peter Dimov suggested the name 'optional', and was the first to point out
|
||||
the need for aligned storage.
|
||||
* Douglas Gregor developed 'type_with_alignment', and later Eric Friedman
|
||||
coded 'aligned_storage', which are the core of the optional class
|
||||
implementation.
|
||||
* Andrei Alexandrescu and Brian Parker also worked with aligned storage
|
||||
techniques and their work influenced the current implementation.
|
||||
* Gennadiy Rozental made extensive and important comments which shaped the
|
||||
design.
|
||||
* 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.
|
||||
* Eric Friedman helped understand the issues involved with aligned storage,
|
||||
move/copy operations and exception safety.
|
||||
* Many others have participated with useful comments: Aleksey Gurotov,
|
||||
Kevlin Henney, David Abrahams, and others I can't recall.
|
||||
|
||||
[heading Post-formal review]
|
||||
|
||||
* 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.
|
||||
* 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.
|
||||
* 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.
|
||||
* Joel de Guzman noticed that optional<> can be seen as an API on top of
|
||||
variant<T,nil_t>.
|
||||
* Dave Gomboc explained the meaning and usage of the Haskell analog to
|
||||
optional<>: the Maybe type constructor (analogy originally pointed out by
|
||||
David Sankel).
|
||||
* Other comments were posted by Vincent Finn, Anthony Williams, Ed Brey,
|
||||
Rob Stewart, and others.
|
||||
* Joel de Guzman made the case for the support of references and helped
|
||||
with the proper semantics.
|
||||
* Mat Marcus shown the virtues of a value-oriented interface, influencing
|
||||
the current design, and contributed the idea of "none".
|
||||
|
||||
[endsect]
|
||||
|
17
doc/dependencies.qbk
Normal file
17
doc/dependencies.qbk
Normal file
@ -0,0 +1,17 @@
|
||||
[/
|
||||
Boost.Optional
|
||||
|
||||
Copyright (c) 2003-2007 Fernando Luis Cacciola Carballal
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt)
|
||||
]
|
||||
|
||||
|
||||
[section Dependencies and Portability]
|
||||
|
||||
The implementation uses `type_traits/alignment_of.hpp` and
|
||||
`type_traits/type_with_alignment.hpp`
|
||||
|
||||
[endsect]
|
251
doc/development.qbk
Normal file
251
doc/development.qbk
Normal file
@ -0,0 +1,251 @@
|
||||
[/
|
||||
Boost.Optional
|
||||
|
||||
Copyright (c) 2003-2007 Fernando Luis Cacciola Carballal
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt)
|
||||
]
|
||||
|
||||
[section Development]
|
||||
|
||||
[section The models]
|
||||
|
||||
In C++, we can ['declare] an object (a variable) of type `T`, and we can give this
|
||||
variable an ['initial value] (through an ['initializer]. (c.f. 8.5)).
|
||||
When a declaration includes a non-empty initializer (an initial value is given),
|
||||
it is said that the object has been initialized.
|
||||
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
|
||||
[*uninitialized]. Its actual value exist but has an ['indeterminate initial value]
|
||||
(c.f. 8.5.9).
|
||||
`optional<T>` intends to formalize the notion of initialization (or lack of it)
|
||||
allowing a program to test whether an object has been initialized and stating
|
||||
that access to the value of an uninitialized object is undefined behavior. 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 no value at all and this situation can be tested at runtime. It
|
||||
is formally ['undefined behavior] to try to access the value of an uninitialized
|
||||
optional. An uninitialized optional can be assigned 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 ['uninitialized].
|
||||
|
||||
In C++ there is no formal notion of uninitialized objects, which means that
|
||||
objects always have an initial value even if indeterminate.
|
||||
As discussed on the previous section, this has a drawback because you need
|
||||
additional information to tell if an object has been effectively initialized.
|
||||
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 ['nil_t]—were `nil_t` is some stateless POD-can be modeled in modern
|
||||
languages as a [*discriminated union] of T and nil_t. Discriminated unions are
|
||||
often called ['variants]. A variant has a ['current type], which in our case is either
|
||||
`T` or `nil_t`.
|
||||
Using the __BOOST_VARIANT__ library, this model can be implemented in terms of `boost::variant<T,nil_t>`.
|
||||
There is precedent for a discriminated union as a model for an optional value:
|
||||
the __HASKELL__ [*Maybe] built-in type constructor. Thus, a discriminated union
|
||||
`T+nil_t` serves as a conceptual foundation.
|
||||
|
||||
A `variant<T,nil_t>` follows naturally from the traditional idiom of extending
|
||||
the range of possible values adding an additional sentinel value with the
|
||||
special meaning of ['Nothing]. However, this additional ['Nothing] value is largely
|
||||
irrelevant for our purpose since our goal is to formalize the notion of
|
||||
uninitialized objects and, while a special extended value can be used to convey
|
||||
that meaning, it is not strictly necessary in order to do so.
|
||||
|
||||
The observation made in the last paragraph about the irrelevant nature of the
|
||||
additional `nil_t` with respect to [_purpose] of `optional<T>` suggests an
|
||||
alternative model: a ['container] that either has a value of `T` or nothing.
|
||||
|
||||
As of this writing I don't know of any precedent for a variable-size
|
||||
fixed-capacity (of 1) stack-based container model for optional values, yet I
|
||||
believe this is the consequence of the lack of practical implementations of
|
||||
such a container rather than an inherent shortcoming of the container model.
|
||||
|
||||
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.
|
||||
For instance, these models show the ['exact] semantics required for a wrapper
|
||||
of optional values:
|
||||
|
||||
Discriminated-union:
|
||||
|
||||
* [*deep-copy] semantics: copies of the variant implies copies of the value.
|
||||
* [*deep-relational] semantics: comparisons between variants matches both
|
||||
current types and values
|
||||
* If the variant's current type is `T`, it is modeling an ['initialized] optional.
|
||||
* If the variant's current type is not `T`, it is modeling an ['uninitialized]
|
||||
optional.
|
||||
* Testing if the variant's current type is `T` models testing if the optional
|
||||
is initialized
|
||||
* Trying to extract a `T` from a variant when its current type is not `T`, models
|
||||
the undefined behavior of trying to access the value of an uninitialized optional
|
||||
|
||||
Single-element container:
|
||||
|
||||
* [*deep-copy] semantics: copies of the container implies copies of the value.
|
||||
* [*deep-relational] semantics: comparisons between containers compare container
|
||||
size and if match, contained value
|
||||
* If the container is not empty (contains an object of type `T`), it is modeling
|
||||
an ['initialized] optional.
|
||||
* If the container is empty, it is modeling an ['uninitialized] optional.
|
||||
* Testing if the container is empty models testing if the optional is
|
||||
initialized
|
||||
* Trying to extract a `T` from an empty container models the undefined behavior
|
||||
of trying to access the value of an uninitialized optional
|
||||
|
||||
[endsect]
|
||||
|
||||
[section The semantics]
|
||||
|
||||
Objects of type `optional<T>` are intended to be used in places where objects of
|
||||
type `T` would but which might be uninitialized. Hence, `optional<T>`'s purpose is
|
||||
to formalize the additional possibly uninitialized state.
|
||||
From the perspective of this role, `optional<T>` can have the same operational
|
||||
semantics of `T` plus the additional semantics corresponding to this special
|
||||
state.
|
||||
As such, `optional<T>` could be thought of as a ['supertype] of `T`. Of course, we
|
||||
can't do that in C++, so we need to compose the desired semantics using a
|
||||
different mechanism.
|
||||
Doing it the other way around, that is, making `optional<T>` a ['subtype] of `T`
|
||||
is not only conceptually wrong but also impractical: it is not allowed to
|
||||
derive from a non-class type, such as a built-in type.
|
||||
|
||||
We can draw from the purpose of `optional<T>` the required basic semantics:
|
||||
|
||||
* [*Default Construction:] To introduce a formally uninitialized wrapped
|
||||
object.
|
||||
* [*Direct Value Construction via copy:] To introduce a formally initialized
|
||||
wrapped object whose value is obtained as a copy of some object.
|
||||
* [*Deep Copy Construction:] To obtain a new yet equivalent wrapped object.
|
||||
* [*Direct Value Assignment (upon initialized):] To assign a value to the
|
||||
wrapped object.
|
||||
* [*Direct Value Assignment (upon uninitialized):] To initialize the wrapped
|
||||
object with a value obtained as a copy of some object.
|
||||
* [*Assignment (upon initialized):] To assign to the wrapped object the value
|
||||
of another wrapped object.
|
||||
* [*Assignment (upon uninitialized):] To initialize the wrapped object with
|
||||
value of another wrapped object.
|
||||
* [*Deep Relational Operations (when supported by the type T):] To compare
|
||||
wrapped object values taking into account the presence of uninitialized states.
|
||||
* [*Value access:] To unwrap the wrapped object.
|
||||
* [*Initialization state query:] To determine if the object is formally
|
||||
initialized or not.
|
||||
* [*Swap:] To exchange wrapped objects. (with whatever exception safety
|
||||
guarantees are provided by `T`'s swap).
|
||||
* [*De-initialization:] To release the wrapped object (if any) and leave the
|
||||
wrapper in the uninitialized state.
|
||||
|
||||
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.
|
||||
|
||||
[endsect]
|
||||
|
||||
[section The Interface]
|
||||
|
||||
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: 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`.
|
||||
|
||||
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`.
|
||||
|
||||
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.
|
||||
|
||||
For the value access operations, which are undefined (w.r.t the type `T`) when
|
||||
the operand is uninitialized, a different interface is chosen (which will be
|
||||
explained next).
|
||||
|
||||
Also, the presence of the possibly uninitialized state requires additional
|
||||
operations not provided by `T` itself which are supported by a special interface.
|
||||
|
||||
[heading Lexically-hinted Value Access in the presence of possibly
|
||||
untitialized optional objects: The operators * and ->]
|
||||
|
||||
A relevant feature of a pointer is that it can have a [*null pointer value].
|
||||
This is a ['special] value which is used to indicate that the pointer is not
|
||||
referring to any object at all. In other words, null pointer values convey
|
||||
the notion of nonexistent objects.
|
||||
|
||||
This meaning of the null pointer value allowed pointers to became a ['de
|
||||
facto] standard 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 ['refer] to optional (that is,
|
||||
possibly nonexistent) objects; particularly as optional arguments to a
|
||||
function, but also quite often as optional data members.
|
||||
|
||||
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: `( *p = 2 )` and `( p->foo() )`,
|
||||
implicitly convey the notion of optionality, and this information is tied to
|
||||
the ['syntax] of the expressions. That is, the presence of operators `*` and `->`
|
||||
tell by themselves —without any additional context— that the expression will
|
||||
be undefined unless the implied pointee actually exist.
|
||||
|
||||
Such a ['de facto] idiom for referring to optional objects can be formalized
|
||||
in the form of a concept: the __OPTIONAL_POINTEE__ concept.
|
||||
This concept captures the syntactic usage of operators `*`, `->` and
|
||||
conversion to `bool` to convey the notion of optionality.
|
||||
|
||||
However, pointers are good to [_refer] 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.
|
||||
|
||||
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 built-in 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 values. Pointers do
|
||||
not have this semantics, so are inappropriate for the initialization and
|
||||
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
|
||||
__OPTIONAL_POINTEE__ concept incarnated by pointers.
|
||||
|
||||
|
||||
[heading Optional<T> as a model of OptionalPointee]
|
||||
|
||||
For value access operations `optional<>` uses operators `*` and `->` to
|
||||
lexically warn about the possibly uninitialized state appealing to the
|
||||
familiar pointer semantics w.r.t. to null pointers.
|
||||
|
||||
[warning
|
||||
However, it is particularly important to note that `optional<>` objects
|
||||
are not pointers. [_`optional<>` is not, and does not model, a pointer].
|
||||
]
|
||||
|
||||
For instance, `optional<>` does not have shallow-copy so does not alias:
|
||||
two different optionals never refer to the ['same] value unless `T` itself is
|
||||
a reference (but may have ['equivalent] values).
|
||||
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.
|
||||
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 __FUNCTION_EQUAL_POINTEES__ and __FUNCTION_LESS_POINTEES__ instead.
|
||||
|
||||
[endsect]
|
||||
|
||||
[endsect]
|
102
doc/examples.qbk
Normal file
102
doc/examples.qbk
Normal file
@ -0,0 +1,102 @@
|
||||
[/
|
||||
Boost.Optional
|
||||
|
||||
Copyright (c) 2003-2007 Fernando Luis Cacciola Carballal
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt)
|
||||
]
|
||||
|
||||
|
||||
[section Examples]
|
||||
|
||||
[section Optional return values]
|
||||
|
||||
optional<char> get_async_input()
|
||||
{
|
||||
if ( !queue.empty() )
|
||||
return optional<char>(queue.top());
|
||||
else return optional<char>(); // uninitialized
|
||||
}
|
||||
|
||||
void receive_async_message()
|
||||
{
|
||||
optional<char> rcv ;
|
||||
// The safe boolean conversion from 'rcv' is used here.
|
||||
while ( (rcv = get_async_input()) && !timeout() )
|
||||
output(*rcv);
|
||||
}
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Optional local variables]
|
||||
|
||||
optional<string> name ;
|
||||
if ( database.open() )
|
||||
{
|
||||
name.reset ( database.lookup(employer_name) ) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( can_ask_user )
|
||||
name.reset ( user.ask(employer_name) ) ;
|
||||
}
|
||||
|
||||
if ( name )
|
||||
print(*name);
|
||||
else print("employer's name not found!");
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Optional data members]
|
||||
|
||||
class figure
|
||||
{
|
||||
public:
|
||||
|
||||
figure()
|
||||
{
|
||||
// data member 'm_clipping_rect' is uninitialized at this point.
|
||||
}
|
||||
|
||||
void clip_in_rect ( rect const& rect )
|
||||
{
|
||||
....
|
||||
m_clipping_rect.reset ( rect ) ; // initialized here.
|
||||
}
|
||||
|
||||
void draw ( canvas& cvs )
|
||||
{
|
||||
if ( m_clipping_rect )
|
||||
do_clipping(*m_clipping_rect);
|
||||
|
||||
cvs.drawXXX(..);
|
||||
}
|
||||
|
||||
// this can return NULL.
|
||||
rect const* get_clipping_rect() { return get_pointer(m_clipping_rect); }
|
||||
|
||||
private :
|
||||
|
||||
optional<rect> m_clipping_rect ;
|
||||
|
||||
};
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Bypassing expensive unnecessary default construction]
|
||||
|
||||
class ExpensiveCtor { ... } ;
|
||||
class Fred
|
||||
{
|
||||
Fred() : mLargeVector(10000) {}
|
||||
|
||||
std::vector< optional<ExpensiveCtor> > mLargeVector ;
|
||||
} ;
|
||||
|
||||
[endsect]
|
||||
|
||||
[endsect]
|
||||
|
||||
|
14
doc/html/HTML.manifest
Normal file
14
doc/html/HTML.manifest
Normal file
@ -0,0 +1,14 @@
|
||||
index.html
|
||||
boost_optional/development.html
|
||||
boost_optional/synopsis.html
|
||||
boost_optional/detailed_semantics.html
|
||||
boost_optional/examples.html
|
||||
boost_optional/optional_references.html
|
||||
boost_optional/rebinding_semantics_for_assignment_of_optional_references.html
|
||||
boost_optional/in_place_factories.html
|
||||
boost_optional/a_note_about_optional_bool_.html
|
||||
boost_optional/exception_safety_guarantees.html
|
||||
boost_optional/type_requirements.html
|
||||
boost_optional/implementation_notes.html
|
||||
boost_optional/dependencies_and_portability.html
|
||||
boost_optional/acknowledgments.html
|
84
doc/html/boost_optional/a_note_about_optional_bool_.html
Normal file
84
doc/html/boost_optional/a_note_about_optional_bool_.html
Normal file
@ -0,0 +1,84 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
|
||||
<title>A note about optional<bool></title>
|
||||
<link rel="stylesheet" href="../boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.75.2">
|
||||
<link rel="home" href="../index.html" title="Chapter 1. Boost.Optional">
|
||||
<link rel="up" href="../index.html" title="Chapter 1. Boost.Optional">
|
||||
<link rel="prev" href="in_place_factories.html" title="In-Place Factories">
|
||||
<link rel="next" href="exception_safety_guarantees.html" title="Exception Safety Guarantees">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
<table cellpadding="2" width="100%"><tr>
|
||||
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td>
|
||||
<td align="center"><a href="../../../../../index.html">Home</a></td>
|
||||
<td align="center"><a href="../../../../../libs/libraries.htm">Libraries</a></td>
|
||||
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
|
||||
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
|
||||
<td align="center"><a href="../../../../../more/index.htm">More</a></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="in_place_factories.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="exception_safety_guarantees.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||
<a name="boost_optional.a_note_about_optional_bool_"></a><a class="link" href="a_note_about_optional_bool_.html" title="A note about optional<bool>">A note about
|
||||
optional<bool></a>
|
||||
</h2></div></div></div>
|
||||
<p>
|
||||
<code class="computeroutput"><span class="identifier">optional</span><span class="special"><</span><span class="keyword">bool</span><span class="special">></span></code> should
|
||||
be used with special caution and consideration.
|
||||
</p>
|
||||
<p>
|
||||
First, it is functionally similar to a tristate boolean (false,maybe,true)
|
||||
—such as <a href="../../../../../doc/html/tribool.html" target="_top">boost::tribool</a>—
|
||||
except that in a tristate boolean, the maybe state <span class="underline">represents
|
||||
a valid value</span>, unlike the corresponding state of an uninitialized
|
||||
<code class="computeroutput"><span class="identifier">optional</span><span class="special"><</span><span class="keyword">bool</span><span class="special">></span></code>. It
|
||||
should be carefully considered if an <code class="computeroutput"><span class="identifier">optional</span><span class="special"><</span><span class="keyword">bool</span><span class="special">></span></code>
|
||||
instead of a <code class="computeroutput"><span class="identifier">tribool</span></code> is really
|
||||
needed.
|
||||
</p>
|
||||
<p>
|
||||
Second, <code class="computeroutput"><span class="identifier">optional</span><span class="special"><></span></code>
|
||||
provides an implicit conversion to <code class="computeroutput"><span class="keyword">bool</span></code>.
|
||||
This conversion refers to the initialization state and not to the contained
|
||||
value. Using <code class="computeroutput"><span class="identifier">optional</span><span class="special"><</span><span class="keyword">bool</span><span class="special">></span></code> can
|
||||
lead to subtle errors due to the implicit <code class="computeroutput"><span class="keyword">bool</span></code>
|
||||
conversion:
|
||||
</p>
|
||||
<pre class="programlisting"><span class="keyword">void</span> <span class="identifier">foo</span> <span class="special">(</span> <span class="keyword">bool</span> <span class="identifier">v</span> <span class="special">)</span> <span class="special">;</span>
|
||||
<span class="keyword">void</span> <span class="identifier">bar</span><span class="special">()</span>
|
||||
<span class="special">{</span>
|
||||
<span class="identifier">optional</span><span class="special"><</span><span class="keyword">bool</span><span class="special">></span> <span class="identifier">v</span> <span class="special">=</span> <span class="keyword">try</span><span class="special">();</span>
|
||||
|
||||
<span class="comment">// The following intended to pass the value of 'v' to foo():
|
||||
</span> <span class="identifier">foo</span><span class="special">(</span><span class="identifier">v</span><span class="special">);</span>
|
||||
<span class="comment">// But instead, the initialization state is passed
|
||||
</span> <span class="comment">// due to a typo: it should have been foo(*v).
|
||||
</span><span class="special">}</span>
|
||||
</pre>
|
||||
<p>
|
||||
The only implicit conversion is to <code class="computeroutput"><span class="keyword">bool</span></code>,
|
||||
and it is safe in the sense that typical integral promotions don't apply (i.e.
|
||||
if <code class="computeroutput"><span class="identifier">foo</span><span class="special">()</span></code>
|
||||
takes an <code class="computeroutput"><span class="keyword">int</span></code> instead, it won't
|
||||
compile).
|
||||
</p>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"></td>
|
||||
<td align="right"><div class="copyright-footer">Copyright © 2003-2007 Fernando Luis Cacciola Carballal<p>
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
|
||||
</p>
|
||||
</div></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="in_place_factories.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="exception_safety_guarantees.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
125
doc/html/boost_optional/acknowledgments.html
Normal file
125
doc/html/boost_optional/acknowledgments.html
Normal file
@ -0,0 +1,125 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
|
||||
<title>Acknowledgments</title>
|
||||
<link rel="stylesheet" href="../boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.75.2">
|
||||
<link rel="home" href="../index.html" title="Chapter 1. Boost.Optional">
|
||||
<link rel="up" href="../index.html" title="Chapter 1. Boost.Optional">
|
||||
<link rel="prev" href="dependencies_and_portability.html" title="Dependencies and Portability">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
<table cellpadding="2" width="100%"><tr>
|
||||
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td>
|
||||
<td align="center"><a href="../../../../../index.html">Home</a></td>
|
||||
<td align="center"><a href="../../../../../libs/libraries.htm">Libraries</a></td>
|
||||
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
|
||||
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
|
||||
<td align="center"><a href="../../../../../more/index.htm">More</a></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="dependencies_and_portability.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||
<a name="boost_optional.acknowledgments"></a><a class="link" href="acknowledgments.html" title="Acknowledgments">Acknowledgments</a>
|
||||
</h2></div></div></div>
|
||||
<a name="boost_optional.acknowledgments.pre_formal_review"></a><h4>
|
||||
<a name="boost_optional.acknowledgments.pre_formal_review-heading"></a>
|
||||
<a class="link" href="acknowledgments.html#boost_optional.acknowledgments.pre_formal_review">Pre-formal
|
||||
review</a>
|
||||
</h4>
|
||||
<div class="itemizedlist"><ul class="itemizedlist" type="disc">
|
||||
<li class="listitem">
|
||||
Peter Dimov suggested the name 'optional', and was the first to point out
|
||||
the need for aligned storage.
|
||||
</li>
|
||||
<li class="listitem">
|
||||
Douglas Gregor developed 'type_with_alignment', and later Eric Friedman
|
||||
coded 'aligned_storage', which are the core of the optional class implementation.
|
||||
</li>
|
||||
<li class="listitem">
|
||||
Andrei Alexandrescu and Brian Parker also worked with aligned storage techniques
|
||||
and their work influenced the current implementation.
|
||||
</li>
|
||||
<li class="listitem">
|
||||
Gennadiy Rozental made extensive and important comments which shaped the
|
||||
design.
|
||||
</li>
|
||||
<li class="listitem">
|
||||
Vesa Karvonen and Douglas Gregor made quite useful comparisons between
|
||||
optional, variant and any; and made other relevant comments.
|
||||
</li>
|
||||
<li class="listitem">
|
||||
Douglas Gregor and Peter Dimov commented on comparisons and evaluation
|
||||
in boolean contexts.
|
||||
</li>
|
||||
<li class="listitem">
|
||||
Eric Friedman helped understand the issues involved with aligned storage,
|
||||
move/copy operations and exception safety.
|
||||
</li>
|
||||
<li class="listitem">
|
||||
Many others have participated with useful comments: Aleksey Gurotov, Kevlin
|
||||
Henney, David Abrahams, and others I can't recall.
|
||||
</li>
|
||||
</ul></div>
|
||||
<a name="boost_optional.acknowledgments.post_formal_review"></a><h4>
|
||||
<a name="boost_optional.acknowledgments.post_formal_review-heading"></a>
|
||||
<a class="link" href="acknowledgments.html#boost_optional.acknowledgments.post_formal_review">Post-formal
|
||||
review</a>
|
||||
</h4>
|
||||
<div class="itemizedlist"><ul class="itemizedlist" type="disc">
|
||||
<li class="listitem">
|
||||
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.
|
||||
</li>
|
||||
<li class="listitem">
|
||||
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.
|
||||
</li>
|
||||
<li class="listitem">
|
||||
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.
|
||||
</li>
|
||||
<li class="listitem">
|
||||
Joel de Guzman noticed that optional<> can be seen as an API on top
|
||||
of variant<T,nil_t>.
|
||||
</li>
|
||||
<li class="listitem">
|
||||
Dave Gomboc explained the meaning and usage of the Haskell analog to optional<>:
|
||||
the Maybe type constructor (analogy originally pointed out by David Sankel).
|
||||
</li>
|
||||
<li class="listitem">
|
||||
Other comments were posted by Vincent Finn, Anthony Williams, Ed Brey,
|
||||
Rob Stewart, and others.
|
||||
</li>
|
||||
<li class="listitem">
|
||||
Joel de Guzman made the case for the support of references and helped with
|
||||
the proper semantics.
|
||||
</li>
|
||||
<li class="listitem">
|
||||
Mat Marcus shown the virtues of a value-oriented interface, influencing
|
||||
the current design, and contributed the idea of "none".
|
||||
</li>
|
||||
</ul></div>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"></td>
|
||||
<td align="right"><div class="copyright-footer">Copyright © 2003-2007 Fernando Luis Cacciola Carballal<p>
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
|
||||
</p>
|
||||
</div></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="dependencies_and_portability.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
48
doc/html/boost_optional/dependencies_and_portability.html
Normal file
48
doc/html/boost_optional/dependencies_and_portability.html
Normal file
@ -0,0 +1,48 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
|
||||
<title>Dependencies and Portability</title>
|
||||
<link rel="stylesheet" href="../boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.75.2">
|
||||
<link rel="home" href="../index.html" title="Chapter 1. Boost.Optional">
|
||||
<link rel="up" href="../index.html" title="Chapter 1. Boost.Optional">
|
||||
<link rel="prev" href="implementation_notes.html" title="Implementation Notes">
|
||||
<link rel="next" href="acknowledgments.html" title="Acknowledgments">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
<table cellpadding="2" width="100%"><tr>
|
||||
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td>
|
||||
<td align="center"><a href="../../../../../index.html">Home</a></td>
|
||||
<td align="center"><a href="../../../../../libs/libraries.htm">Libraries</a></td>
|
||||
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
|
||||
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
|
||||
<td align="center"><a href="../../../../../more/index.htm">More</a></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="implementation_notes.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="acknowledgments.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||
<a name="boost_optional.dependencies_and_portability"></a><a class="link" href="dependencies_and_portability.html" title="Dependencies and Portability">Dependencies
|
||||
and Portability</a>
|
||||
</h2></div></div></div>
|
||||
<p>
|
||||
The implementation uses <code class="computeroutput"><span class="identifier">type_traits</span><span class="special">/</span><span class="identifier">alignment_of</span><span class="special">.</span><span class="identifier">hpp</span></code> and
|
||||
<code class="computeroutput"><span class="identifier">type_traits</span><span class="special">/</span><span class="identifier">type_with_alignment</span><span class="special">.</span><span class="identifier">hpp</span></code>
|
||||
</p>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"></td>
|
||||
<td align="right"><div class="copyright-footer">Copyright © 2003-2007 Fernando Luis Cacciola Carballal<p>
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
|
||||
</p>
|
||||
</div></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="implementation_notes.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="acknowledgments.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
1370
doc/html/boost_optional/detailed_semantics.html
Normal file
1370
doc/html/boost_optional/detailed_semantics.html
Normal file
File diff suppressed because it is too large
Load Diff
413
doc/html/boost_optional/development.html
Normal file
413
doc/html/boost_optional/development.html
Normal file
@ -0,0 +1,413 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
|
||||
<title>Development</title>
|
||||
<link rel="stylesheet" href="../boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.75.2">
|
||||
<link rel="home" href="../index.html" title="Chapter 1. Boost.Optional">
|
||||
<link rel="up" href="../index.html" title="Chapter 1. Boost.Optional">
|
||||
<link rel="prev" href="../index.html" title="Chapter 1. Boost.Optional">
|
||||
<link rel="next" href="synopsis.html" title="Synopsis">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
<table cellpadding="2" width="100%"><tr>
|
||||
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td>
|
||||
<td align="center"><a href="../../../../../index.html">Home</a></td>
|
||||
<td align="center"><a href="../../../../../libs/libraries.htm">Libraries</a></td>
|
||||
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
|
||||
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
|
||||
<td align="center"><a href="../../../../../more/index.htm">More</a></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="../index.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="synopsis.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||
<a name="boost_optional.development"></a><a class="link" href="development.html" title="Development">Development</a>
|
||||
</h2></div></div></div>
|
||||
<div class="toc"><dl>
|
||||
<dt><span class="section"><a href="development.html#boost_optional.development.the_models">The models</a></span></dt>
|
||||
<dt><span class="section"><a href="development.html#boost_optional.development.the_semantics">The semantics</a></span></dt>
|
||||
<dt><span class="section"><a href="development.html#boost_optional.development.the_interface">The Interface</a></span></dt>
|
||||
</dl></div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
<a name="boost_optional.development.the_models"></a><a class="link" href="development.html#boost_optional.development.the_models" title="The models">The models</a>
|
||||
</h3></div></div></div>
|
||||
<p>
|
||||
In C++, we can <span class="emphasis"><em>declare</em></span> an object (a variable) of type
|
||||
<code class="computeroutput"><span class="identifier">T</span></code>, and we can give this variable
|
||||
an <span class="emphasis"><em>initial value</em></span> (through an <span class="emphasis"><em>initializer</em></span>.
|
||||
(c.f. 8.5)). When a declaration includes a non-empty initializer (an initial
|
||||
value is given), it is said that the object has been initialized. 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
|
||||
<span class="bold"><strong>uninitialized</strong></span>. Its actual value exist but
|
||||
has an <span class="emphasis"><em>indeterminate initial value</em></span> (c.f. 8.5.9). <code class="computeroutput"><span class="identifier">optional</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span></code> intends
|
||||
to formalize the notion of initialization (or lack of it) allowing a program
|
||||
to test whether an object has been initialized and stating that access to
|
||||
the value of an uninitialized object is undefined behavior. That is, when
|
||||
a variable is declared as <code class="computeroutput"><span class="identifier">optional</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span></code>
|
||||
and no initial value is given, the variable is <span class="emphasis"><em>formally</em></span>
|
||||
uninitialized. A formally uninitialized optional object has conceptually
|
||||
no value at all and this situation can be tested at runtime. It is formally
|
||||
<span class="emphasis"><em>undefined behavior</em></span> to try to access the value of an
|
||||
uninitialized optional. An uninitialized optional can be assigned 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 <span class="emphasis"><em>uninitialized</em></span>.
|
||||
</p>
|
||||
<p>
|
||||
In C++ there is no formal notion of uninitialized objects, which means that
|
||||
objects always have an initial value even if indeterminate. As discussed
|
||||
on the previous section, this has a drawback because you need additional
|
||||
information to tell if an object has been effectively initialized. One of
|
||||
the typical ways in which this has been historically dealt with is via a
|
||||
special value: <code class="computeroutput"><span class="identifier">EOF</span></code>, <code class="computeroutput"><span class="identifier">npos</span></code>, -1, etc... This is equivalent to
|
||||
adding the special value to the set of possible values of a given type. This
|
||||
super set of <code class="computeroutput"><span class="identifier">T</span></code> plus some
|
||||
<span class="emphasis"><em>nil_t</em></span>—were <code class="computeroutput"><span class="identifier">nil_t</span></code>
|
||||
is some stateless POD-can be modeled in modern languages as a <span class="bold"><strong>discriminated
|
||||
union</strong></span> of T and nil_t. Discriminated unions are often called <span class="emphasis"><em>variants</em></span>.
|
||||
A variant has a <span class="emphasis"><em>current type</em></span>, which in our case is either
|
||||
<code class="computeroutput"><span class="identifier">T</span></code> or <code class="computeroutput"><span class="identifier">nil_t</span></code>.
|
||||
Using the <a href="../../../../variant/index.html" target="_top">Boost.Variant</a>
|
||||
library, this model can be implemented in terms of <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">variant</span><span class="special"><</span><span class="identifier">T</span><span class="special">,</span><span class="identifier">nil_t</span><span class="special">></span></code>.
|
||||
There is precedent for a discriminated union as a model for an optional value:
|
||||
the <a href="http://www.haskell.org/" target="_top">Haskell</a> <span class="bold"><strong>Maybe</strong></span>
|
||||
built-in type constructor. Thus, a discriminated union <code class="computeroutput"><span class="identifier">T</span><span class="special">+</span><span class="identifier">nil_t</span></code>
|
||||
serves as a conceptual foundation.
|
||||
</p>
|
||||
<p>
|
||||
A <code class="computeroutput"><span class="identifier">variant</span><span class="special"><</span><span class="identifier">T</span><span class="special">,</span><span class="identifier">nil_t</span><span class="special">></span></code> follows naturally from the traditional
|
||||
idiom of extending the range of possible values adding an additional sentinel
|
||||
value with the special meaning of <span class="emphasis"><em>Nothing</em></span>. However,
|
||||
this additional <span class="emphasis"><em>Nothing</em></span> value is largely irrelevant
|
||||
for our purpose since our goal is to formalize the notion of uninitialized
|
||||
objects and, while a special extended value can be used to convey that meaning,
|
||||
it is not strictly necessary in order to do so.
|
||||
</p>
|
||||
<p>
|
||||
The observation made in the last paragraph about the irrelevant nature of
|
||||
the additional <code class="computeroutput"><span class="identifier">nil_t</span></code> with
|
||||
respect to <span class="underline">purpose</span> of <code class="computeroutput"><span class="identifier">optional</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span></code> suggests
|
||||
an alternative model: a <span class="emphasis"><em>container</em></span> that either has a
|
||||
value of <code class="computeroutput"><span class="identifier">T</span></code> or nothing.
|
||||
</p>
|
||||
<p>
|
||||
As of this writing I don't know of any precedent for a variable-size fixed-capacity
|
||||
(of 1) stack-based container model for optional values, yet I believe this
|
||||
is the consequence of the lack of practical implementations of such a container
|
||||
rather than an inherent shortcoming of the container model.
|
||||
</p>
|
||||
<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. For instance, these models show the <span class="emphasis"><em>exact</em></span>
|
||||
semantics required for a wrapper of optional values:
|
||||
</p>
|
||||
<p>
|
||||
Discriminated-union:
|
||||
</p>
|
||||
<div class="itemizedlist"><ul class="itemizedlist" type="disc">
|
||||
<li class="listitem">
|
||||
<span class="bold"><strong>deep-copy</strong></span> semantics: copies of the variant
|
||||
implies copies of the value.
|
||||
</li>
|
||||
<li class="listitem">
|
||||
<span class="bold"><strong>deep-relational</strong></span> semantics: comparisons
|
||||
between variants matches both current types and values
|
||||
</li>
|
||||
<li class="listitem">
|
||||
If the variant's current type is <code class="computeroutput"><span class="identifier">T</span></code>,
|
||||
it is modeling an <span class="emphasis"><em>initialized</em></span> optional.
|
||||
</li>
|
||||
<li class="listitem">
|
||||
If the variant's current type is not <code class="computeroutput"><span class="identifier">T</span></code>,
|
||||
it is modeling an <span class="emphasis"><em>uninitialized</em></span> optional.
|
||||
</li>
|
||||
<li class="listitem">
|
||||
Testing if the variant's current type is <code class="computeroutput"><span class="identifier">T</span></code>
|
||||
models testing if the optional is initialized
|
||||
</li>
|
||||
<li class="listitem">
|
||||
Trying to extract a <code class="computeroutput"><span class="identifier">T</span></code>
|
||||
from a variant when its current type is not <code class="computeroutput"><span class="identifier">T</span></code>,
|
||||
models the undefined behavior of trying to access the value of an uninitialized
|
||||
optional
|
||||
</li>
|
||||
</ul></div>
|
||||
<p>
|
||||
Single-element container:
|
||||
</p>
|
||||
<div class="itemizedlist"><ul class="itemizedlist" type="disc">
|
||||
<li class="listitem">
|
||||
<span class="bold"><strong>deep-copy</strong></span> semantics: copies of the container
|
||||
implies copies of the value.
|
||||
</li>
|
||||
<li class="listitem">
|
||||
<span class="bold"><strong>deep-relational</strong></span> semantics: comparisons
|
||||
between containers compare container size and if match, contained value
|
||||
</li>
|
||||
<li class="listitem">
|
||||
If the container is not empty (contains an object of type <code class="computeroutput"><span class="identifier">T</span></code>), it is modeling an <span class="emphasis"><em>initialized</em></span>
|
||||
optional.
|
||||
</li>
|
||||
<li class="listitem">
|
||||
If the container is empty, it is modeling an <span class="emphasis"><em>uninitialized</em></span>
|
||||
optional.
|
||||
</li>
|
||||
<li class="listitem">
|
||||
Testing if the container is empty models testing if the optional is initialized
|
||||
</li>
|
||||
<li class="listitem">
|
||||
Trying to extract a <code class="computeroutput"><span class="identifier">T</span></code>
|
||||
from an empty container models the undefined behavior of trying to access
|
||||
the value of an uninitialized optional
|
||||
</li>
|
||||
</ul></div>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
<a name="boost_optional.development.the_semantics"></a><a class="link" href="development.html#boost_optional.development.the_semantics" title="The semantics">The semantics</a>
|
||||
</h3></div></div></div>
|
||||
<p>
|
||||
Objects of type <code class="computeroutput"><span class="identifier">optional</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span></code>
|
||||
are intended to be used in places where objects of type <code class="computeroutput"><span class="identifier">T</span></code>
|
||||
would but which might be uninitialized. Hence, <code class="computeroutput"><span class="identifier">optional</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span></code>'s
|
||||
purpose is to formalize the additional possibly uninitialized state. From
|
||||
the perspective of this role, <code class="computeroutput"><span class="identifier">optional</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span></code>
|
||||
can have the same operational semantics of <code class="computeroutput"><span class="identifier">T</span></code>
|
||||
plus the additional semantics corresponding to this special state. As such,
|
||||
<code class="computeroutput"><span class="identifier">optional</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span></code> could
|
||||
be thought of as a <span class="emphasis"><em>supertype</em></span> of <code class="computeroutput"><span class="identifier">T</span></code>.
|
||||
Of course, we can't do that in C++, so we need to compose the desired semantics
|
||||
using a different mechanism. Doing it the other way around, that is, making
|
||||
<code class="computeroutput"><span class="identifier">optional</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span></code> a
|
||||
<span class="emphasis"><em>subtype</em></span> of <code class="computeroutput"><span class="identifier">T</span></code>
|
||||
is not only conceptually wrong but also impractical: it is not allowed to
|
||||
derive from a non-class type, such as a built-in type.
|
||||
</p>
|
||||
<p>
|
||||
We can draw from the purpose of <code class="computeroutput"><span class="identifier">optional</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span></code>
|
||||
the required basic semantics:
|
||||
</p>
|
||||
<div class="itemizedlist"><ul class="itemizedlist" type="disc">
|
||||
<li class="listitem">
|
||||
<span class="bold"><strong>Default Construction:</strong></span> To introduce a
|
||||
formally uninitialized wrapped object.
|
||||
</li>
|
||||
<li class="listitem">
|
||||
<span class="bold"><strong>Direct Value Construction via copy:</strong></span>
|
||||
To introduce a formally initialized wrapped object whose value is obtained
|
||||
as a copy of some object.
|
||||
</li>
|
||||
<li class="listitem">
|
||||
<span class="bold"><strong>Deep Copy Construction:</strong></span> To obtain a
|
||||
new yet equivalent wrapped object.
|
||||
</li>
|
||||
<li class="listitem">
|
||||
<span class="bold"><strong>Direct Value Assignment (upon initialized):</strong></span>
|
||||
To assign a value to the wrapped object.
|
||||
</li>
|
||||
<li class="listitem">
|
||||
<span class="bold"><strong>Direct Value Assignment (upon uninitialized):</strong></span>
|
||||
To initialize the wrapped object with a value obtained as a copy of some
|
||||
object.
|
||||
</li>
|
||||
<li class="listitem">
|
||||
<span class="bold"><strong>Assignment (upon initialized):</strong></span> To assign
|
||||
to the wrapped object the value of another wrapped object.
|
||||
</li>
|
||||
<li class="listitem">
|
||||
<span class="bold"><strong>Assignment (upon uninitialized):</strong></span> To
|
||||
initialize the wrapped object with value of another wrapped object.
|
||||
</li>
|
||||
<li class="listitem">
|
||||
<span class="bold"><strong>Deep Relational Operations (when supported by the
|
||||
type T):</strong></span> To compare wrapped object values taking into account
|
||||
the presence of uninitialized states.
|
||||
</li>
|
||||
<li class="listitem">
|
||||
<span class="bold"><strong>Value access:</strong></span> To unwrap the wrapped
|
||||
object.
|
||||
</li>
|
||||
<li class="listitem">
|
||||
<span class="bold"><strong>Initialization state query:</strong></span> To determine
|
||||
if the object is formally initialized or not.
|
||||
</li>
|
||||
<li class="listitem">
|
||||
<span class="bold"><strong>Swap:</strong></span> To exchange wrapped objects. (with
|
||||
whatever exception safety guarantees are provided by <code class="computeroutput"><span class="identifier">T</span></code>'s
|
||||
swap).
|
||||
</li>
|
||||
<li class="listitem">
|
||||
<span class="bold"><strong>De-initialization:</strong></span> To release the wrapped
|
||||
object (if any) and leave the wrapper in the uninitialized state.
|
||||
</li>
|
||||
</ul></div>
|
||||
<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>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
<a name="boost_optional.development.the_interface"></a><a class="link" href="development.html#boost_optional.development.the_interface" title="The Interface">The Interface</a>
|
||||
</h3></div></div></div>
|
||||
<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 <code class="computeroutput"><span class="identifier">T</span></code> type
|
||||
as much as possible. In order to choose the proper degree of adoption of
|
||||
the native <code class="computeroutput"><span class="identifier">T</span></code> interface, the
|
||||
following must be noted: Even if all the operations supported by an instance
|
||||
of type <code class="computeroutput"><span class="identifier">T</span></code> are defined for
|
||||
the entire range of values for such a type, an <code class="computeroutput"><span class="identifier">optional</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span></code>
|
||||
extends such a set of values with a new value for which most (otherwise valid)
|
||||
operations are not defined in terms of <code class="computeroutput"><span class="identifier">T</span></code>.
|
||||
</p>
|
||||
<p>
|
||||
Furthermore, since <code class="computeroutput"><span class="identifier">optional</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span></code>
|
||||
itself is merely a <code class="computeroutput"><span class="identifier">T</span></code> wrapper
|
||||
(modeling a <code class="computeroutput"><span class="identifier">T</span></code> supertype),
|
||||
any attempt to define such operations upon uninitialized optionals will be
|
||||
totally artificial w.r.t. <code class="computeroutput"><span class="identifier">T</span></code>.
|
||||
</p>
|
||||
<p>
|
||||
This library chooses an interface which follows from <code class="computeroutput"><span class="identifier">T</span></code>'s
|
||||
interface only for those operations which are well defined (w.r.t the type
|
||||
<code class="computeroutput"><span class="identifier">T</span></code>) even if any of the operands
|
||||
are uninitialized. These operations include: construction, copy-construction,
|
||||
assignment, swap and relational operations.
|
||||
</p>
|
||||
<p>
|
||||
For the value access operations, which are undefined (w.r.t the type <code class="computeroutput"><span class="identifier">T</span></code>) when the operand is uninitialized, a
|
||||
different interface is chosen (which will be explained next).
|
||||
</p>
|
||||
<p>
|
||||
Also, the presence of the possibly uninitialized state requires additional
|
||||
operations not provided by <code class="computeroutput"><span class="identifier">T</span></code>
|
||||
itself which are supported by a special interface.
|
||||
</p>
|
||||
<a name="boost_optional.development.the_interface.lexically_hinted_value_access_in_the_presence_of_possibly_untitialized_optional_objects__the_operators___and___gt_"></a><h5>
|
||||
<a name="boost_optional.development.the_interface.lexically_hinted_value_access_in_the_presence_of_possibly_untitialized_optional_objects__the_operators___and___gt_-heading"></a>
|
||||
<a class="link" href="development.html#boost_optional.development.the_interface.lexically_hinted_value_access_in_the_presence_of_possibly_untitialized_optional_objects__the_operators___and___gt_">Lexically-hinted
|
||||
Value Access in the presence of possibly untitialized optional objects: The
|
||||
operators * and -></a>
|
||||
</h5>
|
||||
<p>
|
||||
A relevant feature of a pointer is that it can have a <span class="bold"><strong>null
|
||||
pointer value</strong></span>. This is a <span class="emphasis"><em>special</em></span> value which
|
||||
is used to indicate that the pointer is not referring to any object at all.
|
||||
In other words, null pointer values convey the notion of nonexistent objects.
|
||||
</p>
|
||||
<p>
|
||||
This meaning of the null pointer value allowed pointers to became a <span class="emphasis"><em>de
|
||||
facto</em></span> standard 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 <span class="emphasis"><em>refer</em></span>
|
||||
to optional (that is, possibly nonexistent) 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 and access operators, such as: <code class="computeroutput"><span class="special">(</span>
|
||||
<span class="special">*</span><span class="identifier">p</span> <span class="special">=</span> <span class="number">2</span> <span class="special">)</span></code>
|
||||
and <code class="computeroutput"><span class="special">(</span> <span class="identifier">p</span><span class="special">-></span><span class="identifier">foo</span><span class="special">()</span> <span class="special">)</span></code>, implicitly
|
||||
convey the notion of optionality, and this information is tied to the <span class="emphasis"><em>syntax</em></span>
|
||||
of the expressions. That is, the presence of operators <code class="computeroutput"><span class="special">*</span></code>
|
||||
and <code class="computeroutput"><span class="special">-></span></code> tell by themselves
|
||||
—without any additional context— that the expression will be undefined
|
||||
unless the implied pointee actually exist.
|
||||
</p>
|
||||
<p>
|
||||
Such a <span class="emphasis"><em>de facto</em></span> idiom for referring to optional objects
|
||||
can be formalized in the form of a concept: the <a href="../../../../utility/OptionalPointee.html" target="_top">OptionalPointee</a>
|
||||
concept. This concept captures the syntactic usage of operators <code class="computeroutput"><span class="special">*</span></code>, <code class="computeroutput"><span class="special">-></span></code>
|
||||
and conversion to <code class="computeroutput"><span class="keyword">bool</span></code> to convey
|
||||
the notion of optionality.
|
||||
</p>
|
||||
<p>
|
||||
However, pointers are good to <span class="underline">refer</span>
|
||||
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.
|
||||
</p>
|
||||
<p>
|
||||
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 <code class="computeroutput"><span class="identifier">X</span></code>, it can use <code class="computeroutput"><span class="identifier">shared_ptr</span><span class="special"><</span><span class="identifier">X</span><span class="special">></span></code>
|
||||
as the return value. However, this requires dynamic allocation of <code class="computeroutput"><span class="identifier">X</span></code>. If <code class="computeroutput"><span class="identifier">X</span></code>
|
||||
is a built-in 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 values. Pointers do not have
|
||||
this semantics, so are inappropriate for the initialization and 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 <a href="../../../../utility/OptionalPointee.html" target="_top">OptionalPointee</a> concept
|
||||
incarnated by pointers.
|
||||
</p>
|
||||
<a name="boost_optional.development.the_interface.optional_lt_t_gt__as_a_model_of_optionalpointee"></a><h5>
|
||||
<a name="boost_optional.development.the_interface.optional_lt_t_gt__as_a_model_of_optionalpointee-heading"></a>
|
||||
<a class="link" href="development.html#boost_optional.development.the_interface.optional_lt_t_gt__as_a_model_of_optionalpointee">Optional<T>
|
||||
as a model of OptionalPointee</a>
|
||||
</h5>
|
||||
<p>
|
||||
For value access operations <code class="computeroutput"><span class="identifier">optional</span><span class="special"><></span></code> uses operators <code class="computeroutput"><span class="special">*</span></code>
|
||||
and <code class="computeroutput"><span class="special">-></span></code> to lexically warn
|
||||
about the possibly uninitialized state appealing to the familiar pointer
|
||||
semantics w.r.t. to null pointers.
|
||||
</p>
|
||||
<div class="warning"><table border="0" summary="Warning">
|
||||
<tr>
|
||||
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Warning]" src="../../../../../doc/src/images/warning.png"></td>
|
||||
<th align="left">Warning</th>
|
||||
</tr>
|
||||
<tr><td align="left" valign="top"><p>
|
||||
However, it is particularly important to note that <code class="computeroutput"><span class="identifier">optional</span><span class="special"><></span></code> objects are not pointers. <span class="underline"><code class="computeroutput"><span class="identifier">optional</span><span class="special"><></span></code> is not, and does not model, a pointer</span>.
|
||||
</p></td></tr>
|
||||
</table></div>
|
||||
<p>
|
||||
For instance, <code class="computeroutput"><span class="identifier">optional</span><span class="special"><></span></code>
|
||||
does not have shallow-copy so does not alias: two different optionals never
|
||||
refer to the <span class="emphasis"><em>same</em></span> value unless <code class="computeroutput"><span class="identifier">T</span></code>
|
||||
itself is a reference (but may have <span class="emphasis"><em>equivalent</em></span> values).
|
||||
The difference between an <code class="computeroutput"><span class="identifier">optional</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span></code>
|
||||
and a pointer must be kept in mind, particularly because the semantics of
|
||||
relational operators are different: since <code class="computeroutput"><span class="identifier">optional</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span></code>
|
||||
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. As a result, you might be able to replace <code class="computeroutput"><span class="identifier">optional</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span></code>
|
||||
by <code class="computeroutput"><span class="identifier">T</span><span class="special">*</span></code>
|
||||
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" target="_top"><code class="computeroutput"><span class="identifier">equal_pointees</span><span class="special">()</span></code></a>
|
||||
and <a href="../../../../utility/OptionalPointee.html#less" target="_top"><code class="computeroutput"><span class="identifier">less_pointees</span><span class="special">()</span></code></a>
|
||||
instead.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"></td>
|
||||
<td align="right"><div class="copyright-footer">Copyright © 2003-2007 Fernando Luis Cacciola Carballal<p>
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
|
||||
</p>
|
||||
</div></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="../index.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="synopsis.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
147
doc/html/boost_optional/examples.html
Normal file
147
doc/html/boost_optional/examples.html
Normal file
@ -0,0 +1,147 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
|
||||
<title>Examples</title>
|
||||
<link rel="stylesheet" href="../boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.75.2">
|
||||
<link rel="home" href="../index.html" title="Chapter 1. Boost.Optional">
|
||||
<link rel="up" href="../index.html" title="Chapter 1. Boost.Optional">
|
||||
<link rel="prev" href="detailed_semantics.html" title="Detailed Semantics">
|
||||
<link rel="next" href="optional_references.html" title="Optional references">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
<table cellpadding="2" width="100%"><tr>
|
||||
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td>
|
||||
<td align="center"><a href="../../../../../index.html">Home</a></td>
|
||||
<td align="center"><a href="../../../../../libs/libraries.htm">Libraries</a></td>
|
||||
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
|
||||
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
|
||||
<td align="center"><a href="../../../../../more/index.htm">More</a></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="detailed_semantics.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="optional_references.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||
<a name="boost_optional.examples"></a><a class="link" href="examples.html" title="Examples">Examples</a>
|
||||
</h2></div></div></div>
|
||||
<div class="toc"><dl>
|
||||
<dt><span class="section"><a href="examples.html#boost_optional.examples.optional_return_values">Optional
|
||||
return values</a></span></dt>
|
||||
<dt><span class="section"><a href="examples.html#boost_optional.examples.optional_local_variables">Optional
|
||||
local variables</a></span></dt>
|
||||
<dt><span class="section"><a href="examples.html#boost_optional.examples.optional_data_members">Optional
|
||||
data members</a></span></dt>
|
||||
<dt><span class="section"><a href="examples.html#boost_optional.examples.bypassing_expensive_unnecessary_default_construction">Bypassing
|
||||
expensive unnecessary default construction</a></span></dt>
|
||||
</dl></div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
<a name="boost_optional.examples.optional_return_values"></a><a class="link" href="examples.html#boost_optional.examples.optional_return_values" title="Optional return values">Optional
|
||||
return values</a>
|
||||
</h3></div></div></div>
|
||||
<pre class="programlisting"><span class="identifier">optional</span><span class="special"><</span><span class="keyword">char</span><span class="special">></span> <span class="identifier">get_async_input</span><span class="special">()</span>
|
||||
<span class="special">{</span>
|
||||
<span class="keyword">if</span> <span class="special">(</span> <span class="special">!</span><span class="identifier">queue</span><span class="special">.</span><span class="identifier">empty</span><span class="special">()</span> <span class="special">)</span>
|
||||
<span class="keyword">return</span> <span class="identifier">optional</span><span class="special"><</span><span class="keyword">char</span><span class="special">>(</span><span class="identifier">queue</span><span class="special">.</span><span class="identifier">top</span><span class="special">());</span>
|
||||
<span class="keyword">else</span> <span class="keyword">return</span> <span class="identifier">optional</span><span class="special"><</span><span class="keyword">char</span><span class="special">>();</span> <span class="comment">// uninitialized
|
||||
</span><span class="special">}</span>
|
||||
|
||||
<span class="keyword">void</span> <span class="identifier">receive_async_message</span><span class="special">()</span>
|
||||
<span class="special">{</span>
|
||||
<span class="identifier">optional</span><span class="special"><</span><span class="keyword">char</span><span class="special">></span> <span class="identifier">rcv</span> <span class="special">;</span>
|
||||
<span class="comment">// The safe boolean conversion from 'rcv' is used here.
|
||||
</span> <span class="keyword">while</span> <span class="special">(</span> <span class="special">(</span><span class="identifier">rcv</span> <span class="special">=</span> <span class="identifier">get_async_input</span><span class="special">())</span> <span class="special">&&</span> <span class="special">!</span><span class="identifier">timeout</span><span class="special">()</span> <span class="special">)</span>
|
||||
<span class="identifier">output</span><span class="special">(*</span><span class="identifier">rcv</span><span class="special">);</span>
|
||||
<span class="special">}</span>
|
||||
</pre>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
<a name="boost_optional.examples.optional_local_variables"></a><a class="link" href="examples.html#boost_optional.examples.optional_local_variables" title="Optional local variables">Optional
|
||||
local variables</a>
|
||||
</h3></div></div></div>
|
||||
<pre class="programlisting"><span class="identifier">optional</span><span class="special"><</span><span class="identifier">string</span><span class="special">></span> <span class="identifier">name</span> <span class="special">;</span>
|
||||
<span class="keyword">if</span> <span class="special">(</span> <span class="identifier">database</span><span class="special">.</span><span class="identifier">open</span><span class="special">()</span> <span class="special">)</span>
|
||||
<span class="special">{</span>
|
||||
<span class="identifier">name</span><span class="special">.</span><span class="identifier">reset</span> <span class="special">(</span> <span class="identifier">database</span><span class="special">.</span><span class="identifier">lookup</span><span class="special">(</span><span class="identifier">employer_name</span><span class="special">)</span> <span class="special">)</span> <span class="special">;</span>
|
||||
<span class="special">}</span>
|
||||
<span class="keyword">else</span>
|
||||
<span class="special">{</span>
|
||||
<span class="keyword">if</span> <span class="special">(</span> <span class="identifier">can_ask_user</span> <span class="special">)</span>
|
||||
<span class="identifier">name</span><span class="special">.</span><span class="identifier">reset</span> <span class="special">(</span> <span class="identifier">user</span><span class="special">.</span><span class="identifier">ask</span><span class="special">(</span><span class="identifier">employer_name</span><span class="special">)</span> <span class="special">)</span> <span class="special">;</span>
|
||||
<span class="special">}</span>
|
||||
|
||||
<span class="keyword">if</span> <span class="special">(</span> <span class="identifier">name</span> <span class="special">)</span>
|
||||
<span class="identifier">print</span><span class="special">(*</span><span class="identifier">name</span><span class="special">);</span>
|
||||
<span class="keyword">else</span> <span class="identifier">print</span><span class="special">(</span><span class="string">"employer's name not found!"</span><span class="special">);</span>
|
||||
</pre>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
<a name="boost_optional.examples.optional_data_members"></a><a class="link" href="examples.html#boost_optional.examples.optional_data_members" title="Optional data members">Optional
|
||||
data members</a>
|
||||
</h3></div></div></div>
|
||||
<pre class="programlisting"><span class="keyword">class</span> <span class="identifier">figure</span>
|
||||
<span class="special">{</span>
|
||||
<span class="keyword">public</span><span class="special">:</span>
|
||||
|
||||
<span class="identifier">figure</span><span class="special">()</span>
|
||||
<span class="special">{</span>
|
||||
<span class="comment">// data member 'm_clipping_rect' is uninitialized at this point.
|
||||
</span> <span class="special">}</span>
|
||||
|
||||
<span class="keyword">void</span> <span class="identifier">clip_in_rect</span> <span class="special">(</span> <span class="identifier">rect</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">rect</span> <span class="special">)</span>
|
||||
<span class="special">{</span>
|
||||
<span class="special">....</span>
|
||||
<span class="identifier">m_clipping_rect</span><span class="special">.</span><span class="identifier">reset</span> <span class="special">(</span> <span class="identifier">rect</span> <span class="special">)</span> <span class="special">;</span> <span class="comment">// initialized here.
|
||||
</span> <span class="special">}</span>
|
||||
|
||||
<span class="keyword">void</span> <span class="identifier">draw</span> <span class="special">(</span> <span class="identifier">canvas</span><span class="special">&</span> <span class="identifier">cvs</span> <span class="special">)</span>
|
||||
<span class="special">{</span>
|
||||
<span class="keyword">if</span> <span class="special">(</span> <span class="identifier">m_clipping_rect</span> <span class="special">)</span>
|
||||
<span class="identifier">do_clipping</span><span class="special">(*</span><span class="identifier">m_clipping_rect</span><span class="special">);</span>
|
||||
|
||||
<span class="identifier">cvs</span><span class="special">.</span><span class="identifier">drawXXX</span><span class="special">(..);</span>
|
||||
<span class="special">}</span>
|
||||
|
||||
<span class="comment">// this can return NULL.
|
||||
</span> <span class="identifier">rect</span> <span class="keyword">const</span><span class="special">*</span> <span class="identifier">get_clipping_rect</span><span class="special">()</span> <span class="special">{</span> <span class="keyword">return</span> <span class="identifier">get_pointer</span><span class="special">(</span><span class="identifier">m_clipping_rect</span><span class="special">);</span> <span class="special">}</span>
|
||||
|
||||
<span class="keyword">private</span> <span class="special">:</span>
|
||||
|
||||
<span class="identifier">optional</span><span class="special"><</span><span class="identifier">rect</span><span class="special">></span> <span class="identifier">m_clipping_rect</span> <span class="special">;</span>
|
||||
|
||||
<span class="special">};</span>
|
||||
</pre>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
<a name="boost_optional.examples.bypassing_expensive_unnecessary_default_construction"></a><a class="link" href="examples.html#boost_optional.examples.bypassing_expensive_unnecessary_default_construction" title="Bypassing expensive unnecessary default construction">Bypassing
|
||||
expensive unnecessary default construction</a>
|
||||
</h3></div></div></div>
|
||||
<pre class="programlisting"><span class="keyword">class</span> <span class="identifier">ExpensiveCtor</span> <span class="special">{</span> <span class="special">...</span> <span class="special">}</span> <span class="special">;</span>
|
||||
<span class="keyword">class</span> <span class="identifier">Fred</span>
|
||||
<span class="special">{</span>
|
||||
<span class="identifier">Fred</span><span class="special">()</span> <span class="special">:</span> <span class="identifier">mLargeVector</span><span class="special">(</span><span class="number">10000</span><span class="special">)</span> <span class="special">{}</span>
|
||||
|
||||
<span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special"><</span> <span class="identifier">optional</span><span class="special"><</span><span class="identifier">ExpensiveCtor</span><span class="special">></span> <span class="special">></span> <span class="identifier">mLargeVector</span> <span class="special">;</span>
|
||||
<span class="special">}</span> <span class="special">;</span>
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"></td>
|
||||
<td align="right"><div class="copyright-footer">Copyright © 2003-2007 Fernando Luis Cacciola Carballal<p>
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
|
||||
</p>
|
||||
</div></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="detailed_semantics.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="optional_references.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
152
doc/html/boost_optional/exception_safety_guarantees.html
Normal file
152
doc/html/boost_optional/exception_safety_guarantees.html
Normal file
@ -0,0 +1,152 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
|
||||
<title>Exception Safety Guarantees</title>
|
||||
<link rel="stylesheet" href="../boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.75.2">
|
||||
<link rel="home" href="../index.html" title="Chapter 1. Boost.Optional">
|
||||
<link rel="up" href="../index.html" title="Chapter 1. Boost.Optional">
|
||||
<link rel="prev" href="a_note_about_optional_bool_.html" title="A note about optional<bool>">
|
||||
<link rel="next" href="type_requirements.html" title="Type requirements">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
<table cellpadding="2" width="100%"><tr>
|
||||
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td>
|
||||
<td align="center"><a href="../../../../../index.html">Home</a></td>
|
||||
<td align="center"><a href="../../../../../libs/libraries.htm">Libraries</a></td>
|
||||
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
|
||||
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
|
||||
<td align="center"><a href="../../../../../more/index.htm">More</a></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="a_note_about_optional_bool_.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="type_requirements.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||
<a name="boost_optional.exception_safety_guarantees"></a><a class="link" href="exception_safety_guarantees.html" title="Exception Safety Guarantees">Exception Safety
|
||||
Guarantees</a>
|
||||
</h2></div></div></div>
|
||||
<p>
|
||||
Because of the current implementation (see <a class="link" href="implementation_notes.html" title="Implementation Notes">Implementation
|
||||
Notes</a>), all of the assignment methods:
|
||||
</p>
|
||||
<div class="itemizedlist"><ul class="itemizedlist" type="disc">
|
||||
<li class="listitem">
|
||||
<code class="computeroutput"><span class="identifier">optional</span><span class="special"><</span><span class="identifier">T</span><span class="special">>::</span><span class="keyword">operator</span><span class="special">=</span> <span class="special">(</span> <span class="identifier">optional</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="special">)</span></code>
|
||||
</li>
|
||||
<li class="listitem">
|
||||
<code class="computeroutput"><span class="identifier">optional</span><span class="special"><</span><span class="identifier">T</span><span class="special">>::</span><span class="keyword">operator</span><span class="special">=</span> <span class="special">(</span> <span class="identifier">T</span> <span class="keyword">const</span><span class="special">&</span> <span class="special">)</span></code>
|
||||
</li>
|
||||
<li class="listitem">
|
||||
<code class="computeroutput"><span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">U</span><span class="special">></span> <span class="identifier">optional</span><span class="special"><</span><span class="identifier">T</span><span class="special">>::</span><span class="keyword">operator</span><span class="special">=</span> <span class="special">(</span> <span class="identifier">optional</span><span class="special"><</span><span class="identifier">U</span><span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="special">)</span></code>
|
||||
</li>
|
||||
<li class="listitem">
|
||||
<code class="computeroutput"><span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">InPlaceFactory</span><span class="special">></span> <span class="identifier">optional</span><span class="special"><</span><span class="identifier">T</span><span class="special">>::</span><span class="keyword">operator</span><span class="special">=</span> <span class="special">(</span> <span class="identifier">InPlaceFactory</span>
|
||||
<span class="keyword">const</span><span class="special">&</span>
|
||||
<span class="special">)</span></code>
|
||||
</li>
|
||||
<li class="listitem">
|
||||
<code class="computeroutput"><span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">TypedInPlaceFactory</span><span class="special">></span> <span class="identifier">optional</span><span class="special"><</span><span class="identifier">T</span><span class="special">>::</span><span class="keyword">operator</span><span class="special">=</span> <span class="special">(</span> <span class="identifier">TypedInPlaceFactory</span>
|
||||
<span class="keyword">const</span><span class="special">&</span>
|
||||
<span class="special">)</span> </code>
|
||||
</li>
|
||||
<li class="listitem">
|
||||
<code class="computeroutput"><span class="identifier">optional</span><span class="special"><</span><span class="identifier">T</span><span class="special">>:::</span><span class="identifier">reset</span> <span class="special">(</span> <span class="identifier">T</span> <span class="keyword">const</span><span class="special">&)</span></code>
|
||||
</li>
|
||||
</ul></div>
|
||||
<p>
|
||||
Can only <span class="emphasis"><em>guarantee</em></span> the <span class="underline">basic
|
||||
exception safety</span>: The lvalue optional is left <span class="underline">uninitialized</span>
|
||||
if an exception is thrown (any previous value is <span class="emphasis"><em>first</em></span>
|
||||
destroyed using <code class="computeroutput"><span class="identifier">T</span><span class="special">::~</span><span class="identifier">T</span><span class="special">()</span></code>)
|
||||
</p>
|
||||
<p>
|
||||
On the other hand, the <span class="emphasis"><em>uninitializing</em></span> methods:
|
||||
</p>
|
||||
<div class="itemizedlist"><ul class="itemizedlist" type="disc">
|
||||
<li class="listitem">
|
||||
<code class="computeroutput"><span class="identifier">optional</span><span class="special"><</span><span class="identifier">T</span><span class="special">>::</span><span class="keyword">operator</span><span class="special">=</span> <span class="special">(</span> <span class="identifier">detail</span><span class="special">::</span><span class="identifier">none_t</span> <span class="special">)</span></code>
|
||||
</li>
|
||||
<li class="listitem">
|
||||
<code class="computeroutput"><span class="identifier">optional</span><span class="special"><</span><span class="identifier">T</span><span class="special">>::</span><span class="identifier">reset</span><span class="special">()</span></code>
|
||||
</li>
|
||||
</ul></div>
|
||||
<p>
|
||||
Provide the no-throw guarantee (assuming a no-throw <code class="computeroutput"><span class="identifier">T</span><span class="special">::~</span><span class="identifier">T</span><span class="special">()</span></code>)
|
||||
</p>
|
||||
<p>
|
||||
However, since <code class="computeroutput"><span class="identifier">optional</span><span class="special"><></span></code>
|
||||
itself doesn't throw any exceptions, the only source for exceptions here are
|
||||
<code class="computeroutput"><span class="identifier">T</span></code>'s constructor, so if you
|
||||
know the exception guarantees for <code class="computeroutput"><span class="identifier">T</span><span class="special">::</span><span class="identifier">T</span> <span class="special">(</span>
|
||||
<span class="identifier">T</span> <span class="keyword">const</span><span class="special">&</span> <span class="special">)</span></code>, you
|
||||
know that <code class="computeroutput"><span class="identifier">optional</span></code>'s assignment
|
||||
and reset has the same guarantees.
|
||||
</p>
|
||||
<pre class="programlisting"><span class="comment">//
|
||||
</span><span class="comment">// Case 1: Exception thrown during assignment.
|
||||
</span><span class="comment">//
|
||||
</span><span class="identifier">T</span> <span class="identifier">v0</span><span class="special">(</span><span class="number">123</span><span class="special">);</span>
|
||||
<span class="identifier">optional</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span> <span class="identifier">opt0</span><span class="special">(</span><span class="identifier">v0</span><span class="special">);</span>
|
||||
<span class="keyword">try</span>
|
||||
<span class="special">{</span>
|
||||
<span class="identifier">T</span> <span class="identifier">v1</span><span class="special">(</span><span class="number">456</span><span class="special">);</span>
|
||||
<span class="identifier">optional</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span> <span class="identifier">opt1</span><span class="special">(</span><span class="identifier">v1</span><span class="special">);</span>
|
||||
<span class="identifier">opt0</span> <span class="special">=</span> <span class="identifier">opt1</span> <span class="special">;</span>
|
||||
|
||||
<span class="comment">// If no exception was thrown, assignment succeeded.
|
||||
</span> <span class="identifier">assert</span><span class="special">(</span> <span class="special">*</span><span class="identifier">opt0</span> <span class="special">==</span> <span class="identifier">v1</span> <span class="special">)</span> <span class="special">;</span>
|
||||
<span class="special">}</span>
|
||||
<span class="keyword">catch</span><span class="special">(...)</span>
|
||||
<span class="special">{</span>
|
||||
<span class="comment">// If any exception was thrown, 'opt0' is reset to uninitialized.
|
||||
</span> <span class="identifier">assert</span><span class="special">(</span> <span class="special">!</span><span class="identifier">opt0</span> <span class="special">)</span> <span class="special">;</span>
|
||||
<span class="special">}</span>
|
||||
|
||||
<span class="comment">//
|
||||
</span><span class="comment">// Case 2: Exception thrown during reset(v)
|
||||
</span><span class="comment">//
|
||||
</span><span class="identifier">T</span> <span class="identifier">v0</span><span class="special">(</span><span class="number">123</span><span class="special">);</span>
|
||||
<span class="identifier">optional</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span> <span class="identifier">opt</span><span class="special">(</span><span class="identifier">v0</span><span class="special">);</span>
|
||||
<span class="keyword">try</span>
|
||||
<span class="special">{</span>
|
||||
<span class="identifier">T</span> <span class="identifier">v1</span><span class="special">(</span><span class="number">456</span><span class="special">);</span>
|
||||
<span class="identifier">opt</span><span class="special">.</span><span class="identifier">reset</span> <span class="special">(</span> <span class="identifier">v1</span> <span class="special">)</span> <span class="special">;</span>
|
||||
|
||||
<span class="comment">// If no exception was thrown, reset succeeded.
|
||||
</span> <span class="identifier">assert</span><span class="special">(</span> <span class="special">*</span><span class="identifier">opt</span> <span class="special">==</span> <span class="identifier">v1</span> <span class="special">)</span> <span class="special">;</span>
|
||||
<span class="special">}</span>
|
||||
<span class="keyword">catch</span><span class="special">(...)</span>
|
||||
<span class="special">{</span>
|
||||
<span class="comment">// If any exception was thrown, 'opt' is reset to uninitialized.
|
||||
</span> <span class="identifier">assert</span><span class="special">(</span> <span class="special">!</span><span class="identifier">opt</span> <span class="special">)</span> <span class="special">;</span>
|
||||
<span class="special">}</span>
|
||||
</pre>
|
||||
<a name="boost_optional.exception_safety_guarantees.swap"></a><h4>
|
||||
<a name="boost_optional.exception_safety_guarantees.swap-heading"></a>
|
||||
<a class="link" href="exception_safety_guarantees.html#boost_optional.exception_safety_guarantees.swap">Swap</a>
|
||||
</h4>
|
||||
<p>
|
||||
<code class="computeroutput"><span class="keyword">void</span> <span class="identifier">swap</span><span class="special">(</span> <span class="identifier">optional</span><span class="special"><</span><span class="identifier">T</span><span class="special">>&,</span>
|
||||
<span class="identifier">optional</span><span class="special"><</span><span class="identifier">T</span><span class="special">>&</span> <span class="special">)</span></code> has the same exception guarantee as <code class="computeroutput"><span class="identifier">swap</span><span class="special">(</span><span class="identifier">T</span><span class="special">&,</span><span class="identifier">T</span><span class="special">&)</span></code>
|
||||
when both optionals are initialized. If only one of the optionals is initialized,
|
||||
it gives the same <span class="emphasis"><em>basic</em></span> exception guarantee as <code class="computeroutput"><span class="identifier">optional</span><span class="special"><</span><span class="identifier">T</span><span class="special">>::</span><span class="identifier">reset</span><span class="special">(</span> <span class="identifier">T</span> <span class="keyword">const</span><span class="special">&</span> <span class="special">)</span></code> (since
|
||||
<code class="computeroutput"><span class="identifier">optional</span><span class="special"><</span><span class="identifier">T</span><span class="special">>::</span><span class="identifier">reset</span><span class="special">()</span></code> doesn't throw). If none of the optionals
|
||||
is initialized, it has no-throw guarantee since it is a no-op.
|
||||
</p>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"></td>
|
||||
<td align="right"><div class="copyright-footer">Copyright © 2003-2007 Fernando Luis Cacciola Carballal<p>
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
|
||||
</p>
|
||||
</div></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="a_note_about_optional_bool_.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="type_requirements.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
55
doc/html/boost_optional/implementation_notes.html
Normal file
55
doc/html/boost_optional/implementation_notes.html
Normal file
@ -0,0 +1,55 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
|
||||
<title>Implementation Notes</title>
|
||||
<link rel="stylesheet" href="../boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.75.2">
|
||||
<link rel="home" href="../index.html" title="Chapter 1. Boost.Optional">
|
||||
<link rel="up" href="../index.html" title="Chapter 1. Boost.Optional">
|
||||
<link rel="prev" href="type_requirements.html" title="Type requirements">
|
||||
<link rel="next" href="dependencies_and_portability.html" title="Dependencies and Portability">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
<table cellpadding="2" width="100%"><tr>
|
||||
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td>
|
||||
<td align="center"><a href="../../../../../index.html">Home</a></td>
|
||||
<td align="center"><a href="../../../../../libs/libraries.htm">Libraries</a></td>
|
||||
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
|
||||
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
|
||||
<td align="center"><a href="../../../../../more/index.htm">More</a></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="type_requirements.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="dependencies_and_portability.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||
<a name="boost_optional.implementation_notes"></a><a class="link" href="implementation_notes.html" title="Implementation Notes">Implementation Notes</a>
|
||||
</h2></div></div></div>
|
||||
<p>
|
||||
<code class="computeroutput"><span class="identifier">optional</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span></code> is
|
||||
currently implemented using a custom aligned storage facility built from <code class="computeroutput"><span class="identifier">alignment_of</span></code> and <code class="computeroutput"><span class="identifier">type_with_alignment</span></code>
|
||||
(both from Type Traits). It uses a separate boolean flag to indicate the initialization
|
||||
state. Placement new with <code class="computeroutput"><span class="identifier">T</span></code>'s
|
||||
copy constructor and <code class="computeroutput"><span class="identifier">T</span></code>'s destructor
|
||||
are explicitly used to initialize,copy and destroy optional values. As a result,
|
||||
<code class="computeroutput"><span class="identifier">T</span></code>'s default constructor is
|
||||
effectively by-passed, but the exception guarantees are basic. It is planned
|
||||
to replace the current implementation with another with stronger exception
|
||||
safety, such as a future <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">variant</span></code>.
|
||||
</p>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"></td>
|
||||
<td align="right"><div class="copyright-footer">Copyright © 2003-2007 Fernando Luis Cacciola Carballal<p>
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
|
||||
</p>
|
||||
</div></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="type_requirements.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="dependencies_and_portability.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
196
doc/html/boost_optional/in_place_factories.html
Normal file
196
doc/html/boost_optional/in_place_factories.html
Normal file
@ -0,0 +1,196 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
|
||||
<title>In-Place Factories</title>
|
||||
<link rel="stylesheet" href="../boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.75.2">
|
||||
<link rel="home" href="../index.html" title="Chapter 1. Boost.Optional">
|
||||
<link rel="up" href="../index.html" title="Chapter 1. Boost.Optional">
|
||||
<link rel="prev" href="rebinding_semantics_for_assignment_of_optional_references.html" title="Rebinding semantics for assignment of optional references">
|
||||
<link rel="next" href="a_note_about_optional_bool_.html" title="A note about optional<bool>">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
<table cellpadding="2" width="100%"><tr>
|
||||
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td>
|
||||
<td align="center"><a href="../../../../../index.html">Home</a></td>
|
||||
<td align="center"><a href="../../../../../libs/libraries.htm">Libraries</a></td>
|
||||
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
|
||||
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
|
||||
<td align="center"><a href="../../../../../more/index.htm">More</a></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="rebinding_semantics_for_assignment_of_optional_references.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="a_note_about_optional_bool_.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||
<a name="boost_optional.in_place_factories"></a><a class="link" href="in_place_factories.html" title="In-Place Factories">In-Place Factories</a>
|
||||
</h2></div></div></div>
|
||||
<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" target="_top">Copy Constructible</a>,
|
||||
but also requires the existence of a fully constructed object, often temporary,
|
||||
just to follow the copy from:
|
||||
</p>
|
||||
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">X</span>
|
||||
<span class="special">{</span>
|
||||
<span class="identifier">X</span> <span class="special">(</span> <span class="keyword">int</span><span class="special">,</span> <span class="identifier">std</span><span class="special">:::</span><span class="identifier">string</span> <span class="special">)</span> <span class="special">;</span>
|
||||
<span class="special">}</span> <span class="special">;</span>
|
||||
|
||||
<span class="keyword">class</span> <span class="identifier">W</span>
|
||||
<span class="special">{</span>
|
||||
<span class="identifier">X</span> <span class="identifier">wrapped_</span> <span class="special">;</span>
|
||||
|
||||
<span class="keyword">public</span><span class="special">:</span>
|
||||
|
||||
<span class="identifier">W</span> <span class="special">(</span> <span class="identifier">X</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">x</span> <span class="special">)</span> <span class="special">:</span> <span class="identifier">wrapped_</span><span class="special">(</span><span class="identifier">x</span><span class="special">)</span> <span class="special">{}</span>
|
||||
<span class="special">}</span> <span class="special">;</span>
|
||||
|
||||
<span class="keyword">void</span> <span class="identifier">foo</span><span class="special">()</span>
|
||||
<span class="special">{</span>
|
||||
<span class="comment">// Temporary object created.
|
||||
</span> <span class="identifier">W</span> <span class="special">(</span> <span class="identifier">X</span><span class="special">(</span><span class="number">123</span><span class="special">,</span><span class="string">"hello"</span><span class="special">)</span> <span class="special">)</span> <span class="special">;</span>
|
||||
<span class="special">}</span>
|
||||
</pre>
|
||||
<p>
|
||||
A solution to this problem is to support direct construction of the contained
|
||||
object right in the container's storage. In this scheme, the user only needs
|
||||
to supply the arguments to the constructor to use in the wrapped object construction.
|
||||
</p>
|
||||
<pre class="programlisting"><span class="keyword">class</span> <span class="identifier">W</span>
|
||||
<span class="special">{</span>
|
||||
<span class="identifier">X</span> <span class="identifier">wrapped_</span> <span class="special">;</span>
|
||||
|
||||
<span class="keyword">public</span><span class="special">:</span>
|
||||
|
||||
<span class="identifier">W</span> <span class="special">(</span> <span class="identifier">X</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">x</span> <span class="special">)</span> <span class="special">:</span> <span class="identifier">wrapped_</span><span class="special">(</span><span class="identifier">x</span><span class="special">)</span> <span class="special">{}</span>
|
||||
<span class="identifier">W</span> <span class="special">(</span> <span class="keyword">int</span> <span class="identifier">a0</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">a1</span><span class="special">)</span> <span class="special">:</span> <span class="identifier">wrapped_</span><span class="special">(</span><span class="identifier">a0</span><span class="special">,</span><span class="identifier">a1</span><span class="special">)</span> <span class="special">{}</span>
|
||||
<span class="special">}</span> <span class="special">;</span>
|
||||
|
||||
<span class="keyword">void</span> <span class="identifier">foo</span><span class="special">()</span>
|
||||
<span class="special">{</span>
|
||||
<span class="comment">// Wrapped object constructed in-place
|
||||
</span> <span class="comment">// No temporary created.
|
||||
</span> <span class="identifier">W</span> <span class="special">(</span><span class="number">123</span><span class="special">,</span><span class="string">"hello"</span><span class="special">)</span> <span class="special">;</span>
|
||||
<span class="special">}</span>
|
||||
</pre>
|
||||
<p>
|
||||
A limitation of this method is that it doesn't scale well to wrapped objects
|
||||
with multiple constructors nor to generic code were the constructor overloads
|
||||
are unknown.
|
||||
</p>
|
||||
<p>
|
||||
The solution presented in this library is the family of <span class="bold"><strong>InPlaceFactories</strong></span>
|
||||
and <span class="bold"><strong>TypedInPlaceFactories</strong></span>. 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 family looks like:
|
||||
</p>
|
||||
<pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span><span class="keyword">class</span> <span class="identifier">A0</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">A1</span><span class="special">></span>
|
||||
<span class="keyword">class</span> <span class="identifier">TypedInPlaceFactory2</span>
|
||||
<span class="special">{</span>
|
||||
<span class="identifier">A0</span> <span class="identifier">m_a0</span> <span class="special">;</span> <span class="identifier">A1</span> <span class="identifier">m_a1</span> <span class="special">;</span>
|
||||
|
||||
<span class="keyword">public</span><span class="special">:</span>
|
||||
|
||||
<span class="identifier">TypedInPlaceFactory2</span><span class="special">(</span> <span class="identifier">A0</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">a0</span><span class="special">,</span> <span class="identifier">A1</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">a1</span> <span class="special">)</span> <span class="special">:</span> <span class="identifier">m_a0</span><span class="special">(</span><span class="identifier">a0</span><span class="special">),</span> <span class="identifier">m_a1</span><span class="special">(</span><span class="identifier">a1</span><span class="special">)</span> <span class="special">{}</span>
|
||||
|
||||
<span class="keyword">void</span> <span class="identifier">construct</span> <span class="special">(</span> <span class="keyword">void</span><span class="special">*</span> <span class="identifier">p</span> <span class="special">)</span> <span class="special">{</span> <span class="keyword">new</span> <span class="special">(</span><span class="identifier">p</span><span class="special">)</span> <span class="identifier">T</span><span class="special">(</span><span class="identifier">m_a0</span><span class="special">,</span><span class="identifier">m_a1</span><span class="special">)</span> <span class="special">;</span> <span class="special">}</span>
|
||||
<span class="special">}</span> <span class="special">;</span>
|
||||
</pre>
|
||||
<p>
|
||||
A wrapper class aware of this can use it as:
|
||||
</p>
|
||||
<pre class="programlisting"><span class="keyword">class</span> <span class="identifier">W</span>
|
||||
<span class="special">{</span>
|
||||
<span class="identifier">X</span> <span class="identifier">wrapped_</span> <span class="special">;</span>
|
||||
|
||||
<span class="keyword">public</span><span class="special">:</span>
|
||||
|
||||
<span class="identifier">W</span> <span class="special">(</span> <span class="identifier">X</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">x</span> <span class="special">)</span> <span class="special">:</span> <span class="identifier">wrapped_</span><span class="special">(</span><span class="identifier">x</span><span class="special">)</span> <span class="special">{}</span>
|
||||
<span class="identifier">W</span> <span class="special">(</span> <span class="identifier">TypedInPlaceFactory2</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">fac</span> <span class="special">)</span> <span class="special">{</span> <span class="identifier">fac</span><span class="special">.</span><span class="identifier">construct</span><span class="special">(&</span><span class="identifier">wrapped_</span><span class="special">)</span> <span class="special">;</span> <span class="special">}</span>
|
||||
<span class="special">}</span> <span class="special">;</span>
|
||||
|
||||
<span class="keyword">void</span> <span class="identifier">foo</span><span class="special">()</span>
|
||||
<span class="special">{</span>
|
||||
<span class="comment">// Wrapped object constructed in-place via a TypedInPlaceFactory.
|
||||
</span> <span class="comment">// No temporary created.
|
||||
</span> <span class="identifier">W</span> <span class="special">(</span> <span class="identifier">TypedInPlaceFactory2</span><span class="special"><</span><span class="identifier">X</span><span class="special">,</span><span class="keyword">int</span><span class="special">,</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">>(</span><span class="number">123</span><span class="special">,</span><span class="string">"hello"</span><span class="special">))</span> <span class="special">;</span>
|
||||
<span class="special">}</span>
|
||||
</pre>
|
||||
<p>
|
||||
The factories are divided in two groups:
|
||||
</p>
|
||||
<div class="itemizedlist"><ul class="itemizedlist" type="disc">
|
||||
<li class="listitem">
|
||||
<span class="underline">TypedInPlaceFactories</span>: those which
|
||||
take the target type as a primary template parameter.
|
||||
</li>
|
||||
<li class="listitem">
|
||||
<span class="underline">InPlaceFactories</span>: those with a template
|
||||
<code class="computeroutput"><span class="identifier">construct</span><span class="special">(</span><span class="keyword">void</span><span class="special">*)</span></code> member
|
||||
function taking the target type.
|
||||
</li>
|
||||
</ul></div>
|
||||
<p>
|
||||
Within each group, all the family members differ only in the number of parameters
|
||||
allowed.
|
||||
</p>
|
||||
<p>
|
||||
This library provides an overloaded set of helper template functions to construct
|
||||
these factories without requiring unnecessary template parameters:
|
||||
</p>
|
||||
<pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">A0</span><span class="special">,...,</span><span class="keyword">class</span> <span class="identifier">AN</span><span class="special">></span>
|
||||
<span class="identifier">InPlaceFactoryN</span> <span class="special"><</span><span class="identifier">A0</span><span class="special">,...,</span><span class="identifier">AN</span><span class="special">></span> <span class="identifier">in_place</span> <span class="special">(</span> <span class="identifier">A0</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">a0</span><span class="special">,</span> <span class="special">...,</span> <span class="identifier">AN</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">aN</span><span class="special">)</span> <span class="special">;</span>
|
||||
|
||||
<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span><span class="keyword">class</span> <span class="identifier">A0</span><span class="special">,...,</span><span class="keyword">class</span> <span class="identifier">AN</span><span class="special">></span>
|
||||
<span class="identifier">TypedInPlaceFactoryN</span> <span class="special"><</span><span class="identifier">T</span><span class="special">,</span><span class="identifier">A0</span><span class="special">,...,</span><span class="identifier">AN</span><span class="special">></span> <span class="identifier">in_place</span> <span class="special">(</span> <span class="identifier">T</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">a0</span><span class="special">,</span> <span class="identifier">A0</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">a0</span><span class="special">,</span> <span class="special">...,</span> <span class="identifier">AN</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">aN</span><span class="special">)</span> <span class="special">;</span>
|
||||
</pre>
|
||||
<p>
|
||||
In-place factories can be used generically by the wrapper and user as follows:
|
||||
</p>
|
||||
<pre class="programlisting"><span class="keyword">class</span> <span class="identifier">W</span>
|
||||
<span class="special">{</span>
|
||||
<span class="identifier">X</span> <span class="identifier">wrapped_</span> <span class="special">;</span>
|
||||
|
||||
<span class="keyword">public</span><span class="special">:</span>
|
||||
|
||||
<span class="identifier">W</span> <span class="special">(</span> <span class="identifier">X</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">x</span> <span class="special">)</span> <span class="special">:</span> <span class="identifier">wrapped_</span><span class="special">(</span><span class="identifier">x</span><span class="special">)</span> <span class="special">{}</span>
|
||||
|
||||
<span class="keyword">template</span><span class="special"><</span> <span class="keyword">class</span> <span class="identifier">InPlaceFactory</span> <span class="special">></span>
|
||||
<span class="identifier">W</span> <span class="special">(</span> <span class="identifier">InPlaceFactory</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">fac</span> <span class="special">)</span> <span class="special">{</span> <span class="identifier">fac</span><span class="special">.</span><span class="keyword">template</span> <span class="special"><</span><span class="identifier">X</span><span class="special">></span><span class="identifier">construct</span><span class="special">(&</span><span class="identifier">wrapped_</span><span class="special">)</span> <span class="special">;</span> <span class="special">}</span>
|
||||
|
||||
<span class="special">}</span> <span class="special">;</span>
|
||||
|
||||
<span class="keyword">void</span> <span class="identifier">foo</span><span class="special">()</span>
|
||||
<span class="special">{</span>
|
||||
<span class="comment">// Wrapped object constructed in-place via a InPlaceFactory.
|
||||
</span> <span class="comment">// No temporary created.
|
||||
</span> <span class="identifier">W</span> <span class="special">(</span> <span class="identifier">in_place</span><span class="special">(</span><span class="number">123</span><span class="special">,</span><span class="string">"hello"</span><span class="special">)</span> <span class="special">)</span> <span class="special">;</span>
|
||||
<span class="special">}</span>
|
||||
</pre>
|
||||
<p>
|
||||
The factories are implemented in the headers: <a href="../../../../../boost/utility/in_place_factory.hpp" target="_top">in_place_factory.hpp</a>
|
||||
and <a href="../../../../../boost/utility/typed_in_place_factory.hpp" target="_top">typed_in_place_factory.hpp</a>
|
||||
</p>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"></td>
|
||||
<td align="right"><div class="copyright-footer">Copyright © 2003-2007 Fernando Luis Cacciola Carballal<p>
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
|
||||
</p>
|
||||
</div></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="rebinding_semantics_for_assignment_of_optional_references.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="a_note_about_optional_bool_.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
85
doc/html/boost_optional/optional_references.html
Normal file
85
doc/html/boost_optional/optional_references.html
Normal file
@ -0,0 +1,85 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
|
||||
<title>Optional references</title>
|
||||
<link rel="stylesheet" href="../boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.75.2">
|
||||
<link rel="home" href="../index.html" title="Chapter 1. Boost.Optional">
|
||||
<link rel="up" href="../index.html" title="Chapter 1. Boost.Optional">
|
||||
<link rel="prev" href="examples.html" title="Examples">
|
||||
<link rel="next" href="rebinding_semantics_for_assignment_of_optional_references.html" title="Rebinding semantics for assignment of optional references">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
<table cellpadding="2" width="100%"><tr>
|
||||
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td>
|
||||
<td align="center"><a href="../../../../../index.html">Home</a></td>
|
||||
<td align="center"><a href="../../../../../libs/libraries.htm">Libraries</a></td>
|
||||
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
|
||||
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
|
||||
<td align="center"><a href="../../../../../more/index.htm">More</a></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="examples.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="rebinding_semantics_for_assignment_of_optional_references.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||
<a name="boost_optional.optional_references"></a><a class="link" href="optional_references.html" title="Optional references">Optional references</a>
|
||||
</h2></div></div></div>
|
||||
<p>
|
||||
This library allows the template parameter <code class="computeroutput"><span class="identifier">T</span></code>
|
||||
to be of reference type: <code class="computeroutput"><span class="identifier">T</span><span class="special">&</span></code>, and to some extent, <code class="computeroutput"><span class="identifier">T</span>
|
||||
<span class="keyword">const</span><span class="special">&</span></code>.
|
||||
</p>
|
||||
<p>
|
||||
However, since references are not real objects some restrictions apply and
|
||||
some operations are not available in this case:
|
||||
</p>
|
||||
<div class="itemizedlist"><ul class="itemizedlist" type="disc">
|
||||
<li class="listitem">
|
||||
Converting constructors
|
||||
</li>
|
||||
<li class="listitem">
|
||||
Converting assignment
|
||||
</li>
|
||||
<li class="listitem">
|
||||
InPlace construction
|
||||
</li>
|
||||
<li class="listitem">
|
||||
InPlace assignment
|
||||
</li>
|
||||
<li class="listitem">
|
||||
Value-access via pointer
|
||||
</li>
|
||||
</ul></div>
|
||||
<p>
|
||||
Also, even though <code class="computeroutput"><span class="identifier">optional</span><span class="special"><</span><span class="identifier">T</span><span class="special">&></span></code>
|
||||
treats it wrapped pseudo-object much as a real value, a true real reference
|
||||
is stored so aliasing will ocurr:
|
||||
</p>
|
||||
<div class="itemizedlist"><ul class="itemizedlist" type="disc">
|
||||
<li class="listitem">
|
||||
Copies of <code class="computeroutput"><span class="identifier">optional</span><span class="special"><</span><span class="identifier">T</span><span class="special">&></span></code>
|
||||
will copy the references but all these references will nonetheless reefer
|
||||
to the same object.
|
||||
</li>
|
||||
<li class="listitem">
|
||||
Value-access will actually provide access to the referenced object rather
|
||||
than the reference itself.
|
||||
</li>
|
||||
</ul></div>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"></td>
|
||||
<td align="right"><div class="copyright-footer">Copyright © 2003-2007 Fernando Luis Cacciola Carballal<p>
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
|
||||
</p>
|
||||
</div></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="examples.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="rebinding_semantics_for_assignment_of_optional_references.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,148 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
|
||||
<title>Rebinding semantics for assignment of optional references</title>
|
||||
<link rel="stylesheet" href="../boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.75.2">
|
||||
<link rel="home" href="../index.html" title="Chapter 1. Boost.Optional">
|
||||
<link rel="up" href="../index.html" title="Chapter 1. Boost.Optional">
|
||||
<link rel="prev" href="optional_references.html" title="Optional references">
|
||||
<link rel="next" href="in_place_factories.html" title="In-Place Factories">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
<table cellpadding="2" width="100%"><tr>
|
||||
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td>
|
||||
<td align="center"><a href="../../../../../index.html">Home</a></td>
|
||||
<td align="center"><a href="../../../../../libs/libraries.htm">Libraries</a></td>
|
||||
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
|
||||
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
|
||||
<td align="center"><a href="../../../../../more/index.htm">More</a></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="optional_references.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="in_place_factories.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||
<a name="boost_optional.rebinding_semantics_for_assignment_of_optional_references"></a><a class="link" href="rebinding_semantics_for_assignment_of_optional_references.html" title="Rebinding semantics for assignment of optional references">Rebinding
|
||||
semantics for assignment of optional references</a>
|
||||
</h2></div></div></div>
|
||||
<p>
|
||||
If you assign to an <span class="emphasis"><em>uninitialized </em></span> <code class="computeroutput"><span class="identifier">optional</span><span class="special"><</span><span class="identifier">T</span><span class="special">&></span></code>
|
||||
the effect is to bind (for the first time) to the object. Clearly, there is
|
||||
no other choice.
|
||||
</p>
|
||||
<pre class="programlisting"><span class="keyword">int</span> <span class="identifier">x</span> <span class="special">=</span> <span class="number">1</span> <span class="special">;</span>
|
||||
<span class="keyword">int</span><span class="special">&</span> <span class="identifier">rx</span> <span class="special">=</span> <span class="identifier">x</span> <span class="special">;</span>
|
||||
<span class="identifier">optional</span><span class="special"><</span><span class="keyword">int</span><span class="special">&></span> <span class="identifier">ora</span> <span class="special">;</span>
|
||||
<span class="identifier">optional</span><span class="special"><</span><span class="keyword">int</span><span class="special">&></span> <span class="identifier">orb</span><span class="special">(</span><span class="identifier">x</span><span class="special">)</span> <span class="special">;</span>
|
||||
<span class="identifier">ora</span> <span class="special">=</span> <span class="identifier">orb</span> <span class="special">;</span> <span class="comment">// now 'ora' is bound to 'x' through 'rx'
|
||||
</span><span class="special">*</span><span class="identifier">ora</span> <span class="special">=</span> <span class="number">2</span> <span class="special">;</span> <span class="comment">// Changes value of 'x' through 'ora'
|
||||
</span><span class="identifier">assert</span><span class="special">(</span><span class="identifier">x</span><span class="special">==</span><span class="number">2</span><span class="special">);</span>
|
||||
</pre>
|
||||
<p>
|
||||
If you assign to a bare C++ reference, the assignment is forwarded to the referenced
|
||||
object; its value changes but the reference is never rebound.
|
||||
</p>
|
||||
<pre class="programlisting"><span class="keyword">int</span> <span class="identifier">a</span> <span class="special">=</span> <span class="number">1</span> <span class="special">;</span>
|
||||
<span class="keyword">int</span><span class="special">&</span> <span class="identifier">ra</span> <span class="special">=</span> <span class="identifier">a</span> <span class="special">;</span>
|
||||
<span class="keyword">int</span> <span class="identifier">b</span> <span class="special">=</span> <span class="number">2</span> <span class="special">;</span>
|
||||
<span class="keyword">int</span><span class="special">&</span> <span class="identifier">rb</span> <span class="special">=</span> <span class="identifier">b</span> <span class="special">;</span>
|
||||
<span class="identifier">ra</span> <span class="special">=</span> <span class="identifier">rb</span> <span class="special">;</span> <span class="comment">// Changes the value of 'a' to 'b'
|
||||
</span><span class="identifier">assert</span><span class="special">(</span><span class="identifier">a</span><span class="special">==</span><span class="identifier">b</span><span class="special">);</span>
|
||||
<span class="identifier">b</span> <span class="special">=</span> <span class="number">3</span> <span class="special">;</span>
|
||||
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">ra</span><span class="special">!=</span><span class="identifier">b</span><span class="special">);</span> <span class="comment">// 'ra' is not rebound to 'b'
|
||||
</span></pre>
|
||||
<p>
|
||||
Now, if you assign to an <span class="emphasis"><em>initialized </em></span> <code class="computeroutput"><span class="identifier">optional</span><span class="special"><</span><span class="identifier">T</span><span class="special">&></span></code>,
|
||||
the effect is to <span class="bold"><strong>rebind</strong></span> to the new object
|
||||
instead of assigning the referee. This is unlike bare C++ references.
|
||||
</p>
|
||||
<pre class="programlisting"><span class="keyword">int</span> <span class="identifier">a</span> <span class="special">=</span> <span class="number">1</span> <span class="special">;</span>
|
||||
<span class="keyword">int</span> <span class="identifier">b</span> <span class="special">=</span> <span class="number">2</span> <span class="special">;</span>
|
||||
<span class="keyword">int</span><span class="special">&</span> <span class="identifier">ra</span> <span class="special">=</span> <span class="identifier">a</span> <span class="special">;</span>
|
||||
<span class="keyword">int</span><span class="special">&</span> <span class="identifier">rb</span> <span class="special">=</span> <span class="identifier">b</span> <span class="special">;</span>
|
||||
<span class="identifier">optional</span><span class="special"><</span><span class="keyword">int</span><span class="special">&></span> <span class="identifier">ora</span><span class="special">(</span><span class="identifier">ra</span><span class="special">)</span> <span class="special">;</span>
|
||||
<span class="identifier">optional</span><span class="special"><</span><span class="keyword">int</span><span class="special">&></span> <span class="identifier">orb</span><span class="special">(</span><span class="identifier">rb</span><span class="special">)</span> <span class="special">;</span>
|
||||
<span class="identifier">ora</span> <span class="special">=</span> <span class="identifier">orb</span> <span class="special">;</span> <span class="comment">// 'ora' is rebound to 'b'
|
||||
</span><span class="special">*</span><span class="identifier">ora</span> <span class="special">=</span> <span class="number">3</span> <span class="special">;</span> <span class="comment">// Changes value of 'b' (not 'a')
|
||||
</span><span class="identifier">assert</span><span class="special">(</span><span class="identifier">a</span><span class="special">==</span><span class="number">1</span><span class="special">);</span>
|
||||
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">b</span><span class="special">==</span><span class="number">3</span><span class="special">);</span>
|
||||
</pre>
|
||||
<a name="boost_optional.rebinding_semantics_for_assignment_of_optional_references.rationale"></a><h4>
|
||||
<a name="boost_optional.rebinding_semantics_for_assignment_of_optional_references.rationale-heading"></a>
|
||||
<a class="link" href="rebinding_semantics_for_assignment_of_optional_references.html#boost_optional.rebinding_semantics_for_assignment_of_optional_references.rationale">Rationale</a>
|
||||
</h4>
|
||||
<p>
|
||||
Rebinding semantics for the assignment of <span class="emphasis"><em>initialized </em></span>
|
||||
<code class="computeroutput"><span class="identifier">optional</span></code> references has been
|
||||
chosen to provide <span class="bold"><strong>consistency among initialization states</strong></span>
|
||||
even at the expense of lack of consistency with the semantics of bare C++ references.
|
||||
It is true that <code class="computeroutput"><span class="identifier">optional</span><span class="special"><</span><span class="identifier">U</span><span class="special">></span></code> strives
|
||||
to behave as much as possible as <code class="computeroutput"><span class="identifier">U</span></code>
|
||||
does whenever it is initialized; but in the case when <code class="computeroutput"><span class="identifier">U</span></code>
|
||||
is <code class="computeroutput"><span class="identifier">T</span><span class="special">&</span></code>,
|
||||
doing so would result in inconsistent behavior w.r.t to the lvalue initialization
|
||||
state.
|
||||
</p>
|
||||
<p>
|
||||
Imagine <code class="computeroutput"><span class="identifier">optional</span><span class="special"><</span><span class="identifier">T</span><span class="special">&></span></code>
|
||||
forwarding assignment to the referenced object (thus changing the referenced
|
||||
object value but not rebinding), and consider the following code:
|
||||
</p>
|
||||
<pre class="programlisting"><span class="identifier">optional</span><span class="special"><</span><span class="keyword">int</span><span class="special">&></span> <span class="identifier">a</span> <span class="special">=</span> <span class="identifier">get</span><span class="special">();</span>
|
||||
<span class="keyword">int</span> <span class="identifier">x</span> <span class="special">=</span> <span class="number">1</span> <span class="special">;</span>
|
||||
<span class="keyword">int</span><span class="special">&</span> <span class="identifier">rx</span> <span class="special">=</span> <span class="identifier">x</span> <span class="special">;</span>
|
||||
<span class="identifier">optional</span><span class="special"><</span><span class="keyword">int</span><span class="special">&></span> <span class="identifier">b</span><span class="special">(</span><span class="identifier">rx</span><span class="special">);</span>
|
||||
<span class="identifier">a</span> <span class="special">=</span> <span class="identifier">b</span> <span class="special">;</span>
|
||||
</pre>
|
||||
<p>
|
||||
What does the assignment do?
|
||||
</p>
|
||||
<p>
|
||||
If <code class="computeroutput"><span class="identifier">a</span></code> is <span class="emphasis"><em>uninitialized</em></span>,
|
||||
the answer is clear: it binds to <code class="computeroutput"><span class="identifier">x</span></code>
|
||||
(we now have another reference to <code class="computeroutput"><span class="identifier">x</span></code>).
|
||||
But what if <code class="computeroutput"><span class="identifier">a</span></code> is already <span class="emphasis"><em>initialized</em></span>?
|
||||
it would change the value of the referenced object (whatever that is); which
|
||||
is inconsistent with the other possible case.
|
||||
</p>
|
||||
<p>
|
||||
If <code class="computeroutput"><span class="identifier">optional</span><span class="special"><</span><span class="identifier">T</span><span class="special">&></span></code>
|
||||
would assign just like <code class="computeroutput"><span class="identifier">T</span><span class="special">&</span></code>
|
||||
does, you would never be able to use Optional's assignment without explicitly
|
||||
handling the previous initialization state unless your code is capable of functioning
|
||||
whether after the assignment, <code class="computeroutput"><span class="identifier">a</span></code>
|
||||
aliases the same object as <code class="computeroutput"><span class="identifier">b</span></code>
|
||||
or not.
|
||||
</p>
|
||||
<p>
|
||||
That is, you would have to discriminate in order to be consistent.
|
||||
</p>
|
||||
<p>
|
||||
If in your code rebinding to another object is not an option, then it is very
|
||||
likely that binding for the first time isn't either. In such case, assignment
|
||||
to an <span class="emphasis"><em>uninitialized </em></span> <code class="computeroutput"><span class="identifier">optional</span><span class="special"><</span><span class="identifier">T</span><span class="special">&></span></code>
|
||||
shall be prohibited. It is quite possible that in such a scenario it is a precondition
|
||||
that the lvalue must be already initialized. If it isn't, then binding for
|
||||
the first time is OK while rebinding is not which is IMO very unlikely. In
|
||||
such a scenario, you can assign the value itself directly, as in:
|
||||
</p>
|
||||
<pre class="programlisting"><span class="identifier">assert</span><span class="special">(!!</span><span class="identifier">opt</span><span class="special">);</span>
|
||||
<span class="special">*</span><span class="identifier">opt</span><span class="special">=</span><span class="identifier">value</span><span class="special">;</span>
|
||||
</pre>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"></td>
|
||||
<td align="right"><div class="copyright-footer">Copyright © 2003-2007 Fernando Luis Cacciola Carballal<p>
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
|
||||
</p>
|
||||
</div></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="optional_references.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="in_place_factories.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
152
doc/html/boost_optional/synopsis.html
Normal file
152
doc/html/boost_optional/synopsis.html
Normal file
@ -0,0 +1,152 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
|
||||
<title>Synopsis</title>
|
||||
<link rel="stylesheet" href="../boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.75.2">
|
||||
<link rel="home" href="../index.html" title="Chapter 1. Boost.Optional">
|
||||
<link rel="up" href="../index.html" title="Chapter 1. Boost.Optional">
|
||||
<link rel="prev" href="development.html" title="Development">
|
||||
<link rel="next" href="detailed_semantics.html" title="Detailed Semantics">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
<table cellpadding="2" width="100%"><tr>
|
||||
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td>
|
||||
<td align="center"><a href="../../../../../index.html">Home</a></td>
|
||||
<td align="center"><a href="../../../../../libs/libraries.htm">Libraries</a></td>
|
||||
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
|
||||
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
|
||||
<td align="center"><a href="../../../../../more/index.htm">More</a></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="development.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="detailed_semantics.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||
<a name="boost_optional.synopsis"></a><a class="link" href="synopsis.html" title="Synopsis">Synopsis</a>
|
||||
</h2></div></div></div>
|
||||
<pre class="programlisting"><code class="computeroutput"><span class="comment">// In Header: <</span></code><a href="../../../../../boost/optional/optional.hpp" target="_top">boost/optional/optional.hpp</a><span class="comment">></span>
|
||||
|
||||
<span class="keyword">namespace</span> <span class="identifier">boost</span> <span class="special">{</span>
|
||||
|
||||
<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span>
|
||||
<span class="keyword">class</span> <span class="identifier">optional</span>
|
||||
<span class="special">{</span>
|
||||
<span class="keyword">public</span> <span class="special">:</span>
|
||||
|
||||
<span class="comment">// (If T is of reference type, the parameters and results by reference are by value)
|
||||
</span>
|
||||
<span class="identifier">optional</span> <span class="special">()</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_optional_constructor"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
|
||||
|
||||
<span class="identifier">optional</span> <span class="special">(</span> <span class="identifier">none_t</span> <span class="special">)</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_optional_constructor_none_t"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
|
||||
|
||||
<span class="identifier">optional</span> <span class="special">(</span> <span class="identifier">T</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">v</span> <span class="special">)</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_optional_constructor_value"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
|
||||
|
||||
<span class="comment">// [new in 1.34]
|
||||
</span> <span class="identifier">optional</span> <span class="special">(</span> <span class="keyword">bool</span> <span class="identifier">condition</span><span class="special">,</span> <span class="identifier">T</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">v</span> <span class="special">)</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_optional_constructor_bool_value"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
|
||||
|
||||
<span class="identifier">optional</span> <span class="special">(</span> <span class="identifier">optional</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">rhs</span> <span class="special">)</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_optional_constructor_optional"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
|
||||
|
||||
<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">U</span><span class="special">></span> <span class="keyword">explicit</span> <span class="identifier">optional</span> <span class="special">(</span> <span class="identifier">optional</span><span class="special"><</span><span class="identifier">U</span><span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">rhs</span> <span class="special">)</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_optional_constructor_other_optional"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
|
||||
|
||||
<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">InPlaceFactory</span><span class="special">></span> <span class="keyword">explicit</span> <span class="identifier">optional</span> <span class="special">(</span> <span class="identifier">InPlaceFactory</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">f</span> <span class="special">)</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_optional_constructor_factory"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
|
||||
|
||||
<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">TypedInPlaceFactory</span><span class="special">></span> <span class="keyword">explicit</span> <span class="identifier">optional</span> <span class="special">(</span> <span class="identifier">TypedInPlaceFactory</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">f</span> <span class="special">)</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_optional_constructor_factory"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
|
||||
|
||||
<span class="identifier">optional</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">=</span> <span class="special">(</span> <span class="identifier">none_t</span> <span class="special">)</span> <span class="special">;</span>
|
||||
|
||||
<span class="identifier">optional</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">=</span> <span class="special">(</span> <span class="identifier">T</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">v</span> <span class="special">)</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_optional_operator_equal_value"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
|
||||
|
||||
<span class="identifier">optional</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">=</span> <span class="special">(</span> <span class="identifier">optional</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">rhs</span> <span class="special">)</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_optional_operator_equal_optional"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
|
||||
|
||||
<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">U</span><span class="special">></span> <span class="identifier">optional</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">=</span> <span class="special">(</span> <span class="identifier">optional</span><span class="special"><</span><span class="identifier">U</span><span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">rhs</span> <span class="special">)</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_optional_operator_equal_other_optional"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
|
||||
|
||||
<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">InPlaceFactory</span><span class="special">></span> <span class="identifier">optional</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">=</span> <span class="special">(</span> <span class="identifier">InPlaceFactory</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">f</span> <span class="special">)</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_optional_operator_equal_factory"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
|
||||
|
||||
<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">TypedInPlaceFactory</span><span class="special">></span> <span class="identifier">optional</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">=</span> <span class="special">(</span> <span class="identifier">TypedInPlaceFactory</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">f</span> <span class="special">)</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_optional_operator_equal_factory"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
|
||||
|
||||
<span class="identifier">T</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">get</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_optional_get"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
|
||||
<span class="identifier">T</span><span class="special">&</span> <span class="identifier">get</span><span class="special">()</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_optional_get"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
|
||||
|
||||
<span class="comment">// [new in 1.34]
|
||||
</span> <span class="identifier">T</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">get_value_or</span><span class="special">(</span> <span class="identifier">T</span> <span class="keyword">const</span><span class="special">&</span> <span class="keyword">default</span> <span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_optional_get_value_or_value"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
|
||||
|
||||
<span class="identifier">T</span> <span class="keyword">const</span><span class="special">*</span> <span class="keyword">operator</span> <span class="special">->()</span> <span class="keyword">const</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_optional_operator_arrow"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
|
||||
<span class="identifier">T</span><span class="special">*</span> <span class="keyword">operator</span> <span class="special">->()</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_optional_operator_arrow"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
|
||||
|
||||
<span class="identifier">T</span> <span class="keyword">const</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">*()</span> <span class="keyword">const</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_optional_get"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
|
||||
<span class="identifier">T</span><span class="special">&</span> <span class="keyword">operator</span> <span class="special">*()</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_optional_get"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
|
||||
|
||||
<span class="identifier">T</span> <span class="keyword">const</span><span class="special">*</span> <span class="identifier">get_ptr</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_optional_get_ptr"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
|
||||
<span class="identifier">T</span><span class="special">*</span> <span class="identifier">get_ptr</span><span class="special">()</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_optional_get_ptr"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
|
||||
|
||||
<span class="keyword">operator</span> <span class="identifier">unspecified</span><span class="special">-</span><span class="keyword">bool</span><span class="special">-</span><span class="identifier">type</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_optional_operator_bool"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
|
||||
|
||||
<span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">!()</span> <span class="keyword">const</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_optional_operator_not"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
|
||||
|
||||
<span class="comment">// deprecated methods
|
||||
</span>
|
||||
<span class="comment">// (deprecated)
|
||||
</span> <span class="keyword">void</span> <span class="identifier">reset</span><span class="special">()</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_optional_reset"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
|
||||
|
||||
<span class="comment">// (deprecated)
|
||||
</span> <span class="keyword">void</span> <span class="identifier">reset</span> <span class="special">(</span> <span class="identifier">T</span> <span class="keyword">const</span><span class="special">&</span> <span class="special">)</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_optional_reset_value"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
|
||||
|
||||
<span class="comment">// (deprecated)
|
||||
</span> <span class="keyword">bool</span> <span class="identifier">is_initialized</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_optional_is_initialized"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
|
||||
|
||||
<span class="special">};</span>
|
||||
|
||||
<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span> <span class="keyword">inline</span> <span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">==</span> <span class="special">(</span> <span class="identifier">optional</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">x</span><span class="special">,</span> <span class="identifier">optional</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">y</span> <span class="special">)</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_operator_compare_equal_optional_optional"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
|
||||
|
||||
<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span> <span class="keyword">inline</span> <span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">!=</span> <span class="special">(</span> <span class="identifier">optional</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">x</span><span class="special">,</span> <span class="identifier">optional</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">y</span> <span class="special">)</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_operator_compare_not_equal_optional_optional"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
|
||||
|
||||
<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span> <span class="keyword">inline</span> <span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special"><</span> <span class="special">(</span> <span class="identifier">optional</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">x</span><span class="special">,</span> <span class="identifier">optional</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">y</span> <span class="special">)</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_operator_compare_less_optional_optional"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
|
||||
|
||||
<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span> <span class="keyword">inline</span> <span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">></span> <span class="special">(</span> <span class="identifier">optional</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">x</span><span class="special">,</span> <span class="identifier">optional</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">y</span> <span class="special">)</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_operator_compare_greater_optional_optional"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
|
||||
|
||||
<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span> <span class="keyword">inline</span> <span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special"><=</span> <span class="special">(</span> <span class="identifier">optional</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">x</span><span class="special">,</span> <span class="identifier">optional</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">y</span> <span class="special">)</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_operator_compare_less_or_equal_optional_optional"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
|
||||
|
||||
<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span> <span class="keyword">inline</span> <span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">>=</span> <span class="special">(</span> <span class="identifier">optional</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">x</span><span class="special">,</span> <span class="identifier">optional</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">y</span> <span class="special">)</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_operator_compare_greater_or_equal_optional_optional"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
|
||||
|
||||
<span class="comment">// [new in 1.34]
|
||||
</span><span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span> <span class="keyword">inline</span> <span class="identifier">optional</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span> <span class="identifier">make_optional</span> <span class="special">(</span> <span class="identifier">T</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">v</span> <span class="special">)</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_make_optional_value"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
|
||||
|
||||
<span class="comment">// [new in 1.34]
|
||||
</span><span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span> <span class="keyword">inline</span> <span class="identifier">optional</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span> <span class="identifier">make_optional</span> <span class="special">(</span> <span class="keyword">bool</span> <span class="identifier">condition</span><span class="special">,</span> <span class="identifier">T</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">v</span> <span class="special">)</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_make_optional_bool_value"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
|
||||
|
||||
<span class="comment">// [new in 1.34]
|
||||
</span><span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span> <span class="keyword">inline</span> <span class="identifier">T</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">get_optional_value_or</span> <span class="special">(</span> <span class="identifier">optional</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">opt</span><span class="special">,</span> <span class="identifier">T</span> <span class="keyword">const</span><span class="special">&</span> <span class="keyword">default</span> <span class="special">)</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_optional_get_value_or_value"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
|
||||
|
||||
<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span> <span class="keyword">inline</span> <span class="identifier">T</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">get</span> <span class="special">(</span> <span class="identifier">optional</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">opt</span> <span class="special">)</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_optional_get"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
|
||||
|
||||
<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span> <span class="keyword">inline</span> <span class="identifier">T</span><span class="special">&</span> <span class="identifier">get</span> <span class="special">(</span> <span class="identifier">optional</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span> <span class="special">&</span> <span class="identifier">opt</span> <span class="special">)</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_optional_get"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
|
||||
|
||||
<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span> <span class="keyword">inline</span> <span class="identifier">T</span> <span class="keyword">const</span><span class="special">*</span> <span class="identifier">get</span> <span class="special">(</span> <span class="identifier">optional</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span> <span class="keyword">const</span><span class="special">*</span> <span class="identifier">opt</span> <span class="special">)</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_optional_get"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
|
||||
|
||||
<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span> <span class="keyword">inline</span> <span class="identifier">T</span><span class="special">*</span> <span class="identifier">get</span> <span class="special">(</span> <span class="identifier">optional</span><span class="special"><</span><span class="identifier">T</span><span class="special">>*</span> <span class="identifier">opt</span> <span class="special">)</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_optional_get"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
|
||||
|
||||
<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span> <span class="keyword">inline</span> <span class="identifier">T</span> <span class="keyword">const</span><span class="special">*</span> <span class="identifier">get_pointer</span> <span class="special">(</span> <span class="identifier">optional</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">opt</span> <span class="special">)</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_optional_get_ptr"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
|
||||
|
||||
<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span> <span class="keyword">inline</span> <span class="identifier">T</span><span class="special">*</span> <span class="identifier">get_pointer</span> <span class="special">(</span> <span class="identifier">optional</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span> <span class="special">&</span> <span class="identifier">opt</span> <span class="special">)</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_optional_get_ptr"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
|
||||
|
||||
<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">></span> <span class="keyword">inline</span> <span class="keyword">void</span> <span class="identifier">swap</span><span class="special">(</span> <span class="identifier">optional</span><span class="special"><</span><span class="identifier">T</span><span class="special">>&</span> <span class="identifier">x</span><span class="special">,</span> <span class="identifier">optional</span><span class="special"><</span><span class="identifier">T</span><span class="special">>&</span> <span class="identifier">y</span> <span class="special">)</span> <span class="special">;</span> <a class="link" href="detailed_semantics.html#reference_swap_optional_optional"><span class="inlinemediaobject"><img src="../images/callouts/R.png" alt="R"></span></a>
|
||||
|
||||
<span class="special">}</span> <span class="comment">// namespace boost
|
||||
</span></pre>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"></td>
|
||||
<td align="right"><div class="copyright-footer">Copyright © 2003-2007 Fernando Luis Cacciola Carballal<p>
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
|
||||
</p>
|
||||
</div></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="development.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="detailed_semantics.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
53
doc/html/boost_optional/type_requirements.html
Normal file
53
doc/html/boost_optional/type_requirements.html
Normal file
@ -0,0 +1,53 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
|
||||
<title>Type requirements</title>
|
||||
<link rel="stylesheet" href="../boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.75.2">
|
||||
<link rel="home" href="../index.html" title="Chapter 1. Boost.Optional">
|
||||
<link rel="up" href="../index.html" title="Chapter 1. Boost.Optional">
|
||||
<link rel="prev" href="exception_safety_guarantees.html" title="Exception Safety Guarantees">
|
||||
<link rel="next" href="implementation_notes.html" title="Implementation Notes">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
<table cellpadding="2" width="100%"><tr>
|
||||
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td>
|
||||
<td align="center"><a href="../../../../../index.html">Home</a></td>
|
||||
<td align="center"><a href="../../../../../libs/libraries.htm">Libraries</a></td>
|
||||
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
|
||||
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
|
||||
<td align="center"><a href="../../../../../more/index.htm">More</a></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="exception_safety_guarantees.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="implementation_notes.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||
<a name="boost_optional.type_requirements"></a><a class="link" href="type_requirements.html" title="Type requirements">Type requirements</a>
|
||||
</h2></div></div></div>
|
||||
<p>
|
||||
In general, <code class="computeroutput"><span class="identifier">T</span></code> must be <a href="../../../../utility/CopyConstructible.html" target="_top">Copy Constructible</a> and
|
||||
have a no-throw destructor. The copy-constructible requirement is not needed
|
||||
if <span class="bold"><strong>InPlaceFactories</strong></span> are used.
|
||||
</p>
|
||||
<p>
|
||||
<code class="computeroutput"><span class="identifier">T</span></code> <span class="underline">is
|
||||
not</span> required to be <a href="http://www.sgi.com/tech/stl/DefaultConstructible.html" target="_top">Default
|
||||
Constructible</a>.
|
||||
</p>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"></td>
|
||||
<td align="right"><div class="copyright-footer">Copyright © 2003-2007 Fernando Luis Cacciola Carballal<p>
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
|
||||
</p>
|
||||
</div></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="exception_safety_guarantees.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="implementation_notes.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
582
doc/html/boostbook.css
Normal file
582
doc/html/boostbook.css
Normal file
@ -0,0 +1,582 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2004 Joel de Guzman
|
||||
http://spirit.sourceforge.net/
|
||||
|
||||
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)
|
||||
=============================================================================*/
|
||||
|
||||
/*=============================================================================
|
||||
Body defaults
|
||||
=============================================================================*/
|
||||
|
||||
body
|
||||
{
|
||||
margin: 1em;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
/*=============================================================================
|
||||
Paragraphs
|
||||
=============================================================================*/
|
||||
|
||||
p
|
||||
{
|
||||
text-align: left;
|
||||
font-size: 10pt;
|
||||
line-height: 1.15;
|
||||
}
|
||||
|
||||
/*=============================================================================
|
||||
Program listings
|
||||
=============================================================================*/
|
||||
|
||||
/* Code on paragraphs */
|
||||
p tt.computeroutput
|
||||
{
|
||||
font-size: 10pt;
|
||||
}
|
||||
|
||||
pre.synopsis
|
||||
{
|
||||
font-size: 10pt;
|
||||
margin: 1pc 4% 0pc 4%;
|
||||
padding: 0.5pc 0.5pc 0.5pc 0.5pc;
|
||||
}
|
||||
|
||||
.programlisting,
|
||||
.screen
|
||||
{
|
||||
font-size: 10pt;
|
||||
display: block;
|
||||
margin: 1pc 4% 0pc 4%;
|
||||
padding: 0.5pc 0.5pc 0.5pc 0.5pc;
|
||||
}
|
||||
|
||||
/* Program listings in tables don't get borders */
|
||||
td .programlisting,
|
||||
td .screen
|
||||
{
|
||||
margin: 0pc 0pc 0pc 0pc;
|
||||
padding: 0pc 0pc 0pc 0pc;
|
||||
}
|
||||
|
||||
/*=============================================================================
|
||||
Headings
|
||||
=============================================================================*/
|
||||
|
||||
h1, h2, h3, h4, h5, h6
|
||||
{
|
||||
text-align: left;
|
||||
margin: 1em 0em 0.5em 0em;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
h1 { font: 140% }
|
||||
h2 { font: bold 140% }
|
||||
h3 { font: bold 130% }
|
||||
h4 { font: bold 120% }
|
||||
h5 { font: italic 110% }
|
||||
h6 { font: italic 100% }
|
||||
|
||||
/* Top page titles */
|
||||
title,
|
||||
h1.title,
|
||||
h2.title
|
||||
h3.title,
|
||||
h4.title,
|
||||
h5.title,
|
||||
h6.title,
|
||||
.refentrytitle
|
||||
{
|
||||
font-weight: bold;
|
||||
margin-bottom: 1pc;
|
||||
}
|
||||
|
||||
h1.title { font-size: 140% }
|
||||
h2.title { font-size: 140% }
|
||||
h3.title { font-size: 130% }
|
||||
h4.title { font-size: 120% }
|
||||
h5.title { font-size: 110% }
|
||||
h6.title { font-size: 100% }
|
||||
|
||||
.section h1
|
||||
{
|
||||
margin: 0em 0em 0.5em 0em;
|
||||
font-size: 140%;
|
||||
}
|
||||
|
||||
.section h2 { font-size: 140% }
|
||||
.section h3 { font-size: 130% }
|
||||
.section h4 { font-size: 120% }
|
||||
.section h5 { font-size: 110% }
|
||||
.section h6 { font-size: 100% }
|
||||
|
||||
/* Code on titles */
|
||||
h1 tt.computeroutput { font-size: 140% }
|
||||
h2 tt.computeroutput { font-size: 140% }
|
||||
h3 tt.computeroutput { font-size: 130% }
|
||||
h4 tt.computeroutput { font-size: 120% }
|
||||
h5 tt.computeroutput { font-size: 110% }
|
||||
h6 tt.computeroutput { font-size: 100% }
|
||||
|
||||
/*=============================================================================
|
||||
Author
|
||||
=============================================================================*/
|
||||
|
||||
h3.author
|
||||
{
|
||||
font-size: 100%
|
||||
}
|
||||
|
||||
/*=============================================================================
|
||||
Lists
|
||||
=============================================================================*/
|
||||
|
||||
li
|
||||
{
|
||||
font-size: 10pt;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
/* Unordered lists */
|
||||
ul
|
||||
{
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
/* Ordered lists */
|
||||
ol
|
||||
{
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
/*=============================================================================
|
||||
Links
|
||||
=============================================================================*/
|
||||
|
||||
a
|
||||
{
|
||||
text-decoration: none; /* no underline */
|
||||
}
|
||||
|
||||
a:hover
|
||||
{
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/*=============================================================================
|
||||
Spirit style navigation
|
||||
=============================================================================*/
|
||||
|
||||
.spirit-nav
|
||||
{
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.spirit-nav a
|
||||
{
|
||||
color: white;
|
||||
padding-left: 0.5em;
|
||||
}
|
||||
|
||||
.spirit-nav img
|
||||
{
|
||||
border-width: 0px;
|
||||
}
|
||||
|
||||
/*=============================================================================
|
||||
Table of contents
|
||||
=============================================================================*/
|
||||
|
||||
.toc
|
||||
{
|
||||
margin: 1pc 4% 0pc 4%;
|
||||
padding: 0.1pc 1pc 0.1pc 1pc;
|
||||
font-size: 10pt;
|
||||
line-height: 1.15;
|
||||
}
|
||||
|
||||
.toc-main
|
||||
{
|
||||
text-align: center;
|
||||
margin: 3pc 16% 3pc 16%;
|
||||
padding: 3pc 1pc 3pc 1pc;
|
||||
line-height: 0.1;
|
||||
}
|
||||
|
||||
.boost-toc
|
||||
{
|
||||
float: right;
|
||||
padding: 0.5pc;
|
||||
}
|
||||
|
||||
/*=============================================================================
|
||||
Tables
|
||||
=============================================================================*/
|
||||
|
||||
.table-title,
|
||||
div.table p.title
|
||||
{
|
||||
margin-left: 4%;
|
||||
padding-right: 0.5em;
|
||||
padding-left: 0.5em;
|
||||
}
|
||||
|
||||
.informaltable table,
|
||||
.table table
|
||||
{
|
||||
width: 92%;
|
||||
margin-left: 4%;
|
||||
margin-right: 4%;
|
||||
}
|
||||
|
||||
div.informaltable table,
|
||||
div.table table
|
||||
{
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
/* Table Cells */
|
||||
div.informaltable table tr td,
|
||||
div.table table tr td
|
||||
{
|
||||
padding: 0.5em;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
div.informaltable table tr th,
|
||||
div.table table tr th
|
||||
{
|
||||
padding: 0.5em 0.5em 0.5em 0.5em;
|
||||
border: 1pt solid white;
|
||||
font-size: 120%;
|
||||
}
|
||||
|
||||
/*=============================================================================
|
||||
Blurbs
|
||||
=============================================================================*/
|
||||
|
||||
div.note,
|
||||
div.tip,
|
||||
div.important,
|
||||
div.caution,
|
||||
div.warning,
|
||||
div.sidebar
|
||||
{
|
||||
font-size: 10pt;
|
||||
line-height: 1.2;
|
||||
display: block;
|
||||
margin: 1pc 4% 0pc 4%;
|
||||
padding: 0.5pc 0.5pc 0.5pc 0.5pc;
|
||||
}
|
||||
|
||||
div.sidebar img
|
||||
{
|
||||
padding: 1pt;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*=============================================================================
|
||||
Callouts
|
||||
=============================================================================*/
|
||||
.line_callout_bug img
|
||||
{
|
||||
float: left;
|
||||
position:relative;
|
||||
left: 4px;
|
||||
top: -12px;
|
||||
clear: left;
|
||||
margin-left:-22px;
|
||||
}
|
||||
|
||||
.callout_bug img
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*=============================================================================
|
||||
Variable Lists
|
||||
=============================================================================*/
|
||||
|
||||
/* Make the terms in definition lists bold */
|
||||
div.variablelist dl dt,
|
||||
span.term
|
||||
{
|
||||
font-weight: bold;
|
||||
font-size: 10pt;
|
||||
}
|
||||
|
||||
div.variablelist table tbody tr td
|
||||
{
|
||||
text-align: left;
|
||||
vertical-align: top;
|
||||
padding: 0em 2em 0em 0em;
|
||||
font-size: 10pt;
|
||||
margin: 0em 0em 0.5em 0em;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
/* Make the terms in definition lists bold */
|
||||
div.variablelist dl dt
|
||||
{
|
||||
margin-bottom: 0.2em;
|
||||
}
|
||||
|
||||
div.variablelist dl dd
|
||||
{
|
||||
margin: 0em 0em 0.5em 2em;
|
||||
font-size: 10pt;
|
||||
}
|
||||
|
||||
div.variablelist table tbody tr td p
|
||||
div.variablelist dl dd p
|
||||
{
|
||||
margin: 0em 0em 0.5em 0em;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
/*=============================================================================
|
||||
Misc
|
||||
=============================================================================*/
|
||||
|
||||
/* Title of books and articles in bibliographies */
|
||||
span.title
|
||||
{
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
span.underline
|
||||
{
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
span.strikethrough
|
||||
{
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
/* Copyright, Legal Notice */
|
||||
div div.legalnotice p
|
||||
{
|
||||
text-align: left
|
||||
}
|
||||
|
||||
/*=============================================================================
|
||||
Colors
|
||||
=============================================================================*/
|
||||
|
||||
@media screen
|
||||
{
|
||||
/* Links */
|
||||
a
|
||||
{
|
||||
color: #0C7445;
|
||||
}
|
||||
|
||||
a:visited
|
||||
{
|
||||
color: #663974;
|
||||
}
|
||||
|
||||
h1 a, h2 a, h3 a, h4 a, h5 a, h6 a,
|
||||
h1 a:hover, h2 a:hover, h3 a:hover, h4 a:hover, h5 a:hover, h6 a:hover,
|
||||
h1 a:visited, h2 a:visited, h3 a:visited, h4 a:visited, h5 a:visited, h6 a:visited
|
||||
{
|
||||
text-decoration: none; /* no underline */
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
/* Syntax Highlighting */
|
||||
.keyword { color: #0000AA; }
|
||||
.identifier { color: #000000; }
|
||||
.special { color: #707070; }
|
||||
.preprocessor { color: #402080; }
|
||||
.char { color: teal; }
|
||||
.comment { color: #800000; }
|
||||
.string { color: teal; }
|
||||
.number { color: teal; }
|
||||
.white_bkd { background-color: #E8FBE9; }
|
||||
.dk_grey_bkd { background-color: #A0DAAC; }
|
||||
|
||||
/* Copyright, Legal Notice */
|
||||
.copyright
|
||||
{
|
||||
color: #666666;
|
||||
font-size: small;
|
||||
}
|
||||
|
||||
div div.legalnotice p
|
||||
{
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
/* Program listing */
|
||||
pre.synopsis
|
||||
{
|
||||
border: 1px solid #DCDCDC;
|
||||
border-bottom: 3px solid #9D9D9D;
|
||||
border-right: 3px solid #9D9D9D;
|
||||
background-color: #FAFFFB;
|
||||
}
|
||||
|
||||
.programlisting,
|
||||
.screen
|
||||
{
|
||||
border: 1px solid #DCDCDC;
|
||||
border-bottom: 3px solid #9D9D9D;
|
||||
border-right: 3px solid #9D9D9D;
|
||||
background-color: #FAFFFB;
|
||||
}
|
||||
|
||||
td .programlisting,
|
||||
td .screen
|
||||
{
|
||||
border: 0px solid #DCDCDC;
|
||||
}
|
||||
|
||||
/* Blurbs */
|
||||
div.note,
|
||||
div.tip,
|
||||
div.important,
|
||||
div.caution,
|
||||
div.warning,
|
||||
div.sidebar
|
||||
{
|
||||
border: 1px solid #DCDCDC;
|
||||
border-bottom: 3px solid #9D9D9D;
|
||||
border-right: 3px solid #9D9D9D;
|
||||
background-color: #FAFFFB;
|
||||
}
|
||||
|
||||
/* Table of contents */
|
||||
.toc
|
||||
{
|
||||
border: 1px solid #DCDCDC;
|
||||
border-bottom: 3px solid #9D9D9D;
|
||||
border-right: 3px solid #9D9D9D;
|
||||
background-color: #FAFFFB;
|
||||
}
|
||||
|
||||
/* Table of contents */
|
||||
.toc-main
|
||||
{
|
||||
border: 1px solid #DCDCDC;
|
||||
border-bottom: 3px solid #9D9D9D;
|
||||
border-right: 3px solid #9D9D9D;
|
||||
background-color: #FAFFFB;
|
||||
}
|
||||
|
||||
|
||||
/* Tables */
|
||||
div.informaltable table tr td,
|
||||
div.table table tr td
|
||||
{
|
||||
border: 1px solid #DCDCDC;
|
||||
background-color: #FAFFFB;
|
||||
}
|
||||
|
||||
div.informaltable table tr th,
|
||||
div.table table tr th
|
||||
{
|
||||
background-color: #E3F9E4;
|
||||
border: 1px solid #DCDCDC;
|
||||
}
|
||||
|
||||
/* Misc */
|
||||
span.highlight
|
||||
{
|
||||
color: #00A000;
|
||||
}
|
||||
}
|
||||
|
||||
@media print
|
||||
{
|
||||
/* Links */
|
||||
a
|
||||
{
|
||||
color: black;
|
||||
}
|
||||
|
||||
a:visited
|
||||
{
|
||||
color: black;
|
||||
}
|
||||
|
||||
.spirit-nav
|
||||
{
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Program listing */
|
||||
pre.synopsis
|
||||
{
|
||||
border: 1px solid gray;
|
||||
background-color: #FAFFFB;
|
||||
}
|
||||
|
||||
.programlisting,
|
||||
.screen
|
||||
{
|
||||
border: 1px solid gray;
|
||||
background-color: #FAFFFB;
|
||||
}
|
||||
|
||||
td .programlisting,
|
||||
td .screen
|
||||
{
|
||||
border: 0px solid #DCDCDC;
|
||||
}
|
||||
|
||||
/* Table of contents */
|
||||
.toc
|
||||
{
|
||||
border: 1px solid #DCDCDC;
|
||||
border-bottom: 3px solid #9D9D9D;
|
||||
border-right: 3px solid #9D9D9D;
|
||||
background-color: #FAFFFB;
|
||||
}
|
||||
|
||||
/* Table of contents */
|
||||
.toc-main
|
||||
{
|
||||
border: 1px solid #DCDCDC;
|
||||
border-bottom: 3px solid #9D9D9D;
|
||||
border-right: 3px solid #9D9D9D;
|
||||
background-color: #FAFFFB;
|
||||
}
|
||||
|
||||
.informaltable table,
|
||||
.table table
|
||||
{
|
||||
border: 1px solid #DCDCDC;
|
||||
border-bottom: 3px solid #9D9D9D;
|
||||
border-right: 3px solid #9D9D9D;
|
||||
border-collapse: collapse;
|
||||
background-color: #FAFFFB;
|
||||
}
|
||||
|
||||
/* Tables */
|
||||
div.informaltable table tr td,
|
||||
div.table table tr td
|
||||
{
|
||||
border: 1px solid #DCDCDC;
|
||||
background-color: #FAFFFB;
|
||||
}
|
||||
|
||||
div.informaltable table tr th,
|
||||
div.table table tr th
|
||||
{
|
||||
border: 1px solid #DCDCDC;
|
||||
background-color: #FAFFFB;
|
||||
}
|
||||
|
||||
/* Misc */
|
||||
span.highlight
|
||||
{
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
BIN
doc/html/images/callouts/R.png
Normal file
BIN
doc/html/images/callouts/R.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 293 B |
BIN
doc/html/images/space.png
Normal file
BIN
doc/html/images/space.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 81 B |
172
doc/html/index.html
Normal file
172
doc/html/index.html
Normal file
@ -0,0 +1,172 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
|
||||
<title>Chapter 1. Boost.Optional</title>
|
||||
<link rel="stylesheet" href="boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.75.2">
|
||||
<link rel="home" href="index.html" title="Chapter 1. Boost.Optional">
|
||||
<link rel="next" href="boost_optional/development.html" title="Development">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
<table cellpadding="2" width="100%"><tr>
|
||||
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../boost.png"></td>
|
||||
<td align="center"><a href="../../../../index.html">Home</a></td>
|
||||
<td align="center"><a href="../../../../libs/libraries.htm">Libraries</a></td>
|
||||
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
|
||||
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
|
||||
<td align="center"><a href="../../../../more/index.htm">More</a></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav"><a accesskey="n" href="boost_optional/development.html"><img src="../../../../doc/src/images/next.png" alt="Next"></a></div>
|
||||
<div class="chapter">
|
||||
<div class="titlepage"><div>
|
||||
<div><h2 class="title">
|
||||
<a name="optional"></a>Chapter 1. Boost.Optional</h2></div>
|
||||
<div><div class="author"><h3 class="author">
|
||||
<span class="firstname">Fernando Luis</span> <span class="surname">Cacciola Carballal</span>
|
||||
</h3></div></div>
|
||||
<div><p class="copyright">Copyright © 2003-2007 Fernando Luis Cacciola Carballal</p></div>
|
||||
<div><div class="legalnotice">
|
||||
<a name="id2833979"></a><p>
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
|
||||
</p>
|
||||
</div></div>
|
||||
</div></div>
|
||||
<div class="toc">
|
||||
<p><b>Table of Contents</b></p>
|
||||
<dl>
|
||||
<dt><span class="section"><a href="index.html#optional.motivation">Motivation</a></span></dt>
|
||||
<dt><span class="section"><a href="boost_optional/development.html">Development</a></span></dt>
|
||||
<dd><dl>
|
||||
<dt><span class="section"><a href="boost_optional/development.html#boost_optional.development.the_models">The models</a></span></dt>
|
||||
<dt><span class="section"><a href="boost_optional/development.html#boost_optional.development.the_semantics">The semantics</a></span></dt>
|
||||
<dt><span class="section"><a href="boost_optional/development.html#boost_optional.development.the_interface">The Interface</a></span></dt>
|
||||
</dl></dd>
|
||||
<dt><span class="section"><a href="boost_optional/synopsis.html">Synopsis</a></span></dt>
|
||||
<dt><span class="section"><a href="boost_optional/detailed_semantics.html">Detailed Semantics</a></span></dt>
|
||||
<dt><span class="section"><a href="boost_optional/examples.html">Examples</a></span></dt>
|
||||
<dd><dl>
|
||||
<dt><span class="section"><a href="boost_optional/examples.html#boost_optional.examples.optional_return_values">Optional
|
||||
return values</a></span></dt>
|
||||
<dt><span class="section"><a href="boost_optional/examples.html#boost_optional.examples.optional_local_variables">Optional
|
||||
local variables</a></span></dt>
|
||||
<dt><span class="section"><a href="boost_optional/examples.html#boost_optional.examples.optional_data_members">Optional
|
||||
data members</a></span></dt>
|
||||
<dt><span class="section"><a href="boost_optional/examples.html#boost_optional.examples.bypassing_expensive_unnecessary_default_construction">Bypassing
|
||||
expensive unnecessary default construction</a></span></dt>
|
||||
</dl></dd>
|
||||
<dt><span class="section"><a href="boost_optional/optional_references.html">Optional references</a></span></dt>
|
||||
<dt><span class="section"><a href="boost_optional/rebinding_semantics_for_assignment_of_optional_references.html">Rebinding
|
||||
semantics for assignment of optional references</a></span></dt>
|
||||
<dt><span class="section"><a href="boost_optional/in_place_factories.html">In-Place Factories</a></span></dt>
|
||||
<dt><span class="section"><a href="boost_optional/a_note_about_optional_bool_.html">A note about
|
||||
optional<bool></a></span></dt>
|
||||
<dt><span class="section"><a href="boost_optional/exception_safety_guarantees.html">Exception Safety
|
||||
Guarantees</a></span></dt>
|
||||
<dt><span class="section"><a href="boost_optional/type_requirements.html">Type requirements</a></span></dt>
|
||||
<dt><span class="section"><a href="boost_optional/implementation_notes.html">Implementation Notes</a></span></dt>
|
||||
<dt><span class="section"><a href="boost_optional/dependencies_and_portability.html">Dependencies
|
||||
and Portability</a></span></dt>
|
||||
<dt><span class="section"><a href="boost_optional/acknowledgments.html">Acknowledgments</a></span></dt>
|
||||
</dl>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||
<a name="optional.motivation"></a><a class="link" href="index.html#optional.motivation" title="Motivation">Motivation</a>
|
||||
</h2></div></div></div>
|
||||
<p>
|
||||
Consider these functions which should return a value but which might not have
|
||||
a value to return:
|
||||
</p>
|
||||
<div class="itemizedlist"><ul class="itemizedlist" type="disc">
|
||||
<li class="listitem">
|
||||
(A) <code class="computeroutput"><span class="keyword">double</span> <span class="identifier">sqrt</span><span class="special">(</span><span class="keyword">double</span> <span class="identifier">n</span> <span class="special">);</span></code>
|
||||
</li>
|
||||
<li class="listitem">
|
||||
(B) <code class="computeroutput"><span class="keyword">char</span> <span class="identifier">get_async_input</span><span class="special">();</span></code>
|
||||
</li>
|
||||
<li class="listitem">
|
||||
(C) <code class="computeroutput"><span class="identifier">point</span> <span class="identifier">polygon</span><span class="special">::</span><span class="identifier">get_any_point_effectively_inside</span><span class="special">();</span></code>
|
||||
</li>
|
||||
</ul></div>
|
||||
<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 assert 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 <span class="emphasis"><em>null-area</em></span> 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 <code class="computeroutput"><span class="identifier">EOF</span></code>, <code class="computeroutput"><span class="identifier">string</span><span class="special">::</span><span class="identifier">npos</span></code>, points
|
||||
at infinity, etc...
|
||||
</p>
|
||||
<p>
|
||||
When those values exist, i.e. the return type can hold all meaningful values
|
||||
<span class="emphasis"><em>plus</em></span> the <span class="emphasis"><em>signal</em></span> 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 <code class="computeroutput"><span class="keyword">int</span></code> in place
|
||||
of <code class="computeroutput"><span class="keyword">char</span></code>; or a compound type, such
|
||||
as <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">pair</span><span class="special"><</span><span class="identifier">point</span><span class="special">,</span><span class="keyword">bool</span><span class="special">></span></code>.
|
||||
</p>
|
||||
<p>
|
||||
Returning a <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">pair</span><span class="special"><</span><span class="identifier">T</span><span class="special">,</span><span class="keyword">bool</span><span class="special">></span></code>, 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 class="programlisting"><span class="identifier">std</span><span class="special">::</span><span class="identifier">pair</span><span class="special"><</span><span class="keyword">char</span><span class="special">,</span><span class="keyword">bool</span><span class="special">></span> <span class="identifier">get_async_input</span><span class="special">();</span>
|
||||
<span class="identifier">std</span><span class="special">::</span><span class="identifier">pair</span><span class="special"><</span><span class="identifier">point</span><span class="special">,</span><span class="keyword">bool</span><span class="special">></span> <span class="identifier">polygon</span><span class="special">::</span><span class="identifier">get_any_point_effectively_inside</span><span class="special">();</span>
|
||||
</pre>
|
||||
<p>
|
||||
These functions use a consistent interface for dealing with possibly nonexistent
|
||||
results:
|
||||
</p>
|
||||
<pre class="programlisting"><span class="identifier">std</span><span class="special">::</span><span class="identifier">pair</span><span class="special"><</span><span class="identifier">point</span><span class="special">,</span><span class="keyword">bool</span><span class="special">></span> <span class="identifier">p</span> <span class="special">=</span> <span class="identifier">poly</span><span class="special">.</span><span class="identifier">get_any_point_effectively_inside</span><span class="special">();</span>
|
||||
<span class="keyword">if</span> <span class="special">(</span> <span class="identifier">p</span><span class="special">.</span><span class="identifier">second</span> <span class="special">)</span>
|
||||
<span class="identifier">flood_fill</span><span class="special">(</span><span class="identifier">p</span><span class="special">.</span><span class="identifier">first</span><span class="special">);</span>
|
||||
</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>
|
||||
</div>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"><p><small>Last revised: April 07, 2011 at 21:02:08 GMT</small></p></td>
|
||||
<td align="right"><div class="copyright-footer"></div></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav"><a accesskey="n" href="boost_optional/development.html"><img src="../../../../doc/src/images/next.png" alt="Next"></a></div>
|
||||
</body>
|
||||
</html>
|
26
doc/implementation_notes.qbk
Normal file
26
doc/implementation_notes.qbk
Normal file
@ -0,0 +1,26 @@
|
||||
[/
|
||||
Boost.Optional
|
||||
|
||||
Copyright (c) 2003-2007 Fernando Luis Cacciola Carballal
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt)
|
||||
]
|
||||
|
||||
|
||||
|
||||
[section Implementation Notes]
|
||||
|
||||
`optional<T>` is currently implemented using a custom aligned storage facility
|
||||
built from `alignment_of` and `type_with_alignment` (both from Type Traits). It
|
||||
uses a separate boolean flag to indicate the initialization state.
|
||||
Placement new with `T`'s copy constructor and `T`'s destructor are explicitly used
|
||||
to initialize,copy and destroy optional values.
|
||||
As a result, `T`'s default constructor is effectively by-passed, but the exception
|
||||
guarantees are basic.
|
||||
It is planned to replace the current implementation with another with stronger
|
||||
exception safety, such as a future `boost::variant`.
|
||||
|
||||
[endsect]
|
||||
|
@ -1,983 +0,0 @@
|
||||
<!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">
|
||||
<LINK REL="stylesheet" TYPE="text/css" HREF="../../../boost.css">
|
||||
<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>
|
||||
<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>
|
||||
|
||||
<h3>The model</h3>
|
||||
<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>
|
||||
When a declaration includes a non-empty initializer (an initial value is given), it is said that
|
||||
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
|
||||
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. And 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>
|
||||
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
|
||||
the special value to the set of possible values of a given type.
|
||||
On modern languages, this can be modeled with a <b>discriminated
|
||||
union</b> of T and something else such as a trivial POD or enum.
|
||||
Discriminated unions are often called <i>variants</i>.
|
||||
A variant has a <i>current type</i>, which in our case is either T or something else. In C++,
|
||||
such a variant would be typically implemented as a template class of the form: <code>variant<T,nil_t></code>
|
||||
</P>
|
||||
<P>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.</p>
|
||||
<p>A discriminated union, which can be seen as a <b>container</b> which has an object of either
|
||||
type T or something else, has <i>exactly</i> the semantics required for a wrapper of optional values:</p>
|
||||
<li><b>deep-copy</b> semantics: copies of the variant implies copies of the contained value.</li>
|
||||
<li><b>deep-relational</b> semantics: comparisons between variants matches both current types and values</li>
|
||||
<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>
|
||||
<P>Because of the way a discriminated union is used for this purpose, it only matters
|
||||
whether its current type is T or not. We can put a layer on top of the variant hidding the other type
|
||||
transforming a container of fixed size 1 into a variable size container which either has
|
||||
a T or has nothing. Thus, the variant<T,nil_t> can be seen as if it were a variable-size
|
||||
fixed-capacity stack-based container with the following optional-oriented interface:</P>
|
||||
|
||||
|
||||
<pre>// Uninitialized (internally, current type is nil_t)
|
||||
optional<T>::optional();
|
||||
|
||||
// Initialized with 'v' (internally, current type is T)
|
||||
optional<T>::optional( T const& v ) ;
|
||||
|
||||
// Back to uninitialized (current type is set to nil_t)
|
||||
void optional<T>::reset();
|
||||
|
||||
// Assigns 'v' whether previously initialized or not (current type is set to T)
|
||||
void optional<T>::reset( T const& v ) ;
|
||||
|
||||
// Returns 'true' if the optional is initialized, 'false' otherwise.
|
||||
bool optional<T>::initialized() ;
|
||||
|
||||
// If the optional is initialized (current type is T), returns a reference to its value.
|
||||
// Otherwise (current type is nil_t), the result is undefined.
|
||||
T const& optional<T>::ref() const ;
|
||||
T& optional<T>::ref() ;
|
||||
|
||||
// If both are initialized, calls swap(T&,T&);
|
||||
// If only one is initialized, calls reset(T const&) and reset().
|
||||
// If both are uninitalized, do nothing.
|
||||
void swap ( optional<T>& lhs, optional<T>& rhs ) ;
|
||||
|
||||
// If both are initialized, compare values.
|
||||
// If only one is initialized, they are not equal.
|
||||
// If both are uninitalized, they are equal.
|
||||
bool operator == ( optional<T> const& lhs, optional<T> const& rhs ) ;
|
||||
bool operator != ( optional<T> const& lhs, optional<T> const& rhs ) ;
|
||||
</pre>
|
||||
|
||||
<h3>Pointers and optional objects</h3>
|
||||
<P>In C++, unlike many other languages, objects can be referenced <i>indirectly</i>
|
||||
by means of a <b>pointer</b> (or a reference). Pointers have several nice features,
|
||||
two of which are relevant to this development.</p>
|
||||
<p>One is that a pointer has its own <i>pointer value</i>, which in effect
|
||||
references the object being pointed to: the <b>pointee</b>. Consequently,
|
||||
copies of pointers do not involve copies of pointees. This effect results in <i>aliasing</i>:
|
||||
different pointers can refer to the same object.
|
||||
The particular semantic that a copy of a pointer does not involve
|
||||
a copy of the pointee is called <b>shallow-copy</b>, which is oppossed to <b>deep-copy</b> were
|
||||
a copy of a wrapper involves a copy of the wrapped object (as with optional<>)<br>
|
||||
Since this is the semantic followed by pointers (and references), shallow-copy
|
||||
(and therefore aliasing) is implied in <b>pointer semantics</b>.</p>
|
||||
<p>The other relevant feature of a pointer is that a pointer can have a <b>null
|
||||
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
|
||||
values convey the notion of inexistent objects.</P>
|
||||
<P>This meaning of the null pointer value allowed pointers to became a defacto standard
|
||||
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
|
||||
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>,
|
||||
implicitly convey the notion of optionality, and this information is tied to
|
||||
the <i>syntax</i> of the expressions. That is, the presence of operators * and -> tell by
|
||||
themselves -without any additional context-, that the expression will be undefined unless
|
||||
the implied pointee actually exist.<br>
|
||||
Furthermore, the existence of the pointee can be tested by a comparison against
|
||||
the null pointer value or via a conversion to bool, which allows expressions of
|
||||
the form: if ( p != 0 ), or if ( p ) to be used to test for the existence of the pointee.</P>
|
||||
<p>Such a defacto idiom for referring to optional objects can be formalized in the form of a
|
||||
concept: the <a href="../../utility/OptionalPointee.html">OptionalPointee</a> concept.<br>
|
||||
This concept captures the syntactic usage of operatos *, -> and conversion to bool to convey
|
||||
the notion of optionality.</p>
|
||||
<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
|
||||
values. Pointers do not have this semantics, so are unappropriate for the initialization and
|
||||
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
|
||||
concept incarnated by pointers. <br>
|
||||
Therefore, the final solution which is presented in this library is to shape the
|
||||
previously discussed optional -which is a value-based container- as a model
|
||||
of the OptionalPointee concept.
|
||||
</p>
|
||||
<h3>Optional<T> as a model of OptionalPointee</h3>
|
||||
<P>The optional<> template class presented with this library is a variation of the
|
||||
sketch shown before (as a layer on top of a variant). It features <b>deep-copy</b> and
|
||||
<b>deep relational operators</b>, but also models the OptionalPointee concept.
|
||||
Instead of the member function 'initialized()' it has a safe conversion to bool,
|
||||
and instead of the 'ref()' member function, it has operators*() and ->().<br>
|
||||
However, it is particularly important that optional<> objects are not mistaken by pointers,
|
||||
they are not. <u><b>optional<> does not model a pointer</b></u>.
|
||||
For instance, optional<> has not shallow-copy so does not alias: two different optionals
|
||||
never refer to the <i>same</i> value (but my have <i>equivalent</i> values).<br>
|
||||
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
|
||||
operators directly, and must use the template function
|
||||
<a href="../../utility/OptionalPointee.html#equal">equal_pointees()</a> instead.
|
||||
<HR>
|
||||
|
||||
<H2><A NAME="synopsis">Synopsis</A></H2>
|
||||
|
||||
<PRE>namespace boost {
|
||||
|
||||
template<class T>
|
||||
class optional
|
||||
{
|
||||
public :
|
||||
|
||||
optional () ;
|
||||
|
||||
explicit optional ( T const& v ) ;
|
||||
|
||||
optional ( optional const& rhs ) ;
|
||||
|
||||
template<class U> explicit optional ( optional<U> const& rhs ) ;
|
||||
|
||||
optional& operator = ( optional const& rhs ) ;
|
||||
|
||||
template<class U> optional& operator = ( optional<U> const& rhs ) ;
|
||||
|
||||
T const* get() const ;
|
||||
T* get() ;
|
||||
|
||||
T const* operator ->() const ;
|
||||
T* operator ->() ;
|
||||
|
||||
T const& operator *() const ;
|
||||
T& operator *() ;
|
||||
|
||||
void reset();
|
||||
|
||||
void reset ( T const& ) ;
|
||||
|
||||
operator <i>unspecified-bool-type</i>() const ;
|
||||
|
||||
bool operator!() const ;
|
||||
|
||||
} ;
|
||||
|
||||
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* get_pointer ( optional<T> const& opt ) ;
|
||||
|
||||
template<class T> inline void swap( optional<T>& x, optional<T>& y ) ;
|
||||
|
||||
} // namespace boost
|
||||
</PRE>
|
||||
|
||||
<HR>
|
||||
|
||||
<h2><A NAME="semantics">Semantics</a></h2>
|
||||
|
||||
<p><i>Note: 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>
|
||||
|
||||
<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>
|
||||
|
||||
<pre>explicit optional<T>::optional( T const& v )</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 a <i>copy</i> of 'v'.</p>
|
||||
<p><b>Throws:</b> Whatever T::T( T const& ) throws.</p>
|
||||
<p><b>Notes:</b> T::T( T const& ) is called.</p>
|
||||
<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>
|
||||
T v;
|
||||
optional<T> opt(v);
|
||||
assert ( *opt == v ) ;
|
||||
</pre>
|
||||
</blockquote>
|
||||
</blockquote>
|
||||
|
||||
<HR>
|
||||
|
||||
<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 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> T::T( T const& ) is called if <b>rhs</b> is initialized.</p>
|
||||
<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>
|
||||
|
||||
<pre>explicit template<U> optional<T>::optional( optional<U> 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 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>
|
||||
|
||||
<pre>optional& optional<T>::operator= ( optional const& rhs ) ;</pre>
|
||||
<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>
|
||||
<pre>
|
||||
T v;
|
||||
optional<T> opt(v);
|
||||
optional<T> uninit ;
|
||||
|
||||
opt = uninit ;
|
||||
assert ( !opt ) ;
|
||||
// previous value (copy of 'v') destroyed from within 'opt'.
|
||||
|
||||
</pre>
|
||||
</blockquote>
|
||||
</blockquote>
|
||||
|
||||
<HR>
|
||||
|
||||
<pre>template<U> optional& optional<T>::operator= ( optional<U> const& rhs ) ;</pre>
|
||||
<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>
|
||||
<pre>
|
||||
T v;
|
||||
optional<T> opt0(v);
|
||||
optional<U> opt1;
|
||||
|
||||
opt1 = opt0 ;
|
||||
assert ( *opt1 == static_cast<U>(v) ) ;
|
||||
</pre>
|
||||
</blockquote>
|
||||
</blockquote>
|
||||
|
||||
<HR>
|
||||
<pre>void optional<T>::reset( T const& v ) ;</pre>
|
||||
<blockquote>
|
||||
<p><b>Effect:</b> Resets the current value.</p>
|
||||
<p><b>Postconditions: </b><b>*this</b> is <u>initialized</u> and its value is
|
||||
a <i>copy</i> of 'v'.
|
||||
</p>
|
||||
<p><b>Throws:</b> Whatever T::T( T const& ) 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.
|
||||
</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>optional<T> opt ( some_T ) ;
|
||||
assert( *opt == some_T );
|
||||
opt.reset ( some_other_T ) ;
|
||||
assert( *opt == some_other_T );
|
||||
</pre>
|
||||
</blockquote>
|
||||
</blockquote>
|
||||
|
||||
<HR>
|
||||
<pre>void optional<T>::reset() ;</pre>
|
||||
<blockquote>
|
||||
<p><b>Effect:</b> Destroys the current value.</p>
|
||||
<p><b>Postconditions: *this</b> is uninitialized.</p>
|
||||
<p><b>Throws:</b> Nothing.</p>
|
||||
<p><b>Notes:</b> T::~T() is called.</p>
|
||||
<p><b>Example:</b></p>
|
||||
<blockquote>
|
||||
<pre>optional<T> opt ( some_T ) ;
|
||||
assert( *opt == some_T );
|
||||
opt.reset();
|
||||
assert( !opt );
|
||||
</pre>
|
||||
</blockquote>
|
||||
</blockquote>
|
||||
|
||||
<HR>
|
||||
|
||||
<pre>
|
||||
T const* optional<T>::get() const ;
|
||||
T* optional<T>::get() ;
|
||||
|
||||
inline T const* get_pointer ( optional<T> const& ) ;
|
||||
inline T* get_pointer ( optional<T>&) ;
|
||||
</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>
|
||||
<pre>
|
||||
T v;
|
||||
optional<T> opt(v);
|
||||
optional<T> const copt(v);
|
||||
T* p = opt.get() ;
|
||||
T const* cp = copt.get();
|
||||
assert ( p == get_pointer(opt) );
|
||||
assert ( cp == get_pointer(copt) ) ;
|
||||
</pre>
|
||||
</blockquote>
|
||||
</blockquote>
|
||||
|
||||
|
||||
<HR>
|
||||
|
||||
|
||||
<pre>
|
||||
T const* optional<T>::operator ->() const ;
|
||||
T* optional<T>::operator ->() ;
|
||||
</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>
|
||||
<pre>
|
||||
struct X { int mdata ; } ;
|
||||
X x ;
|
||||
optional<X> opt (x);
|
||||
opt->mdata = 2 ;
|
||||
</pre>
|
||||
</blockquote>
|
||||
</blockquote>
|
||||
|
||||
|
||||
<HR>
|
||||
|
||||
|
||||
<pre>T const& optional<T>::operator*() const ;
|
||||
T& optional<T>::operator*();</pre>
|
||||
<blockquote>
|
||||
<p><b>Requirements: *this</b> is initialized</p>
|
||||
<p><b>Returns:</b> A reference 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>
|
||||
<pre>T v ;
|
||||
optional<T> opt ( v );
|
||||
T const& u = *opt;
|
||||
assert ( u == v ) ;
|
||||
T w ;
|
||||
*opt = w ;
|
||||
assert ( *opt == w ) ;
|
||||
</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>
|
||||
|
||||
<HR>
|
||||
|
||||
|
||||
<pre>bool operator == ( optional<T> const& x, optional<T> const& 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>
|
||||
<pre>
|
||||
T x(12);
|
||||
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>
|
||||
|
||||
<HR>
|
||||
<pre>bool operator != ( optional<T> const& x, optional<T> const& y );
|
||||
</pre>
|
||||
<blockquote>
|
||||
<p><b>Returns:</b> !( x == y );</p>
|
||||
<p><b>Throws:</b> Nothing.</p>
|
||||
</blockquote>
|
||||
|
||||
<HR>
|
||||
|
||||
<pre>void swap ( optional<T>& x, optional<T>& 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>
|
||||
<pre>
|
||||
T x(12);
|
||||
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()
|
||||
{
|
||||
if ( !queue.empty() )
|
||||
return optional<char>(queue.top());
|
||||
else return optional<char>(); // uninitialized
|
||||
}
|
||||
|
||||
void recieve_async_message()
|
||||
{
|
||||
optional<char> rcv ;
|
||||
// The safe boolean conversion from 'rcv' is used here.
|
||||
while ( (rcv = get_async_input()) && !timeout() )
|
||||
output(*rcv);
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h3>Optional local variables</h3>
|
||||
<pre>optional<string> name ;
|
||||
if ( database.open() )
|
||||
{
|
||||
name.reset ( database.lookup(employer_name) ) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( can_ask_user )
|
||||
name.reset ( user.ask(employer_name) ) ;
|
||||
}
|
||||
|
||||
if ( name )
|
||||
print(*name);
|
||||
else print("employer's name not found!");
|
||||
</pre>
|
||||
|
||||
<h3>Optional data members</h3>
|
||||
<pre>class figure
|
||||
{
|
||||
public:
|
||||
|
||||
figure()
|
||||
{
|
||||
// data member 'm_clipping_rect' is uninitialized at this point.
|
||||
}
|
||||
|
||||
void clip_in_rect ( rect const& rect )
|
||||
{
|
||||
....
|
||||
m_clipping_rect.reset ( rect ) ; // initialized here.
|
||||
}
|
||||
|
||||
void draw ( canvas& cvs )
|
||||
{
|
||||
if ( m_clipping_rect )
|
||||
do_clipping(*m_clipping_rect);
|
||||
|
||||
cvs.drawXXX(..);
|
||||
}
|
||||
|
||||
// this can return NULL.
|
||||
rect const* get_clipping_rect() { return get_pointer(m_clipping_rect); }
|
||||
|
||||
private :
|
||||
|
||||
optional<rect> m_clipping_rect ;
|
||||
|
||||
};
|
||||
</pre>
|
||||
<h3>Bypassing expensive unnecesary default construction</h3>
|
||||
<pre>class ExpensiveCtor { ... } ;
|
||||
class Fred
|
||||
{
|
||||
Fred() : mLargeVector(10000) {}
|
||||
|
||||
std::vector< optional<ExpensiveCtor> > mLargeVector ;
|
||||
} ;
|
||||
</pre>
|
||||
|
||||
<HR>
|
||||
|
||||
<H2><A NAME="bool">A note about optional<bool></A></H2>
|
||||
<p><code>optional<bool></code> should be used with special caution and consideration.</p>
|
||||
<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, 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 and 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 ) ;
|
||||
void bar()
|
||||
{
|
||||
optional<bool> v = try();
|
||||
|
||||
// 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).
|
||||
}
|
||||
</pre>
|
||||
<p>The only implicit conversion is to bool, and it is <i>safe</i> in the sense that typical
|
||||
integral promotions don't apply (i.e. if foo() takes an 'int' instead, it won't compile).
|
||||
<HR>
|
||||
|
||||
<H2><A NAME="exsafety">Exception Safety Guarantees</A></H2>
|
||||
<H3><u>Assignment and Reset:</u></H3>
|
||||
<p>Because of the current implementation (see <A HREF="#impl">Implementation Notes</A>),
|
||||
<code> optional<T>::operator=( optional<T> const& )
|
||||
and optional<T>::reset( T const& )</code>
|
||||
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><code>optional<T>::reset()</code> provides the no-throw guarantee (assuming a no-throw T::~T())</p>
|
||||
<p>However, since <code>optional<></code> itself doesn't throw any exceptions,
|
||||
the only source for exceptions here is T's copy constructor, so if you know the exception guarantees
|
||||
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<T> opt0(v0);
|
||||
try
|
||||
{
|
||||
T v1(456);
|
||||
optional<T> opt1(v1);
|
||||
opt0 = opt1 ;
|
||||
|
||||
// If no exception was thrown, assignment succeeded.
|
||||
assert( *opt0 == v1 ) ;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
// If any exception was thrown, 'opt0' is reset to uninitialized.
|
||||
assert( !opt0 ) ;
|
||||
}
|
||||
|
||||
//
|
||||
// Case 2: Exception thrown during reset(v)
|
||||
//
|
||||
T v0(123);
|
||||
optional<T> opt(v0);
|
||||
try
|
||||
{
|
||||
T v1(456);
|
||||
opt.reset ( v1 ) ;
|
||||
|
||||
// If no exception was thrown, reset succeeded.
|
||||
assert( *opt == v1 ) ;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
// If any exception was thrown, 'opt' is reset to uninitialized.
|
||||
assert( !opt ) ;
|
||||
}
|
||||
</pre>
|
||||
<H3><u>Swap:</u></H3>
|
||||
<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>
|
||||
|
||||
<HR>
|
||||
|
||||
<H2><A NAME="requirements">Type requirements</A></H2>
|
||||
<p>T must be <a href="../../utility/CopyConstructible.html">Copy Constructible</a>
|
||||
and have a no-throw destructor.<br>
|
||||
T <u>is not</u> required to be
|
||||
<a href="http://www.sgi.com/tech/stl/DefaultConstructible.html">Default Constructible</a>
|
||||
</p>
|
||||
|
||||
<HR>
|
||||
|
||||
<H2><A NAME="impl">Implementation Notes</A></H2>
|
||||
<p>optional<T> is currently implemented
|
||||
using a custom aligned storage facility built from <code>alignment_of</code> and
|
||||
<code>type_with_alignment</code> (both from Type Traits).
|
||||
It uses a separate boolean flag to indicate the initialization state.<br>
|
||||
Placement new with T's copy constructor and T's destructor
|
||||
are explicitly used to initialize,copy and destroy optional values.<br>
|
||||
As a result, T's default constructor is effectively by-passed, but the exception
|
||||
guarantees are basic.<br>
|
||||
It is planned to replace the current implementation with another with
|
||||
stronger exception safety, such as a future boost::variant<T,nil_t>.
|
||||
</p>
|
||||
|
||||
<HR>
|
||||
|
||||
<H2><A NAME="porta">Dependencies and Portability</A></H2>
|
||||
|
||||
<p>The implementation uses <code>type_traits/alignment_of.hpp</code>
|
||||
and <code>type_traits/type_with_alignment.hpp</code></p>
|
||||
<p>It has been tested on bcc5.5.1, vc6.0 and gcc2.95.2</p>
|
||||
|
||||
<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
|
||||
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 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,
|
||||
and others.
|
||||
</p>
|
||||
</blockquote>
|
||||
<HR>
|
||||
|
||||
<P>Revised January 20, 2003</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>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 discussion list at
|
||||
<A
|
||||
HREF="http://www.yahoogroups.com/list/boost">www.yahoogroups.com/list/boost</A>.
|
||||
</P>
|
||||
</u></BODY>
|
||||
</HTML>
|
||||
|
126
doc/optional.qbk
Normal file
126
doc/optional.qbk
Normal file
@ -0,0 +1,126 @@
|
||||
[library Boost.Optional
|
||||
[quickbook 1.4]
|
||||
[authors [Cacciola Carballal, Fernando Luis]]
|
||||
[copyright 2003-2007 Fernando Luis Cacciola Carballal]
|
||||
[category miscellaneous]
|
||||
[id optional]
|
||||
[dirname optional]
|
||||
[purpose
|
||||
Discriminated-union wrapper for optional values
|
||||
]
|
||||
[source-mode c++]
|
||||
[license
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
[@http://www.boost.org/LICENSE_1_0.txt])
|
||||
]
|
||||
]
|
||||
|
||||
[/ Macros will be used for links so we have a central place to change them ]
|
||||
|
||||
|
||||
[/ Cited Boost resources ]
|
||||
|
||||
[def __BOOST_VARIANT__ [@../../../variant/index.html Boost.Variant]]
|
||||
[def __BOOST_TRIBOOL__ [@../../../../doc/html/tribool.html boost::tribool]]
|
||||
|
||||
[def __OPTIONAL_POINTEE__ [@../../../utility/OptionalPointee.html OptionalPointee]]
|
||||
[def __COPY_CONSTRUCTIBLE__ [@../../../utility/CopyConstructible.html Copy Constructible]]
|
||||
[def __FUNCTION_EQUAL_POINTEES__ [@../../../utility/OptionalPointee.html#equal `equal_pointees()`]]
|
||||
[def __FUNCTION_LESS_POINTEES__ [@../../../utility/OptionalPointee.html#less `less_pointees()`]]
|
||||
|
||||
[def __IN_PLACE_FACTORY_HPP__ [@../../../../boost/utility/in_place_factory.hpp in_place_factory.hpp]]
|
||||
[def __TYPED_IN_PLACE_FACTORY_HPP__ [@../../../../boost/utility/typed_in_place_factory.hpp typed_in_place_factory.hpp]]
|
||||
|
||||
[/ Other web resources ]
|
||||
|
||||
[def __HASKELL__ [@http://www.haskell.org/ Haskell]]
|
||||
[def __SGI_DEFAULT_CONSTRUCTIBLE__ [@http://www.sgi.com/tech/stl/DefaultConstructible.html Default Constructible]]
|
||||
|
||||
|
||||
[/ Icons ]
|
||||
|
||||
[def __SPACE__ [$images/space.png]]
|
||||
[def __GO_TO__ [$images/callouts/R.png]]
|
||||
|
||||
|
||||
[section Motivation]
|
||||
|
||||
Consider these functions which should return a value but which might not have
|
||||
a value to return:
|
||||
|
||||
* (A) `double sqrt(double n );`
|
||||
* (B) `char get_async_input();`
|
||||
* (C) `point polygon::get_any_point_effectively_inside();`
|
||||
|
||||
There are different approaches to the issue of not having a value to return.
|
||||
|
||||
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 assert 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.
|
||||
|
||||
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.
|
||||
|
||||
A similar situation occurs with function (C): it is conceptually an error to
|
||||
ask a ['null-area] 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.
|
||||
|
||||
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...
|
||||
|
||||
When those values exist, i.e. the return type can hold all meaningful values
|
||||
['plus] the ['signal] 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>`.
|
||||
|
||||
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:
|
||||
|
||||
std::pair<char,bool> get_async_input();
|
||||
std::pair<point,bool> polygon::get_any_point_effectively_inside();
|
||||
|
||||
These functions use a consistent interface for dealing with possibly nonexistent
|
||||
results:
|
||||
|
||||
std::pair<point,bool> p = poly.get_any_point_effectively_inside();
|
||||
if ( p.second )
|
||||
flood_fill(p.first);
|
||||
|
||||
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.
|
||||
|
||||
Clearly, we need a better idiom.
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
[include development.qbk]
|
||||
[include reference.qbk]
|
||||
[include examples.qbk]
|
||||
[include special_cases.qbk]
|
||||
[include implementation_notes.qbk]
|
||||
[include dependencies.qbk]
|
||||
[include acknowledgments.qbk]
|
||||
|
||||
|
900
doc/reference.qbk
Normal file
900
doc/reference.qbk
Normal file
@ -0,0 +1,900 @@
|
||||
[/
|
||||
Boost.Optional
|
||||
|
||||
Copyright (c) 2003-2007 Fernando Luis Cacciola Carballal
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt)
|
||||
]
|
||||
|
||||
|
||||
[section Synopsis]
|
||||
|
||||
```// In Header: <`[@boost:/boost/optional/optional.hpp boost/optional/optional.hpp]'''<phrase role="comment">></phrase>'''``
|
||||
|
||||
namespace boost {
|
||||
|
||||
template<class T>
|
||||
class optional
|
||||
{
|
||||
public :
|
||||
|
||||
// (If T is of reference type, the parameters and results by reference are by value)
|
||||
|
||||
optional () ; ``[link reference_optional_constructor __GO_TO__]``
|
||||
|
||||
optional ( none_t ) ; ``[link reference_optional_constructor_none_t __GO_TO__]``
|
||||
|
||||
optional ( T const& v ) ; ``[link reference_optional_constructor_value __GO_TO__]``
|
||||
|
||||
// [new in 1.34]
|
||||
optional ( bool condition, T const& v ) ; ``[link reference_optional_constructor_bool_value __GO_TO__]``
|
||||
|
||||
optional ( optional const& rhs ) ; ``[link reference_optional_constructor_optional __GO_TO__]``
|
||||
|
||||
template<class U> explicit optional ( optional<U> const& rhs ) ; ``[link reference_optional_constructor_other_optional __GO_TO__]``
|
||||
|
||||
template<class InPlaceFactory> explicit optional ( InPlaceFactory const& f ) ; ``[link reference_optional_constructor_factory __GO_TO__]``
|
||||
|
||||
template<class TypedInPlaceFactory> explicit optional ( TypedInPlaceFactory const& f ) ; ``[link reference_optional_constructor_factory __GO_TO__]``
|
||||
|
||||
optional& operator = ( none_t ) ; ``[/[link reference_optional_operator_equal_none_t __GO_TO__]]``
|
||||
|
||||
optional& operator = ( T const& v ) ; ``[link reference_optional_operator_equal_value __GO_TO__]``
|
||||
|
||||
optional& operator = ( optional const& rhs ) ; ``[link reference_optional_operator_equal_optional __GO_TO__]``
|
||||
|
||||
template<class U> optional& operator = ( optional<U> const& rhs ) ; ``[link reference_optional_operator_equal_other_optional __GO_TO__]``
|
||||
|
||||
template<class InPlaceFactory> optional& operator = ( InPlaceFactory const& f ) ; ``[link reference_optional_operator_equal_factory __GO_TO__]``
|
||||
|
||||
template<class TypedInPlaceFactory> optional& operator = ( TypedInPlaceFactory const& f ) ; ``[link reference_optional_operator_equal_factory __GO_TO__]``
|
||||
|
||||
T const& get() const ; ``[link reference_optional_get __GO_TO__]``
|
||||
T& get() ; ``[link reference_optional_get __GO_TO__]``
|
||||
|
||||
// [new in 1.34]
|
||||
T const& get_value_or( T const& default ) const ; ``[link reference_optional_get_value_or_value __GO_TO__]``
|
||||
|
||||
T const* operator ->() const ; ``[link reference_optional_operator_arrow __GO_TO__]``
|
||||
T* operator ->() ; ``[link reference_optional_operator_arrow __GO_TO__]``
|
||||
|
||||
T const& operator *() const ; ``[link reference_optional_get __GO_TO__]``
|
||||
T& operator *() ; ``[link reference_optional_get __GO_TO__]``
|
||||
|
||||
T const* get_ptr() const ; ``[link reference_optional_get_ptr __GO_TO__]``
|
||||
T* get_ptr() ; ``[link reference_optional_get_ptr __GO_TO__]``
|
||||
|
||||
operator unspecified-bool-type() const ; ``[link reference_optional_operator_bool __GO_TO__]``
|
||||
|
||||
bool operator!() const ; ``[link reference_optional_operator_not __GO_TO__]``
|
||||
|
||||
// deprecated methods
|
||||
|
||||
// (deprecated)
|
||||
void reset() ; ``[link reference_optional_reset __GO_TO__]``
|
||||
|
||||
// (deprecated)
|
||||
void reset ( T const& ) ; ``[link reference_optional_reset_value __GO_TO__]``
|
||||
|
||||
// (deprecated)
|
||||
bool is_initialized() const ; ``[link reference_optional_is_initialized __GO_TO__]``
|
||||
|
||||
};
|
||||
|
||||
template<class T> inline bool operator == ( optional<T> const& x, optional<T> const& y ) ; ``[link reference_operator_compare_equal_optional_optional __GO_TO__]``
|
||||
|
||||
template<class T> inline bool operator != ( optional<T> const& x, optional<T> const& y ) ; ``[link reference_operator_compare_not_equal_optional_optional __GO_TO__]``
|
||||
|
||||
template<class T> inline bool operator < ( optional<T> const& x, optional<T> const& y ) ; ``[link reference_operator_compare_less_optional_optional __GO_TO__]``
|
||||
|
||||
template<class T> inline bool operator > ( optional<T> const& x, optional<T> const& y ) ; ``[link reference_operator_compare_greater_optional_optional __GO_TO__]``
|
||||
|
||||
template<class T> inline bool operator <= ( optional<T> const& x, optional<T> const& y ) ; ``[link reference_operator_compare_less_or_equal_optional_optional __GO_TO__]``
|
||||
|
||||
template<class T> inline bool operator >= ( optional<T> const& x, optional<T> const& y ) ; ``[link reference_operator_compare_greater_or_equal_optional_optional __GO_TO__]``
|
||||
|
||||
// [new in 1.34]
|
||||
template<class T> inline optional<T> make_optional ( T const& v ) ; ``[link reference_make_optional_value __GO_TO__]``
|
||||
|
||||
// [new in 1.34]
|
||||
template<class T> inline optional<T> make_optional ( bool condition, T const& v ) ; ``[link reference_make_optional_bool_value __GO_TO__]``
|
||||
|
||||
// [new in 1.34]
|
||||
template<class T> inline T const& get_optional_value_or ( optional<T> const& opt, T const& default ) ; ``[link reference_optional_get_value_or_value __GO_TO__]``
|
||||
|
||||
template<class T> inline T const& get ( optional<T> const& opt ) ; ``[link reference_optional_get __GO_TO__]``
|
||||
|
||||
template<class T> inline T& get ( optional<T> & opt ) ; ``[link reference_optional_get __GO_TO__]``
|
||||
|
||||
template<class T> inline T const* get ( optional<T> const* opt ) ; ``[link reference_optional_get __GO_TO__]``
|
||||
|
||||
template<class T> inline T* get ( optional<T>* opt ) ; ``[link reference_optional_get __GO_TO__]``
|
||||
|
||||
template<class T> inline T const* get_pointer ( optional<T> const& opt ) ; ``[link reference_optional_get_ptr __GO_TO__]``
|
||||
|
||||
template<class T> inline T* get_pointer ( optional<T> & opt ) ; ``[link reference_optional_get_ptr __GO_TO__]``
|
||||
|
||||
template<class T> inline void swap( optional<T>& x, optional<T>& y ) ; ``[link reference_swap_optional_optional __GO_TO__]``
|
||||
|
||||
} // namespace boost
|
||||
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Detailed Semantics]
|
||||
|
||||
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:
|
||||
|
||||
* If the entry reads: `optional<T`['(not a ref)]`>`, the description
|
||||
corresponds only to the case where `T` is not of reference type.
|
||||
* If the entry reads: `optional<T&>`, the description corresponds only to
|
||||
the case where `T` is of reference type.
|
||||
* If the entry reads: `optional<T>`, the description is the same for both
|
||||
cases.
|
||||
|
||||
[note
|
||||
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.
|
||||
]
|
||||
|
||||
__SPACE__
|
||||
|
||||
[heading optional class member functions]
|
||||
|
||||
__SPACE__
|
||||
|
||||
[#reference_optional_constructor]
|
||||
|
||||
[: `optional<T>::optional();`]
|
||||
|
||||
* [*Effect:] Default-Constructs an `optional`.
|
||||
* [*Postconditions:] `*this` is [_uninitialized].
|
||||
* [*Throws:] Nothing.
|
||||
* Notes: T's default constructor [_is not] called.
|
||||
* [*Example:]
|
||||
``
|
||||
optional<T> def ;
|
||||
assert ( !def ) ;
|
||||
``
|
||||
|
||||
__SPACE__
|
||||
|
||||
[#reference_optional_constructor_none_t]
|
||||
|
||||
[: `optional<T>::optional( none_t );`]
|
||||
|
||||
* [*Effect:] Constructs an `optional` uninitialized.
|
||||
* [*Postconditions:] `*this` is [_uninitialized].
|
||||
* [*Throws:] Nothing.
|
||||
* [*Notes:] `T`'s default constructor [_is not] called. The expression
|
||||
`boost::none` denotes an instance of `boost::none_t` that can be used as
|
||||
the parameter.
|
||||
* [*Example:]
|
||||
``
|
||||
#include <boost/none.hpp>
|
||||
optional<T> n(none) ;
|
||||
assert ( !n ) ;
|
||||
``
|
||||
|
||||
__SPACE__
|
||||
|
||||
[#reference_optional_constructor_value]
|
||||
|
||||
[: `optional<T `['(not a ref)]`>::optional( T const& v )`]
|
||||
|
||||
* [*Effect:] Directly-Constructs an `optional`.
|
||||
* [*Postconditions:] `*this` is [_initialized] and its value is a['copy]
|
||||
of `v`.
|
||||
* [*Throws:] Whatever `T::T( T const& )` throws.
|
||||
* [*Notes: ] `T::T( T const& )` is called.
|
||||
* [*Exception Safety:] Exceptions can only be thrown during
|
||||
`T::T( T const& );` in that case, this constructor has no effect.
|
||||
* [*Example:]
|
||||
``
|
||||
T v;
|
||||
optional<T> opt(v);
|
||||
assert ( *opt == v ) ;
|
||||
``
|
||||
|
||||
__SPACE__
|
||||
|
||||
[: `optional<T&>::optional( T& ref )`]
|
||||
|
||||
* [*Effect:] Directly-Constructs an `optional`.
|
||||
* [*Postconditions:] `*this` is [_initialized] and its value is an instance
|
||||
of an internal type wrapping the reference `ref`.
|
||||
* [*Throws:] Nothing.
|
||||
* [*Example:]
|
||||
``
|
||||
T v;
|
||||
T& vref = v ;
|
||||
optional<T&> opt(vref);
|
||||
assert ( *opt == v ) ;
|
||||
++ v ; // mutate referee
|
||||
assert (*opt == v);
|
||||
``
|
||||
|
||||
__SPACE__
|
||||
|
||||
[#reference_optional_constructor_bool_value]
|
||||
|
||||
[: `optional<T` ['(not a ref)]`>::optional( bool condition, T const& v ) ;` ]
|
||||
[: `optional<T&> ::optional( bool condition, T& v ) ;` ]
|
||||
|
||||
* If condition is true, same as:
|
||||
|
||||
[: `optional<T` ['(not a ref)]`>::optional( T const& v )`]
|
||||
[: `optional<T&> ::optional( T& v )`]
|
||||
|
||||
* otherwise, same as:
|
||||
|
||||
[: `optional<T `['(not a ref)]`>::optional()`]
|
||||
[: `optional<T&> ::optional()`]
|
||||
|
||||
__SPACE__
|
||||
|
||||
[#reference_optional_constructor_optional]
|
||||
|
||||
[: `optional<T `['(not a ref)]`>::optional( optional const& rhs );`]
|
||||
|
||||
* [*Effect:] Copy-Constructs an `optional`.
|
||||
* [*Postconditions:] If rhs is initialized, `*this` is initialized and
|
||||
its value is a ['copy] of the value of `rhs`; else `*this` is uninitialized.
|
||||
* [*Throws:] Whatever `T::T( T const& )` throws.
|
||||
* [*Notes:] If rhs is initialized, `T::T(T const& )` is called.
|
||||
* [*Exception Safety:] Exceptions can only be thrown during
|
||||
`T::T( T const& );` in that case, this constructor has no effect.
|
||||
* [*Example:]
|
||||
``
|
||||
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 ) ;
|
||||
``
|
||||
|
||||
__SPACE__
|
||||
|
||||
[: `optional<T&>::optional( optional const& rhs );`]
|
||||
|
||||
* [*Effect:] Copy-Constructs an `optional`.
|
||||
* [*Postconditions:] If `rhs` is initialized, `*this` is initialized and its
|
||||
value is another reference to the same object referenced by `*rhs`; else
|
||||
`*this` is uninitialized.
|
||||
* [*Throws:] Nothing.
|
||||
* [*Notes:] If `rhs` is initialized, both `*this` and `*rhs` will reefer to the
|
||||
same object (they alias).
|
||||
* [*Example:]
|
||||
``
|
||||
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 ) ;
|
||||
|
||||
v = 3 ;
|
||||
|
||||
assert ( *init == 3 ) ;
|
||||
assert ( *init2 == 3 ) ;
|
||||
``
|
||||
|
||||
__SPACE__
|
||||
|
||||
[#reference_optional_constructor_other_optional]
|
||||
|
||||
[: `template<U> explicit optional<T` ['(not a ref)]`>::optional( optional<U> const& rhs );`]
|
||||
|
||||
* [*Effect:] Copy-Constructs an `optional`.
|
||||
* [*Postconditions:] If `rhs` is initialized, `*this` is initialized and its
|
||||
value is a ['copy] of the value of rhs converted to type `T`; else `*this` is
|
||||
uninitialized.
|
||||
* [*Throws:] Whatever `T::T( U const& )` throws.
|
||||
* [*Notes: ] `T::T( U const& )` is called if `rhs` is initialized, which requires a
|
||||
valid conversion from `U` to `T`.
|
||||
* [*Exception Safety:] Exceptions can only be thrown during `T::T( U const& );`
|
||||
in that case, this constructor has no effect.
|
||||
* [*Example:]
|
||||
``
|
||||
optional<double> x(123.4);
|
||||
assert ( *x == 123.4 ) ;
|
||||
|
||||
optional<int> y(x) ;
|
||||
assert( *y == 123 ) ;
|
||||
``
|
||||
|
||||
__SPACE__
|
||||
|
||||
[#reference_optional_constructor_factory]
|
||||
|
||||
[: `template<InPlaceFactory> explicit optional<T` ['(not a ref)]`>::optional( InPlaceFactory const& f );`]
|
||||
[: `template<TypedInPlaceFactory> explicit optional<T` ['(not a ref)]`>::optional( TypedInPlaceFactory const& f );`]
|
||||
|
||||
* [*Effect:] Constructs an `optional` with a value of `T` obtained from the
|
||||
factory.
|
||||
* [*Postconditions: ] `*this` is [_initialized] and its value is ['directly given]
|
||||
from the factory `f` (i.e., the value [_is not copied]).
|
||||
* [*Throws:] Whatever the `T` constructor called by the factory throws.
|
||||
* [*Notes:] See [link boost_optional.in_place_factories In-Place Factories]
|
||||
* [*Exception Safety:] Exceptions can only be thrown during the call to
|
||||
the `T` constructor used by the factory; in that case, this constructor has
|
||||
no effect.
|
||||
* [*Example:]
|
||||
``
|
||||
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 ) ;
|
||||
``
|
||||
|
||||
__SPACE__
|
||||
|
||||
[#reference_optional_operator_equal_value]
|
||||
|
||||
[: `optional& optional<T` ['(not a ref)]`>::operator= ( T const& rhs ) ;`]
|
||||
|
||||
* [*Effect:] Assigns the value `rhs` to an `optional`.
|
||||
* [*Postconditions: ] `*this` is initialized and its value is a ['copy] of `rhs`.
|
||||
* [*Throws:] Whatever `T::operator=( T const& )` or `T::T(T const&)` throws.
|
||||
* [*Notes:] If `*this` was initialized, `T`'s assignment operator is used,
|
||||
otherwise, its copy-constructor is used.
|
||||
* [*Exception Safety:] In the event of an exception, the initialization
|
||||
state of `*this` is unchanged and its value unspecified as far as `optional`
|
||||
is concerned (it is up to `T`'s `operator=()`). If `*this` is initially
|
||||
uninitialized and `T`'s ['copy constructor] fails, `*this` is left properly
|
||||
uninitialized.
|
||||
* [*Example:]
|
||||
``
|
||||
T x;
|
||||
optional<T> def ;
|
||||
optional<T> opt(x) ;
|
||||
|
||||
T y;
|
||||
def = y ;
|
||||
assert ( *def == y ) ;
|
||||
opt = y ;
|
||||
assert ( *opt == y ) ;
|
||||
``
|
||||
|
||||
__SPACE__
|
||||
|
||||
[: `optional<T&>& optional<T&>::operator= ( T& rhs ) ;`]
|
||||
|
||||
* [*Effect:] (Re)binds the wrapped reference.
|
||||
* [*Postconditions: ] `*this` is initialized and it references the same
|
||||
object referenced by `rhs`.
|
||||
* [*Notes:] If `*this` was initialized, is is ['rebound] to the new object.
|
||||
See [link boost_optional.rebinding_semantics_for_assignment_of_optional_references here] for details on this behavior.
|
||||
* [*Example:]
|
||||
``
|
||||
int a = 1 ;
|
||||
int b = 2 ;
|
||||
T& ra = a ;
|
||||
T& rb = b ;
|
||||
optional<int&> def ;
|
||||
optional<int&> opt(ra) ;
|
||||
|
||||
def = rb ; // binds 'def' to 'b' through 'rb'
|
||||
assert ( *def == b ) ;
|
||||
*def = a ; // changes the value of 'b' to a copy of the value of 'a'
|
||||
assert ( b == a ) ;
|
||||
int c = 3;
|
||||
int& rc = c ;
|
||||
opt = rc ; // REBINDS to 'c' through 'rc'
|
||||
c = 4 ;
|
||||
assert ( *opt == 4 ) ;
|
||||
``
|
||||
|
||||
__SPACE__
|
||||
|
||||
[#reference_optional_operator_equal_optional]
|
||||
|
||||
[: `optional& optional<T` ['(not a ref)]`>::operator= ( optional const& rhs ) ;`]
|
||||
|
||||
* [*Effect:] Assigns another `optional` to an `optional`.
|
||||
* [*Postconditions:] If `rhs` is initialized, `*this` is initialized and
|
||||
its value is a ['copy] of the value of `rhs`; else `*this` is uninitialized.
|
||||
* [*Throws:] Whatever `T::operator( T const&)` or `T::T( T const& )` throws.
|
||||
* [*Notes:] If both `*this` and `rhs` are initially initialized, `T`'s
|
||||
['assignment operator] is used. If `*this` is initially initialized but `rhs` is
|
||||
uninitialized, `T`'s [destructor] is called. If `*this` is initially uninitialized
|
||||
but `rhs` is initialized, `T`'s ['copy constructor] is called.
|
||||
* [*Exception Safety:] In the event of an exception, the initialization state of
|
||||
`*this` is unchanged and its value unspecified as far as optional is concerned
|
||||
(it is up to `T`'s `operator=()`). If `*this` is initially uninitialized and
|
||||
`T`'s ['copy constructor] fails, `*this` is left properly uninitialized.
|
||||
* [*Example:]
|
||||
``
|
||||
T v;
|
||||
optional<T> opt(v);
|
||||
optional<T> def ;
|
||||
|
||||
opt = def ;
|
||||
assert ( !def ) ;
|
||||
// previous value (copy of 'v') destroyed from within 'opt'.
|
||||
``
|
||||
|
||||
__SPACE__
|
||||
|
||||
[: `optional<T&> & optional<T&>::operator= ( optional<T&> const& rhs ) ;`]
|
||||
|
||||
* [*Effect:] (Re)binds thee wrapped reference.
|
||||
* [*Postconditions:] If `*rhs` is initialized, `*this` is initialized and it
|
||||
references the same object referenced by `*rhs`; otherwise, `*this` is
|
||||
uninitialized (and references no object).
|
||||
* [*Notes:] If `*this` was initialized and so is *rhs, this is is ['rebound] to
|
||||
the new object. See [link boost_optional.rebinding_semantics_for_assignment_of_optional_references here] for details on this behavior.
|
||||
* [*Example:]
|
||||
``
|
||||
int a = 1 ;
|
||||
int b = 2 ;
|
||||
T& ra = a ;
|
||||
T& rb = b ;
|
||||
optional<int&> def ;
|
||||
optional<int&> ora(ra) ;
|
||||
optional<int&> orb(rb) ;
|
||||
|
||||
def = orb ; // binds 'def' to 'b' through 'rb' wrapped within 'orb'
|
||||
assert ( *def == b ) ;
|
||||
*def = ora ; // changes the value of 'b' to a copy of the value of 'a'
|
||||
assert ( b == a ) ;
|
||||
int c = 3;
|
||||
int& rc = c ;
|
||||
optional<int&> orc(rc) ;
|
||||
ora = orc ; // REBINDS ora to 'c' through 'rc'
|
||||
c = 4 ;
|
||||
assert ( *ora == 4 ) ;
|
||||
``
|
||||
|
||||
__SPACE__
|
||||
|
||||
[#reference_optional_operator_equal_other_optional]
|
||||
|
||||
[: `template<U> optional& optional<T` ['(not a ref)]`>::operator= ( optional<U> const& rhs ) ;`]
|
||||
|
||||
* [*Effect:] Assigns another convertible optional to an optional.
|
||||
* [*Postconditions:] If `rhs` is initialized, `*this` is initialized and
|
||||
its value is a ['copy] of the value of `rhs` ['converted] to type `T`; else
|
||||
`*this` is uninitialized.
|
||||
* [*Throws:] Whatever `T::operator=( U const& )` or `T::T( U const& )` throws.
|
||||
* [*Notes:] If both `*this` and rhs are initially initialized, `T`'s
|
||||
['assignment operator] (from `U`) is used. If `*this` is initially initialized
|
||||
but `rhs` is uninitialized, `T`'s ['destructor] is called. If `*this` is
|
||||
initially uninitialized but rhs is initialized, `T`'s ['converting constructor]
|
||||
(from `U`) is called.
|
||||
* [*Exception Safety:] In the event of an exception, the initialization state
|
||||
of `*this` is unchanged and its value unspecified as far as optional is
|
||||
concerned (it is up to `T`'s `operator=()`). If `*this` is initially
|
||||
uninitialized and `T`'s converting constructor fails, `*this` is left properly
|
||||
uninitialized.
|
||||
* [*Example:]
|
||||
``
|
||||
T v;
|
||||
optional<T> opt0(v);
|
||||
optional<U> opt1;
|
||||
|
||||
opt1 = opt0 ;
|
||||
assert ( *opt1 == static_cast<U>(v) ) ;
|
||||
``
|
||||
|
||||
__SPACE__
|
||||
|
||||
[#reference_optional_operator_equal_factory]
|
||||
|
||||
[: `template<InPlaceFactory> optional<T>& optional<T` ['(not a ref)]`>::operator=( InPlaceFactory const& f );`]
|
||||
[: `template<TypedInPlaceFactory> optional<T>& optional<T` ['(not a ref)]`>::operator=( TypedInPlaceFactory const& f );`]
|
||||
|
||||
* [*Effect:] Assigns an `optional` with a value of `T` obtained from the
|
||||
factory.
|
||||
* [*Postconditions: ] `*this` is [_initialized] and its value is ['directly given]
|
||||
from the factory `f` (i.e., the value [_is not copied]).
|
||||
* [*Throws:] Whatever the `T` constructor called by the factory throws.
|
||||
* [*Notes:] See [link boost_optional.in_place_factories In-Place Factories]
|
||||
* [*Exception Safety:] Exceptions can only be thrown during the call to
|
||||
the `T` constructor used by the factory; in that case, the `optional` object
|
||||
will be reset to be ['uninitialized].
|
||||
|
||||
__SPACE__
|
||||
|
||||
[#reference_optional_reset_value]
|
||||
|
||||
[: `void optional<T` ['(not a ref)]`>::reset( T const& v ) ;`]
|
||||
* [*Deprecated:] same as `operator= ( T const& v) ;`
|
||||
|
||||
__SPACE__
|
||||
|
||||
[#reference_optional_reset]
|
||||
|
||||
[: `void optional<T>::reset() ;`]
|
||||
* [*Deprecated:] Same as `operator=( detail::none_t );`
|
||||
|
||||
__SPACE__
|
||||
|
||||
[#reference_optional_get]
|
||||
|
||||
[: `T const& optional<T` ['(not a ref)]`>::operator*() const ;`]
|
||||
[: `T& optional<T` ['(not a ref)]`>::operator*();`]
|
||||
[: `T const& optional<T` ['(not a ref)]`>::get() const ;`]
|
||||
[: `T& optional<T` ['(not a ref)]`>::get() ;`]
|
||||
|
||||
[: `inline T const& get ( optional<T` ['(not a ref)]`> const& ) ;`]
|
||||
[: `inline T& get ( optional<T` ['(not a ref)]`> &) ;`]
|
||||
|
||||
* [*Requirements:] `*this` is initialized
|
||||
* [*Returns:] A reference to the contained value
|
||||
* [*Throws:] Nothing.
|
||||
* [*Notes:] The requirement is asserted via `BOOST_ASSERT()`.
|
||||
* [*Example:]
|
||||
``
|
||||
T v ;
|
||||
optional<T> opt ( v );
|
||||
T const& u = *opt;
|
||||
assert ( u == v ) ;
|
||||
T w ;
|
||||
*opt = w ;
|
||||
assert ( *opt == w ) ;
|
||||
``
|
||||
|
||||
__SPACE__
|
||||
|
||||
[#reference_optional_get_value_or_value]
|
||||
|
||||
[: `T const& optional<T` ['(not a ref)]`>::get_value_or( T const& default) const ;`]
|
||||
[: `T& optional<T` ['(not a ref)]`>::get_value_or( T& default ) ;`]
|
||||
|
||||
[: `inline T const& get_optional_value_or ( optional<T` ['(not a ref)]`> const& o, T const& default ) ;`]
|
||||
[: `inline T& get_optional_value_or ( optional<T` ['(not a ref)]`>& o, T& default ) ;`]
|
||||
|
||||
* [*Returns:] A reference to the contained value, if any, or `default`.
|
||||
* [*Throws:] Nothing.
|
||||
* [*Example:]
|
||||
``
|
||||
T v, z ;
|
||||
optional<T> def;
|
||||
T const& y = def.get_value_or(z);
|
||||
assert ( y == z ) ;
|
||||
|
||||
optional<T> opt ( v );
|
||||
T const& u = get_optional_value_or(opt,z);
|
||||
assert ( u == v ) ;
|
||||
assert ( u != z ) ;
|
||||
``
|
||||
|
||||
__SPACE__
|
||||
|
||||
[: `T const& optional<T&>::operator*() const ;`]
|
||||
[: `T & optional<T&>::operator*();`]
|
||||
[: `T const& optional<T&>::get() const ;`]
|
||||
[: `T& optional<T&>::get() ;`]
|
||||
|
||||
[: `inline T const& get ( optional<T&> const& ) ;`]
|
||||
[: `inline T& get ( optional<T&> &) ;`]
|
||||
|
||||
* [*Requirements: ] `*this` is initialized
|
||||
* [*Returns:] [_The] reference contained.
|
||||
* [*Throws:] Nothing.
|
||||
* [*Notes:] The requirement is asserted via `BOOST_ASSERT()`.
|
||||
* [*Example:]
|
||||
``
|
||||
T v ;
|
||||
T& vref = v ;
|
||||
optional<T&> opt ( vref );
|
||||
T const& vref2 = *opt;
|
||||
assert ( vref2 == v ) ;
|
||||
++ v ;
|
||||
assert ( *opt == v ) ;
|
||||
``
|
||||
|
||||
__SPACE__
|
||||
|
||||
[#reference_optional_get_ptr]
|
||||
|
||||
[: `T const* optional<T` ['(not a ref)]`>::get_ptr() const ;`]
|
||||
[: `T* optional<T` ['(not a ref)]`>::get_ptr() ;`]
|
||||
|
||||
[: `inline T const* get_pointer ( optional<T` ['(not a ref)]`> const& ) ;`]
|
||||
[: `inline T* get_pointer ( optional<T` ['(not a ref)]`> &) ;`]
|
||||
|
||||
* [*Returns:] If `*this` is initialized, a pointer to the contained value;
|
||||
else `0` (['null]).
|
||||
* [*Throws:] Nothing.
|
||||
* [*Notes:] The contained value is permanently stored within `*this`, so you
|
||||
should not hold nor delete this pointer
|
||||
* [*Example:]
|
||||
``
|
||||
T v;
|
||||
optional<T> opt(v);
|
||||
optional<T> const copt(v);
|
||||
T* p = opt.get_ptr() ;
|
||||
T const* cp = copt.get_ptr();
|
||||
assert ( p == get_pointer(opt) );
|
||||
assert ( cp == get_pointer(copt) ) ;
|
||||
``
|
||||
|
||||
__SPACE__
|
||||
|
||||
[#reference_optional_operator_arrow]
|
||||
|
||||
[: `T const* optional<T` ['(not a ref)]`>::operator ->() const ;`]
|
||||
[: `T* optional<T` ['(not a ref)]`>::operator ->() ;`]
|
||||
|
||||
* [*Requirements: ] `*this` is initialized.
|
||||
* [*Returns:] A pointer to the contained value.
|
||||
* [*Throws:] Nothing.
|
||||
* [*Notes:] The requirement is asserted via `BOOST_ASSERT()`.
|
||||
* [*Example:]
|
||||
``
|
||||
struct X { int mdata ; } ;
|
||||
X x ;
|
||||
optional<X> opt (x);
|
||||
opt->mdata = 2 ;
|
||||
``
|
||||
|
||||
__SPACE__
|
||||
|
||||
[#reference_optional_operator_bool]
|
||||
|
||||
[: `optional<T>::operator `['unspecified-bool-type]`() const ;`]
|
||||
|
||||
* [*Returns:] An unspecified value which if used on a boolean context
|
||||
is equivalent to (`get() != 0`)
|
||||
* [*Throws:] Nothing.
|
||||
* [*Example:]
|
||||
``
|
||||
optional<T> def ;
|
||||
assert ( def == 0 );
|
||||
optional<T> opt ( v ) ;
|
||||
assert ( opt );
|
||||
assert ( opt != 0 );
|
||||
``
|
||||
|
||||
__SPACE__
|
||||
|
||||
[#reference_optional_operator_not]
|
||||
|
||||
[: `bool optional<T>::operator!() ;`]
|
||||
|
||||
* [*Returns:] If `*this` is uninitialized, `true`; else `false`.
|
||||
* [*Throws:] Nothing.
|
||||
* [*Notes:] This operator is provided for those compilers which can't
|
||||
use the ['unspecified-bool-type operator] in certain boolean contexts.
|
||||
* [*Example:]
|
||||
``
|
||||
optional<T> opt ;
|
||||
assert ( !opt );
|
||||
*opt = some_T ;
|
||||
|
||||
// Notice the "double-bang" idiom here.
|
||||
assert ( !!opt ) ;
|
||||
``
|
||||
|
||||
__SPACE__
|
||||
|
||||
[#reference_optional_is_initialized]
|
||||
|
||||
[: `bool optional<T>::is_initialized() const ;`]
|
||||
|
||||
* [*Returns: ] `true` if the `optional` is initialized, `false` otherwise.
|
||||
* [*Throws:] Nothing.
|
||||
* [*Example:]
|
||||
``
|
||||
optional<T> def ;
|
||||
assert ( !def.is_initialized() );
|
||||
optional<T> opt ( v ) ;
|
||||
assert ( opt.is_initialized() );
|
||||
``
|
||||
|
||||
__SPACE__
|
||||
|
||||
[heading Free functions]
|
||||
|
||||
__SPACE__
|
||||
|
||||
[#reference_make_optional_value]
|
||||
|
||||
[: `optional<T` ['(not a ref)]`> make_optional( T const& v )`]
|
||||
|
||||
* [*Returns: ] `optional<T>(v)` for the ['deduced] type `T` of `v`.
|
||||
* [*Example:]
|
||||
``
|
||||
template<class T> void foo ( optional<T> const& opt ) ;
|
||||
|
||||
foo ( make_optional(1+1) ) ; // Creates an optional<int>
|
||||
``
|
||||
|
||||
__SPACE__
|
||||
|
||||
[#reference_make_optional_bool_value]
|
||||
|
||||
[: `optional<T` ['(not a ref)]`> make_optional( bool condition, T const& v )`]
|
||||
|
||||
* [*Returns: ] `optional<T>(condition,v)` for the ['deduced] type `T` of `v`.
|
||||
* [*Example:]
|
||||
``
|
||||
optional<double> calculate_foo()
|
||||
{
|
||||
double val = compute_foo();
|
||||
return make_optional(is_not_nan_and_finite(val),val);
|
||||
}
|
||||
|
||||
optional<double> v = calculate_foo();
|
||||
if ( !v )
|
||||
error("foo wasn't computed");
|
||||
``
|
||||
|
||||
__SPACE__
|
||||
|
||||
[#reference_operator_compare_equal_optional_optional]
|
||||
|
||||
[: `bool operator == ( optional<T> const& x, optional<T> const& y );`]
|
||||
|
||||
* [*Returns:] If both `x` and `y` are initialized, `(*x == *y)`. If only
|
||||
`x` or `y` is initialized, `false`. If both are uninitialized, `true`.
|
||||
* [*Throws:] Nothing.
|
||||
* [*Notes:] Pointers have shallow relational operators while `optional` 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
|
||||
__FUNCTION_EQUAL_POINTEES__ instead
|
||||
* [*Example:]
|
||||
``
|
||||
T x(12);
|
||||
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 ) ;
|
||||
``
|
||||
|
||||
__SPACE__
|
||||
|
||||
[#reference_operator_compare_less_optional_optional]
|
||||
|
||||
[: `bool operator < ( optional<T> const& x, optional<T> const& y );`]
|
||||
|
||||
* [*Returns:] If `y` is not initialized, `false`. If `y` is initialized
|
||||
and `x` is not initialized, `true`. If both `x` and `y` are initialized,
|
||||
`(*x < *y)`.
|
||||
* [*Throws:] Nothing.
|
||||
* [*Notes:] Pointers have shallow relational operators while `optional` 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 __FUNCTION_LESS_POINTEES__ instead.
|
||||
* [*Example:]
|
||||
``
|
||||
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 ) ;
|
||||
``
|
||||
|
||||
__SPACE__
|
||||
|
||||
[#reference_operator_compare_not_equal_optional_optional]
|
||||
|
||||
[: `bool operator != ( optional<T> const& x, optional<T> const& y );`]
|
||||
|
||||
* [*Returns: ] `!( x == y );`
|
||||
* [*Throws:] Nothing.
|
||||
|
||||
__SPACE__
|
||||
|
||||
[#reference_operator_compare_greater_optional_optional]
|
||||
|
||||
[: `bool operator > ( optional<T> const& x, optional<T> const& y );`]
|
||||
|
||||
* [*Returns: ] `( y < x );`
|
||||
* [*Throws:] Nothing.
|
||||
|
||||
__SPACE__
|
||||
|
||||
[#reference_operator_compare_less_or_equal_optional_optional]
|
||||
|
||||
[: `bool operator <= ( optional<T> const& x, optional<T> const& y );`]
|
||||
|
||||
* [*Returns: ] `!( y<x );`
|
||||
* [*Throws:] Nothing.
|
||||
|
||||
__SPACE__
|
||||
|
||||
[#reference_operator_compare_greater_or_equal_optional_optional]
|
||||
|
||||
[: `bool operator >= ( optional<T> const& x, optional<T> const& y );`]
|
||||
|
||||
* [*Returns: ] `!( x<y );`
|
||||
* [*Throws:] Nothing.
|
||||
|
||||
__SPACE__
|
||||
|
||||
[#reference_swap_optional_optional]
|
||||
|
||||
[: `void swap ( optional<T>& x, optional<T>& y );`]
|
||||
|
||||
* [*Effect:] If both `x` and `y` are initialized, calls `swap(*x,*y)`
|
||||
using `std::swap`. If only one is initialized, say `x`, calls:
|
||||
`y.reset(*x); x.reset();` If none is initialized, does nothing.
|
||||
* [*Postconditions:] The states of `x` and `y` interchanged.
|
||||
* [*Throws:] If both are initialized, whatever `swap(T&,T&)` throws. If only
|
||||
one is initialized, whatever `T::T ( T const& )` throws.
|
||||
* [*Notes:] If both are initialized, `swap(T&,T&)` is used unqualified but
|
||||
with `std::swap` introduced in scope.
|
||||
If only one is initialized, `T::~T()` and `T::T( T const& )` is called.
|
||||
* [*Exception Safety:] If both are initialized, this operation has the
|
||||
exception safety guarantees of `swap(T&,T&)`.
|
||||
If only one is initialized, it has the same basic guarantee as
|
||||
`optional<T>::reset( T const& )`.
|
||||
* [*Example:]
|
||||
``
|
||||
T x(12);
|
||||
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 );
|
||||
``
|
||||
|
||||
[endsect]
|
372
doc/special_cases.qbk
Normal file
372
doc/special_cases.qbk
Normal file
@ -0,0 +1,372 @@
|
||||
|
||||
[section Optional references]
|
||||
|
||||
This library allows the template parameter `T` to be of reference type:
|
||||
`T&`, and to some extent, `T const&`.
|
||||
|
||||
However, since references are not real objects some restrictions apply and
|
||||
some operations are not available in this case:
|
||||
|
||||
* Converting constructors
|
||||
* Converting assignment
|
||||
* InPlace construction
|
||||
* InPlace assignment
|
||||
* Value-access via pointer
|
||||
|
||||
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:
|
||||
|
||||
* Copies of `optional<T&>` will copy the references but all these references
|
||||
will nonetheless reefer to the same object.
|
||||
* Value-access will actually provide access to the referenced object
|
||||
rather than the reference itself.
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Rebinding semantics for assignment of optional references]
|
||||
|
||||
If you assign to an ['uninitialized ] `optional<T&>` the effect is to bind (for
|
||||
the first time) to the object. Clearly, there is no other choice.
|
||||
|
||||
int x = 1 ;
|
||||
int& rx = x ;
|
||||
optional<int&> ora ;
|
||||
optional<int&> orb(x) ;
|
||||
ora = orb ; // now 'ora' is bound to 'x' through 'rx'
|
||||
*ora = 2 ; // Changes value of 'x' through 'ora'
|
||||
assert(x==2);
|
||||
|
||||
If you assign to a bare C++ reference, the assignment is forwarded to the
|
||||
referenced object; its value changes but the reference is never rebound.
|
||||
|
||||
int a = 1 ;
|
||||
int& ra = a ;
|
||||
int b = 2 ;
|
||||
int& rb = b ;
|
||||
ra = rb ; // Changes the value of 'a' to 'b'
|
||||
assert(a==b);
|
||||
b = 3 ;
|
||||
assert(ra!=b); // 'ra' is not rebound to 'b'
|
||||
|
||||
Now, if you assign to an ['initialized ] `optional<T&>`, the effect is to
|
||||
[*rebind] to the new object instead of assigning the referee. This is unlike
|
||||
bare C++ references.
|
||||
|
||||
int a = 1 ;
|
||||
int b = 2 ;
|
||||
int& ra = a ;
|
||||
int& rb = b ;
|
||||
optional<int&> ora(ra) ;
|
||||
optional<int&> orb(rb) ;
|
||||
ora = orb ; // 'ora' is rebound to 'b'
|
||||
*ora = 3 ; // Changes value of 'b' (not 'a')
|
||||
assert(a==1);
|
||||
assert(b==3);
|
||||
|
||||
[heading Rationale]
|
||||
|
||||
Rebinding semantics for the assignment of ['initialized ] `optional` references has
|
||||
been chosen to provide [*consistency among initialization states] even at the
|
||||
expense of lack of consistency with the semantics of bare C++ references.
|
||||
It is true that `optional<U>` strives to behave as much as possible as `U`
|
||||
does whenever it is initialized; but in the case when `U` is `T&`, doing so would
|
||||
result in inconsistent behavior w.r.t to the lvalue initialization state.
|
||||
|
||||
Imagine `optional<T&>` forwarding assignment to the referenced object (thus
|
||||
changing the referenced object value but not rebinding), and consider the
|
||||
following code:
|
||||
|
||||
optional<int&> a = get();
|
||||
int x = 1 ;
|
||||
int& rx = x ;
|
||||
optional<int&> b(rx);
|
||||
a = b ;
|
||||
|
||||
What does the assignment do?
|
||||
|
||||
If `a` is ['uninitialized], the answer is clear: it binds to `x` (we now have
|
||||
another reference to `x`).
|
||||
But what if `a` is already ['initialized]? it would change the value of the
|
||||
referenced object (whatever that is); which is inconsistent with the other
|
||||
possible case.
|
||||
|
||||
If `optional<T&>` would assign just like `T&` does, you would never be able to
|
||||
use Optional's assignment without explicitly handling the previous
|
||||
initialization state unless your code is capable of functioning whether
|
||||
after the assignment, `a` aliases the same object as `b` or not.
|
||||
|
||||
That is, you would have to discriminate in order to be consistent.
|
||||
|
||||
If in your code rebinding to another object is not an option, then it is very
|
||||
likely that binding for the first time isn't either. In such case, assignment
|
||||
to an ['uninitialized ] `optional<T&>` shall be prohibited. It is quite possible
|
||||
that in such a scenario it is a precondition that the lvalue must be already
|
||||
initialized. If it isn't, then binding for the first time is OK
|
||||
while rebinding is not which is IMO very unlikely.
|
||||
In such a scenario, you can assign the value itself directly, as in:
|
||||
|
||||
assert(!!opt);
|
||||
*opt=value;
|
||||
|
||||
[endsect]
|
||||
|
||||
[section In-Place Factories]
|
||||
|
||||
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 __COPY_CONSTRUCTIBLE__, but also requires the existence of
|
||||
a fully constructed object, often temporary, just to follow the copy from:
|
||||
|
||||
struct X
|
||||
{
|
||||
X ( int, std:::string ) ;
|
||||
} ;
|
||||
|
||||
class W
|
||||
{
|
||||
X wrapped_ ;
|
||||
|
||||
public:
|
||||
|
||||
W ( X const& x ) : wrapped_(x) {}
|
||||
} ;
|
||||
|
||||
void foo()
|
||||
{
|
||||
// Temporary object created.
|
||||
W ( X(123,"hello") ) ;
|
||||
}
|
||||
|
||||
A solution to this problem is to support direct construction of the
|
||||
contained object right in the container's storage.
|
||||
In this scheme, the user only needs to supply the arguments to the
|
||||
constructor to use in the wrapped object construction.
|
||||
|
||||
class W
|
||||
{
|
||||
X wrapped_ ;
|
||||
|
||||
public:
|
||||
|
||||
W ( X const& x ) : wrapped_(x) {}
|
||||
W ( int a0, std::string a1) : wrapped_(a0,a1) {}
|
||||
} ;
|
||||
|
||||
void foo()
|
||||
{
|
||||
// Wrapped object constructed in-place
|
||||
// No temporary created.
|
||||
W (123,"hello") ;
|
||||
}
|
||||
|
||||
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.
|
||||
|
||||
The solution presented in this library is the family of [*InPlaceFactories]
|
||||
and [*TypedInPlaceFactories].
|
||||
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.
|
||||
|
||||
For example, one member of this family looks like:
|
||||
|
||||
template<class T,class A0, class A1>
|
||||
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) ; }
|
||||
} ;
|
||||
|
||||
A wrapper class aware of this can use it as:
|
||||
|
||||
class W
|
||||
{
|
||||
X wrapped_ ;
|
||||
|
||||
public:
|
||||
|
||||
W ( X const& x ) : wrapped_(x) {}
|
||||
W ( TypedInPlaceFactory2 const& fac ) { fac.construct(&wrapped_) ; }
|
||||
} ;
|
||||
|
||||
void foo()
|
||||
{
|
||||
// Wrapped object constructed in-place via a TypedInPlaceFactory.
|
||||
// No temporary created.
|
||||
W ( TypedInPlaceFactory2<X,int,std::string>(123,"hello")) ;
|
||||
}
|
||||
|
||||
The factories are divided in two groups:
|
||||
|
||||
* [_TypedInPlaceFactories]: those which take the target type as a primary
|
||||
template parameter.
|
||||
* [_InPlaceFactories]: those with a template `construct(void*)` member
|
||||
function taking the target type.
|
||||
|
||||
Within each group, all the family members differ only in the number of
|
||||
parameters allowed.
|
||||
|
||||
This library provides an overloaded set of helper template functions to
|
||||
construct these factories without requiring unnecessary template parameters:
|
||||
|
||||
template<class A0,...,class AN>
|
||||
InPlaceFactoryN <A0,...,AN> in_place ( A0 const& a0, ..., AN const& aN) ;
|
||||
|
||||
template<class T,class A0,...,class AN>
|
||||
TypedInPlaceFactoryN <T,A0,...,AN> in_place ( T const& a0, A0 const& a0, ..., AN const& aN) ;
|
||||
|
||||
In-place factories can be used generically by the wrapper and user as follows:
|
||||
|
||||
class W
|
||||
{
|
||||
X wrapped_ ;
|
||||
|
||||
public:
|
||||
|
||||
W ( X const& x ) : wrapped_(x) {}
|
||||
|
||||
template< class InPlaceFactory >
|
||||
W ( InPlaceFactory const& fac ) { fac.template <X>construct(&wrapped_) ; }
|
||||
|
||||
} ;
|
||||
|
||||
void foo()
|
||||
{
|
||||
// Wrapped object constructed in-place via a InPlaceFactory.
|
||||
// No temporary created.
|
||||
W ( in_place(123,"hello") ) ;
|
||||
}
|
||||
|
||||
The factories are implemented in the headers: __IN_PLACE_FACTORY_HPP__ and __TYPED_IN_PLACE_FACTORY_HPP__
|
||||
|
||||
[endsect]
|
||||
|
||||
[section A note about optional<bool>]
|
||||
|
||||
`optional<bool>` should be used with special caution and consideration.
|
||||
|
||||
First, it is functionally similar to a tristate boolean (false,maybe,true)
|
||||
—such as __BOOST_TRIBOOL__— except that in a tristate boolean, the maybe state
|
||||
[_represents a valid value], unlike the corresponding state of an uninitialized
|
||||
`optional<bool>`.
|
||||
It should be carefully considered if an `optional<bool>` instead of a `tribool`
|
||||
is really needed.
|
||||
|
||||
Second, `optional<>` provides an implicit conversion to `bool`. This
|
||||
conversion refers to the initialization state and not to the contained value.
|
||||
Using `optional<bool>` can lead to subtle errors due to the implicit `bool`
|
||||
conversion:
|
||||
|
||||
void foo ( bool v ) ;
|
||||
void bar()
|
||||
{
|
||||
optional<bool> v = try();
|
||||
|
||||
// The following intended to pass the value of 'v' to foo():
|
||||
foo(v);
|
||||
// But instead, the initialization state is passed
|
||||
// due to a typo: it should have been foo(*v).
|
||||
}
|
||||
|
||||
The only implicit conversion is to `bool`, and it is safe in the sense that
|
||||
typical integral promotions don't apply (i.e. if `foo()` takes an `int`
|
||||
instead, it won't compile).
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Exception Safety Guarantees]
|
||||
|
||||
Because of the current implementation (see [link boost_optional.implementation_notes Implementation Notes]), all of the assignment methods:
|
||||
|
||||
* `optional<T>::operator= ( optional<T> const& )`
|
||||
* `optional<T>::operator= ( T const& )`
|
||||
* `template<class U> optional<T>::operator= ( optional<U> const& )`
|
||||
* `template<class InPlaceFactory> optional<T>::operator= ( InPlaceFactory const& )`
|
||||
* `template<class TypedInPlaceFactory> optional<T>::operator= ( TypedInPlaceFactory const& ) `
|
||||
* `optional<T>:::reset ( T const&)`
|
||||
|
||||
Can only ['guarantee] the [_basic exception safety]: The lvalue optional is
|
||||
left [_uninitialized] if an exception is thrown (any previous value is ['first]
|
||||
destroyed using `T::~T()`)
|
||||
|
||||
On the other hand, the ['uninitializing] methods:
|
||||
|
||||
* `optional<T>::operator= ( detail::none_t )`
|
||||
* `optional<T>::reset()`
|
||||
|
||||
Provide the no-throw guarantee (assuming a no-throw `T::~T()`)
|
||||
|
||||
However, since `optional<>` itself doesn't throw any exceptions, the only
|
||||
source for exceptions here are `T`'s constructor, so if you know the exception
|
||||
guarantees for `T::T ( T const& )`, you know that `optional`'s assignment and
|
||||
reset has the same guarantees.
|
||||
|
||||
//
|
||||
// Case 1: Exception thrown during assignment.
|
||||
//
|
||||
T v0(123);
|
||||
optional<T> opt0(v0);
|
||||
try
|
||||
{
|
||||
T v1(456);
|
||||
optional<T> opt1(v1);
|
||||
opt0 = opt1 ;
|
||||
|
||||
// If no exception was thrown, assignment succeeded.
|
||||
assert( *opt0 == v1 ) ;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
// If any exception was thrown, 'opt0' is reset to uninitialized.
|
||||
assert( !opt0 ) ;
|
||||
}
|
||||
|
||||
//
|
||||
// Case 2: Exception thrown during reset(v)
|
||||
//
|
||||
T v0(123);
|
||||
optional<T> opt(v0);
|
||||
try
|
||||
{
|
||||
T v1(456);
|
||||
opt.reset ( v1 ) ;
|
||||
|
||||
// If no exception was thrown, reset succeeded.
|
||||
assert( *opt == v1 ) ;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
// If any exception was thrown, 'opt' is reset to uninitialized.
|
||||
assert( !opt ) ;
|
||||
}
|
||||
|
||||
[heading Swap]
|
||||
|
||||
`void swap( optional<T>&, optional<T>& )` has the same exception guarantee
|
||||
as `swap(T&,T&)` when both optionals are initialized.
|
||||
If only one of the optionals is initialized, it gives the same ['basic]
|
||||
exception guarantee as `optional<T>::reset( T const& )` (since
|
||||
`optional<T>::reset()` doesn't throw).
|
||||
If none of the optionals is initialized, it has no-throw guarantee
|
||||
since it is a no-op.
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Type requirements]
|
||||
|
||||
In general, `T` must be __COPY_CONSTRUCTIBLE__ and have a no-throw destructor.
|
||||
The copy-constructible requirement is not needed if [*InPlaceFactories] are used.
|
||||
|
||||
`T` [_is not] required to be __SGI_DEFAULT_CONSTRUCTIBLE__.
|
||||
|
||||
[endsect]
|
||||
|
||||
|
28
include/boost/detail/none_t.hpp
Normal file
28
include/boost/detail/none_t.hpp
Normal file
@ -0,0 +1,28 @@
|
||||
// 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/libs/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// fernando_cacciola@hotmail.com
|
||||
//
|
||||
#ifndef BOOST_DETAIL_NONE_T_17SEP2003_HPP
|
||||
#define BOOST_DETAIL_NONE_T_17SEP2003_HPP
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace detail {
|
||||
|
||||
struct none_helper{};
|
||||
|
||||
typedef int none_helper::*none_t ;
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
|
28
include/boost/none.hpp
Normal file
28
include/boost/none.hpp
Normal file
@ -0,0 +1,28 @@
|
||||
// Copyright (C) 2003, Fernando Luis Cacciola Carballal.
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// fernando_cacciola@hotmail.com
|
||||
//
|
||||
#ifndef BOOST_NONE_17SEP2003_HPP
|
||||
#define BOOST_NONE_17SEP2003_HPP
|
||||
|
||||
#include "boost/none_t.hpp"
|
||||
|
||||
// NOTE: Borland users have to include this header outside any precompiled headers
|
||||
// (bcc<=5.64 cannot include instance data in a precompiled header)
|
||||
// -- * To be verified, now that there's no unnamed namespace
|
||||
|
||||
namespace boost {
|
||||
|
||||
none_t const none = (static_cast<none_t>(0)) ;
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
|
24
include/boost/none_t.hpp
Normal file
24
include/boost/none_t.hpp
Normal file
@ -0,0 +1,24 @@
|
||||
// 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/libs/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// fernando_cacciola@hotmail.com
|
||||
//
|
||||
#ifndef BOOST_NONE_T_17SEP2003_HPP
|
||||
#define BOOST_NONE_T_17SEP2003_HPP
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace detail { struct none_helper{}; }
|
||||
|
||||
typedef int detail::none_helper::*none_t ;
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
|
@ -1,15 +1,10 @@
|
||||
// (C) 2003, Fernando Luis Cacciola Carballal.
|
||||
// Copyright (C) 2003, Fernando Luis Cacciola Carballal.
|
||||
//
|
||||
// This material is provided "as is", with absolutely no warranty expressed
|
||||
// or implied. Any use is at your own risk.
|
||||
// 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)
|
||||
//
|
||||
// Permission to use or copy this software for any purpose is hereby granted
|
||||
// without fee, provided the above notices are retained on all copies.
|
||||
// Permission to modify the code and to distribute modified code is granted,
|
||||
// provided the above notices are retained, and a notice that the code was
|
||||
// modified is included with the above copyright notice.
|
||||
//
|
||||
// See http://www.boost.org/lib/optional for documentation.
|
||||
// See http://www.boost.org/libs/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// fernando_cacciola@hotmail.com
|
||||
@ -17,300 +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_traits/alignment_of.hpp"
|
||||
#include "boost/type_traits/type_with_alignment.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
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace optional_detail
|
||||
{
|
||||
template <class T>
|
||||
class aligned_storage
|
||||
{
|
||||
// Borland ICEs if unnamed unions are used for this!
|
||||
union dummy_u
|
||||
{
|
||||
char data[ sizeof(T) ];
|
||||
type_with_alignment< ::boost::alignment_of<T>::value > aligner_;
|
||||
} dummy_ ;
|
||||
|
||||
public:
|
||||
|
||||
void const* address() const { return &dummy_.data[0]; }
|
||||
void * address() { return &dummy_.data[0]; }
|
||||
} ;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
class optional
|
||||
{
|
||||
typedef optional<T> this_type ;
|
||||
|
||||
typedef optional_detail::aligned_storage<T> storage_type ;
|
||||
|
||||
typedef void (this_type::*unspecified_bool_type)();
|
||||
|
||||
public :
|
||||
|
||||
typedef T value_type ;
|
||||
|
||||
// Creates an optional<T> uninitialized.
|
||||
// No-throw
|
||||
optional ()
|
||||
:
|
||||
m_initialized(false) {}
|
||||
|
||||
// Creates an optional<T> initialized with 'val'.
|
||||
// Can throw if T::T(T const&) does
|
||||
explicit optional ( T const& val )
|
||||
:
|
||||
m_initialized(false)
|
||||
{
|
||||
construct(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 )
|
||||
:
|
||||
m_initialized(false)
|
||||
{
|
||||
if ( rhs )
|
||||
construct(*rhs);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Creates a deep copy of another optional<T>
|
||||
// Can throw if T::T(T const&) does
|
||||
optional ( optional const& rhs )
|
||||
:
|
||||
m_initialized(false)
|
||||
{
|
||||
if ( rhs )
|
||||
construct(*rhs);
|
||||
}
|
||||
|
||||
// No-throw (assuming T::~T() doesn't)
|
||||
~optional() { destroy() ; }
|
||||
|
||||
#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 )
|
||||
{
|
||||
destroy(); // no-throw
|
||||
|
||||
if ( rhs )
|
||||
{
|
||||
// An exception can be thrown here.
|
||||
// It it happens, THIS will be left uninitialized.
|
||||
construct(*rhs);
|
||||
}
|
||||
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
|
||||
optional& operator= ( optional const& rhs )
|
||||
{
|
||||
destroy(); // no-throw
|
||||
|
||||
if ( rhs )
|
||||
{
|
||||
// An exception can be thrown here.
|
||||
// It it happens, THIS will be left uninitialized.
|
||||
construct(*rhs);
|
||||
}
|
||||
return *this ;
|
||||
}
|
||||
|
||||
// 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 ( T const& val )
|
||||
{
|
||||
destroy();
|
||||
construct(val);
|
||||
}
|
||||
|
||||
// Returns a pointer to the value if this is initialized, otherwise,
|
||||
// returns NULL.
|
||||
// No-throw
|
||||
T const* get() const { return m_initialized ? static_cast<T const*>(m_storage.address()) : 0 ; }
|
||||
T* get() { return m_initialized ? static_cast<T*> (m_storage.address()) : 0 ; }
|
||||
|
||||
// Returns a pointer to the value if this is initialized, otherwise,
|
||||
// the behaviour is UNDEFINED
|
||||
// No-throw
|
||||
T const* operator->() const { BOOST_ASSERT(m_initialized) ; return static_cast<T const*>(m_storage.address()) ; }
|
||||
T* operator->() { BOOST_ASSERT(m_initialized) ; return static_cast<T*> (m_storage.address()) ; }
|
||||
|
||||
// Returns a reference to the value if this is initialized, otherwise,
|
||||
// the behaviour is UNDEFINED
|
||||
// No-throw
|
||||
T const& operator *() const { BOOST_ASSERT(m_initialized) ; return *static_cast<T const*>(m_storage.address()) ; }
|
||||
T& operator *() { BOOST_ASSERT(m_initialized) ; return *static_cast<T*> (m_storage.address()) ; }
|
||||
|
||||
// implicit conversion to "bool"
|
||||
// No-throw
|
||||
operator unspecified_bool_type() const { return m_initialized ? &this_type::destroy : 0 ; }
|
||||
|
||||
// This is provided for those compilers which don't like the conversion to bool
|
||||
// on some contexts.
|
||||
bool operator!() const { return !m_initialized ; }
|
||||
|
||||
private :
|
||||
|
||||
void construct ( T const& val )
|
||||
{
|
||||
new (m_storage.address()) T(val) ;
|
||||
m_initialized = true ;
|
||||
}
|
||||
|
||||
void destroy()
|
||||
{
|
||||
if ( m_initialized )
|
||||
{
|
||||
get()->~T() ;
|
||||
m_initialized = false ;
|
||||
}
|
||||
}
|
||||
|
||||
bool m_initialized ;
|
||||
storage_type m_storage ;
|
||||
} ;
|
||||
|
||||
// Returns a pointer to the value if this is initialized, otherwise, returns NULL.
|
||||
// No-throw
|
||||
template<class T>
|
||||
inline
|
||||
T const* get_pointer ( optional<T> const& opt )
|
||||
{
|
||||
return opt.get() ;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
T* get_pointer ( optional<T>& opt )
|
||||
{
|
||||
return opt.get() ;
|
||||
}
|
||||
|
||||
// template<class OP> bool equal_pointees(OP const& x, OP const& y);
|
||||
//
|
||||
// Being OP a model of OptionalPointee (either a pointer or an optional):
|
||||
//
|
||||
// If both x and y have valid pointees, returns the result of (*x == *y)
|
||||
// If only one has a valid pointee, returns false.
|
||||
// If none have valid pointees, returns true.
|
||||
// No-throw
|
||||
template<class OptionalPointee>
|
||||
inline
|
||||
bool equal_pointees ( OptionalPointee const& x, OptionalPointee const& y )
|
||||
{
|
||||
return (!x) != (!y) ? false : ( !x ? true : (*x) == (*y) ) ;
|
||||
}
|
||||
|
||||
// optional's operator == and != have deep-semantics (compare values).
|
||||
// WARNING: This is UNLIKE pointers. Use equal_pointees() 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 !( x == y ) ; }
|
||||
|
||||
|
||||
//
|
||||
// The following swap implementation follows the GCC workaround as found in
|
||||
// "boost/detail/compressed_pair.hpp"
|
||||
//
|
||||
namespace optional_detail {
|
||||
|
||||
#ifdef __GNUC__
|
||||
// workaround for GCC (JM):
|
||||
using std::swap;
|
||||
#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 )
|
||||
{
|
||||
#ifndef __GNUC__
|
||||
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
|
||||
|
||||
|
991
include/boost/optional/optional.hpp
Normal file
991
include/boost/optional/optional.hpp
Normal file
@ -0,0 +1,991 @@
|
||||
// Copyright (C) 2003, 2008 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/libs/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// fernando_cacciola@hotmail.com
|
||||
//
|
||||
// Revisions:
|
||||
// 27 Apr 2008 (improved swap) Fernando Cacciola, Niels Dekker, Thorsten Ottosen
|
||||
//
|
||||
#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/has_nothrow_constructor.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/none.hpp>
|
||||
#include <boost/utility/swap.hpp>
|
||||
#include <boost/utility/addressof.hpp>
|
||||
#include <boost/utility/compare_pointees.hpp>
|
||||
#include <boost/utility/in_place_factory.hpp>
|
||||
|
||||
#include <boost/optional/optional_fwd.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__, BOOST_TESTED_AT(0x581) )
|
||||
// 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
|
||||
|
||||
#if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) > 302 \
|
||||
&& !defined(__INTEL_COMPILER)
|
||||
// GCC since 3.3 has may_alias attribute that helps to alleviate optimizer issues with
|
||||
// regard to violation of the strict aliasing rules. The optional< T > storage type is marked
|
||||
// with this attribute in order to let the compiler know that it will alias objects of type T
|
||||
// and silence compilation warnings.
|
||||
#define BOOST_OPTIONAL_DETAIL_USE_ATTRIBUTE_MAY_ALIAS
|
||||
#endif
|
||||
|
||||
// Daniel Wallin discovered that bind/apply.hpp badly interacts with the apply<>
|
||||
// member template of a factory as used in the optional<> implementation.
|
||||
// He proposed this simple fix which is to move the call to apply<> outside
|
||||
// namespace boost.
|
||||
namespace boost_optional_detail
|
||||
{
|
||||
template <class T, class Factory>
|
||||
inline void construct(Factory const& factory, void* address)
|
||||
{
|
||||
factory.BOOST_NESTED_TEMPLATE apply<T>(address);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
namespace boost {
|
||||
|
||||
class in_place_factory_base ;
|
||||
class typed_in_place_factory_base ;
|
||||
|
||||
// This forward is needed to refer to namespace scope swap from the member swap
|
||||
template<class T> void swap ( optional<T>& x, optional<T>& y );
|
||||
|
||||
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
|
||||
// This works around GCC warnings about breaking strict aliasing rules when casting storage address to T*
|
||||
#if defined(BOOST_OPTIONAL_DETAIL_USE_ATTRIBUTE_MAY_ALIAS)
|
||||
__attribute__((may_alias))
|
||||
#endif
|
||||
dummy_u
|
||||
{
|
||||
char data[ sizeof(T) ];
|
||||
BOOST_DEDUCED_TYPENAME type_with_alignment<
|
||||
::boost::alignment_of<T>::value >::type aligner_;
|
||||
} dummy_ ;
|
||||
|
||||
public:
|
||||
|
||||
#if defined(BOOST_OPTIONAL_DETAIL_USE_ATTRIBUTE_MAY_ALIAS)
|
||||
void const* address() const { return &dummy_; }
|
||||
void * address() { return &dummy_; }
|
||||
#else
|
||||
void const* address() const { return dummy_.data; }
|
||||
void * address() { return dummy_.data; }
|
||||
#endif
|
||||
} ;
|
||||
|
||||
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
|
||||
#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
|
||||
BOOST_DEDUCED_TYPENAME
|
||||
#endif
|
||||
::boost::detail::make_reference_content<T>::type internal_type ;
|
||||
|
||||
typedef aligned_storage<internal_type> storage_type ;
|
||||
|
||||
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 ;
|
||||
|
||||
public:
|
||||
typedef BOOST_DEDUCED_TYPENAME mpl::if_<is_reference_predicate,types_when_ref,types_when_not_ref>::type types ;
|
||||
|
||||
protected:
|
||||
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 ( none_t )
|
||||
:
|
||||
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 an optional<T> initialized with 'val' IFF cond is true, otherwise creates an uninitialzed optional<T>.
|
||||
// Can throw if T::T(T const&) does
|
||||
optional_base ( bool cond, argument_type val )
|
||||
:
|
||||
m_initialized(false)
|
||||
{
|
||||
if ( cond )
|
||||
construct(val);
|
||||
}
|
||||
|
||||
// Creates a deep copy of another optional<T>
|
||||
// Can throw if T::T(T const&) does
|
||||
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)
|
||||
void assign ( optional_base const& rhs )
|
||||
{
|
||||
if (is_initialized())
|
||||
{
|
||||
if ( rhs.is_initialized() )
|
||||
assign_value(rhs.get_impl(), is_reference_predicate() );
|
||||
else destroy();
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( rhs.is_initialized() )
|
||||
construct(rhs.get_impl());
|
||||
}
|
||||
}
|
||||
|
||||
// Assigns from another _convertible_ optional<U> (deep-copies the rhs value)
|
||||
template<class U>
|
||||
void assign ( optional<U> const& rhs )
|
||||
{
|
||||
if (is_initialized())
|
||||
{
|
||||
if ( rhs.is_initialized() )
|
||||
assign_value(static_cast<value_type>(rhs.get()), is_reference_predicate() );
|
||||
else destroy();
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( rhs.is_initialized() )
|
||||
construct(static_cast<value_type>(rhs.get()));
|
||||
}
|
||||
}
|
||||
|
||||
// Assigns from a T (deep-copies the rhs value)
|
||||
void assign ( argument_type val )
|
||||
{
|
||||
if (is_initialized())
|
||||
assign_value(val, is_reference_predicate() );
|
||||
else construct(val);
|
||||
}
|
||||
|
||||
// Assigns from "none", destroying the current value, if any, leaving this UNINITIALIZED
|
||||
// No-throw (assuming T::~T() doesn't)
|
||||
void assign ( none_t ) { destroy(); }
|
||||
|
||||
#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
|
||||
template<class Expr>
|
||||
void assign_expr ( Expr const& expr, Expr const* tag )
|
||||
{
|
||||
if (is_initialized())
|
||||
assign_expr_to_initialized(expr,tag);
|
||||
else 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'
|
||||
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 ) ;
|
||||
boost_optional_detail::construct<value_type>(factory, 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 ;
|
||||
}
|
||||
|
||||
template<class Expr>
|
||||
void assign_expr_to_initialized ( Expr const& factory, in_place_factory_base const* tag )
|
||||
{
|
||||
destroy();
|
||||
construct(factory,tag);
|
||||
}
|
||||
|
||||
// Constructs in-place using the given typed factory
|
||||
template<class Expr>
|
||||
void assign_expr_to_initialized ( Expr const& factory, typed_in_place_factory_base const* tag )
|
||||
{
|
||||
destroy();
|
||||
construct(factory,tag);
|
||||
}
|
||||
#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 ;
|
||||
}
|
||||
|
||||
// Assigns using a form any expression implicitely convertible to the single argument
|
||||
// of a T's assignment operator.
|
||||
// Converting assignments of optional<T> from optional<U> uses this function with
|
||||
// 'Expr' being of type 'U' and relying on a converting assignment of T from U.
|
||||
template<class Expr>
|
||||
void assign_expr_to_initialized ( Expr const& expr, void const* )
|
||||
{
|
||||
assign_value(expr, is_reference_predicate());
|
||||
}
|
||||
|
||||
#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 assign_value ( argument_type val, is_not_reference_tag ) { get_impl() = val; }
|
||||
void assign_value ( argument_type val, is_reference_tag ) { construct(val); }
|
||||
|
||||
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>
|
||||
#if defined(BOOST_OPTIONAL_DETAIL_USE_ATTRIBUTE_MAY_ALIAS)
|
||||
// This workaround is supposed to silence GCC warnings about broken strict aliasing rules
|
||||
internal_type const* get_object() const
|
||||
{
|
||||
union { void const* ap_pvoid; internal_type const* as_ptype; } caster = { m_storage.address() };
|
||||
return caster.as_ptype;
|
||||
}
|
||||
internal_type * get_object()
|
||||
{
|
||||
union { void* ap_pvoid; internal_type* as_ptype; } caster = { m_storage.address() };
|
||||
return caster.as_ptype;
|
||||
}
|
||||
#else
|
||||
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()); }
|
||||
#endif
|
||||
|
||||
// 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__, BOOST_TESTED_AT(0x581))
|
||||
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 ; }
|
||||
pointer_const_type cast_ptr( internal_type const* p, is_reference_tag ) const { return &p->get() ; }
|
||||
pointer_type cast_ptr( internal_type * p, is_reference_tag ) { return &p->get() ; }
|
||||
|
||||
bool m_initialized ;
|
||||
storage_type m_storage ;
|
||||
} ;
|
||||
|
||||
} // 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( none_t none_ ) : base(none_) {}
|
||||
|
||||
// Creates an optional<T> initialized with 'val'.
|
||||
// Can throw if T::T(T const&) does
|
||||
optional ( argument_type val ) : base(val) {}
|
||||
|
||||
// Creates an optional<T> initialized with 'val' IFF cond is true, otherwise creates an uninitialized optional.
|
||||
// Can throw if T::T(T const&) does
|
||||
optional ( bool cond, argument_type val ) : base(cond,val) {}
|
||||
|
||||
#ifndef BOOST_OPTIONAL_NO_CONVERTING_COPY_CTOR
|
||||
// NOTE: MSVC needs templated versions first
|
||||
|
||||
// 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,boost::addressof(expr)) {}
|
||||
#endif
|
||||
|
||||
// Creates a deep copy of another optional<T>
|
||||
// Can throw if T::T(T const&) does
|
||||
optional ( optional const& rhs ) : base( static_cast<base const&>(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 const& expr )
|
||||
{
|
||||
this->assign_expr(expr,boost::addressof(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->assign(rhs);
|
||||
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( static_cast<base const&>(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= ( none_t none_ )
|
||||
{
|
||||
this->assign( none_ ) ;
|
||||
return *this ;
|
||||
}
|
||||
|
||||
void swap( optional & arg )
|
||||
{
|
||||
// allow for Koenig lookup
|
||||
using boost::swap;
|
||||
swap(*this, arg);
|
||||
}
|
||||
|
||||
|
||||
// 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 copy of the value if this is initialized, 'v' otherwise
|
||||
reference_const_type get_value_or ( reference_const_type v ) const { return this->is_initialized() ? get() : v ; }
|
||||
reference_type get_value_or ( reference_type v ) { return this->is_initialized() ? get() : v ; }
|
||||
|
||||
// Returns a pointer to the value if this is initialized, otherwise,
|
||||
// the behaviour is UNDEFINED
|
||||
// No-throw
|
||||
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 optional<T>(v)
|
||||
template<class T>
|
||||
inline
|
||||
optional<T> make_optional ( T const& v )
|
||||
{
|
||||
return optional<T>(v);
|
||||
}
|
||||
|
||||
// Returns optional<T>(cond,v)
|
||||
template<class T>
|
||||
inline
|
||||
optional<T> make_optional ( bool cond, T const& v )
|
||||
{
|
||||
return optional<T>(cond,v);
|
||||
}
|
||||
|
||||
// Returns a reference to the value if this is initialized, otherwise, the behaviour is UNDEFINED.
|
||||
// No-throw
|
||||
template<class T>
|
||||
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 reference to the value if this is initialized, otherwise, the behaviour is UNDEFINED.
|
||||
// No-throw
|
||||
template<class T>
|
||||
inline
|
||||
BOOST_DEDUCED_TYPENAME optional<T>::reference_const_type
|
||||
get_optional_value_or ( optional<T> const& opt, BOOST_DEDUCED_TYPENAME optional<T>::reference_const_type v )
|
||||
{
|
||||
return opt.get_value_or(v) ;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
BOOST_DEDUCED_TYPENAME optional<T>::reference_type
|
||||
get_optional_value_or ( optional<T>& opt, BOOST_DEDUCED_TYPENAME optional<T>::reference_type v )
|
||||
{
|
||||
return opt.get_value_or(v) ;
|
||||
}
|
||||
|
||||
// Returns a pointer to the value if this is initialized, otherwise, returns NULL.
|
||||
// No-throw
|
||||
template<class T>
|
||||
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.
|
||||
|
||||
|
||||
//
|
||||
// optional<T> vs optional<T> cases
|
||||
//
|
||||
|
||||
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 ) ; }
|
||||
|
||||
|
||||
//
|
||||
// optional<T> vs T cases
|
||||
//
|
||||
template<class T>
|
||||
inline
|
||||
bool operator == ( optional<T> const& x, T const& y )
|
||||
{ return equal_pointees(x, optional<T>(y)); }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator < ( optional<T> const& x, T const& y )
|
||||
{ return less_pointees(x, optional<T>(y)); }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator != ( optional<T> const& x, T const& y )
|
||||
{ return !( x == y ) ; }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator > ( optional<T> const& x, T const& y )
|
||||
{ return y < x ; }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator <= ( optional<T> const& x, T const& y )
|
||||
{ return !( y < x ) ; }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator >= ( optional<T> const& x, T const& y )
|
||||
{ return !( x < y ) ; }
|
||||
|
||||
//
|
||||
// T vs optional<T> cases
|
||||
//
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator == ( T const& x, optional<T> const& y )
|
||||
{ return equal_pointees( optional<T>(x), y ); }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator < ( T const& x, optional<T> const& y )
|
||||
{ return less_pointees( optional<T>(x), y ); }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator != ( T const& x, optional<T> const& y )
|
||||
{ return !( x == y ) ; }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator > ( T const& x, optional<T> const& y )
|
||||
{ return y < x ; }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator <= ( T const& x, optional<T> const& y )
|
||||
{ return !( y < x ) ; }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator >= ( T const& x, optional<T> const& y )
|
||||
{ return !( x < y ) ; }
|
||||
|
||||
|
||||
//
|
||||
// optional<T> vs none cases
|
||||
//
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator == ( optional<T> const& x, none_t )
|
||||
{ return equal_pointees(x, optional<T>() ); }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator < ( optional<T> const& x, none_t )
|
||||
{ return less_pointees(x,optional<T>() ); }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator != ( optional<T> const& x, none_t y )
|
||||
{ return !( x == y ) ; }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator > ( optional<T> const& x, none_t y )
|
||||
{ return y < x ; }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator <= ( optional<T> const& x, none_t y )
|
||||
{ return !( y < x ) ; }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator >= ( optional<T> const& x, none_t y )
|
||||
{ return !( x < y ) ; }
|
||||
|
||||
//
|
||||
// none vs optional<T> cases
|
||||
//
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator == ( none_t x, optional<T> const& y )
|
||||
{ return equal_pointees(optional<T>() ,y); }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator < ( none_t x, optional<T> const& y )
|
||||
{ return less_pointees(optional<T>() ,y); }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator != ( none_t x, optional<T> const& y )
|
||||
{ return !( x == y ) ; }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator > ( none_t x, optional<T> const& y )
|
||||
{ return y < x ; }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator <= ( none_t x, optional<T> const& y )
|
||||
{ return !( y < x ) ; }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator >= ( none_t x, optional<T> const& y )
|
||||
{ return !( x < y ) ; }
|
||||
|
||||
namespace optional_detail {
|
||||
|
||||
template<bool use_default_constructor> struct swap_selector;
|
||||
|
||||
template<>
|
||||
struct swap_selector<true>
|
||||
{
|
||||
template<class T>
|
||||
static void optional_swap ( optional<T>& x, optional<T>& y )
|
||||
{
|
||||
const bool hasX = !!x;
|
||||
const bool hasY = !!y;
|
||||
|
||||
if ( !hasX && !hasY )
|
||||
return;
|
||||
|
||||
if( !hasX )
|
||||
x = boost::in_place();
|
||||
else if ( !hasY )
|
||||
y = boost::in_place();
|
||||
|
||||
// Boost.Utility.Swap will take care of ADL and workarounds for broken compilers
|
||||
boost::swap(x.get(),y.get());
|
||||
|
||||
if( !hasX )
|
||||
y = boost::none ;
|
||||
else if( !hasY )
|
||||
x = boost::none ;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct swap_selector<false>
|
||||
{
|
||||
template<class T>
|
||||
static void optional_swap ( optional<T>& x, optional<T>& y )
|
||||
{
|
||||
const bool hasX = !!x;
|
||||
const bool hasY = !!y;
|
||||
|
||||
if ( !hasX && hasY )
|
||||
{
|
||||
x = y.get();
|
||||
y = boost::none ;
|
||||
}
|
||||
else if ( hasX && !hasY )
|
||||
{
|
||||
y = x.get();
|
||||
x = boost::none ;
|
||||
}
|
||||
else if ( hasX && hasY )
|
||||
{
|
||||
// Boost.Utility.Swap will take care of ADL and workarounds for broken compilers
|
||||
boost::swap(x.get(),y.get());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace optional_detail
|
||||
|
||||
template<class T>
|
||||
struct optional_swap_should_use_default_constructor : has_nothrow_default_constructor<T> {} ;
|
||||
|
||||
template<class T> inline void swap ( optional<T>& x, optional<T>& y )
|
||||
{
|
||||
optional_detail::swap_selector<optional_swap_should_use_default_constructor<T>::value>::optional_swap(x, y);
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
29
include/boost/optional/optional_fwd.hpp
Normal file
29
include/boost/optional/optional_fwd.hpp
Normal file
@ -0,0 +1,29 @@
|
||||
// Copyright (C) 2003, 2008 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/libs/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// fernando_cacciola@hotmail.com
|
||||
//
|
||||
// Revisions:
|
||||
// 10 May 2008 (added swap related forward declaration) Niels Dekker
|
||||
//
|
||||
#ifndef BOOST_OPTIONAL_OPTIONAL_FWD_FLC_19NOV2002_HPP
|
||||
#define BOOST_OPTIONAL_OPTIONAL_FWD_FLC_19NOV2002_HPP
|
||||
|
||||
namespace boost {
|
||||
|
||||
template<class T> class optional ;
|
||||
|
||||
template<class T> void swap ( optional<T>& , optional<T>& ) ;
|
||||
|
||||
template<class T> struct optional_swap_should_use_default_constructor ;
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
|
98
include/boost/optional/optional_io.hpp
Normal file
98
include/boost/optional/optional_io.hpp
Normal file
@ -0,0 +1,98 @@
|
||||
// Copyright (C) 2005, 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/libs/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// fernando_cacciola@hotmail.com
|
||||
//
|
||||
#ifndef BOOST_OPTIONAL_OPTIONAL_IO_FLC_19NOV2002_HPP
|
||||
#define BOOST_OPTIONAL_OPTIONAL_IO_FLC_19NOV2002_HPP
|
||||
|
||||
#if defined __GNUC__
|
||||
# if (__GNUC__ == 2 && __GNUC_MINOR__ <= 97)
|
||||
# define BOOST_OPTIONAL_NO_TEMPLATED_STREAMS
|
||||
# endif
|
||||
#endif // __GNUC__
|
||||
|
||||
#if defined BOOST_OPTIONAL_NO_TEMPLATED_STREAMS
|
||||
# include <iostream>
|
||||
#else
|
||||
# include <istream>
|
||||
# include <ostream>
|
||||
#endif
|
||||
|
||||
#include <boost/none.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include "boost/optional/optional.hpp"
|
||||
#include "boost/utility/value_init.hpp"
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
#if defined (BOOST_NO_TEMPLATED_STREAMS)
|
||||
template<class T>
|
||||
inline std::ostream& operator<<(std::ostream& out, optional<T> const& v)
|
||||
#else
|
||||
template<class CharType, class CharTrait, class T>
|
||||
inline
|
||||
std::basic_ostream<CharType, CharTrait>&
|
||||
operator<<(std::basic_ostream<CharType, CharTrait>& out, optional<T> const& v)
|
||||
#endif
|
||||
{
|
||||
if ( out.good() )
|
||||
{
|
||||
if ( !v )
|
||||
out << "--" ;
|
||||
else out << ' ' << *v ;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
#if defined (BOOST_NO_TEMPLATED_STREAMS)
|
||||
template<class T>
|
||||
inline std::istream& operator>>(std::istream& in, optional<T>& v)
|
||||
#else
|
||||
template<class CharType, class CharTrait, class T>
|
||||
inline
|
||||
std::basic_istream<CharType, CharTrait>&
|
||||
operator>>(std::basic_istream<CharType, CharTrait>& in, optional<T>& v)
|
||||
#endif
|
||||
{
|
||||
if (in.good())
|
||||
{
|
||||
int d = in.get();
|
||||
if (d == ' ')
|
||||
{
|
||||
T x;
|
||||
in >> x;
|
||||
v = x;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (d == '-')
|
||||
{
|
||||
d = in.get();
|
||||
|
||||
if (d == '-')
|
||||
{
|
||||
v = none;
|
||||
return in;
|
||||
}
|
||||
}
|
||||
|
||||
in.setstate( std::ios::failbit );
|
||||
}
|
||||
}
|
||||
|
||||
return in;
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
|
10
index.html
10
index.html
@ -1,9 +1,13 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="refresh" content="0; URL=doc/optional.html">
|
||||
<meta http-equiv="refresh" content="0; URL=doc/html/index.html">
|
||||
</head>
|
||||
<body>
|
||||
Automatic redirection failed, please go to
|
||||
<a href="doc/optional.html">doc/optional.html</a>.
|
||||
<a href="doc/html/index.html">doc/html/index.html</a>. <hr>
|
||||
<p><EFBFBD> Copyright Beman Dawes, 2001</p>
|
||||
<p>Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or copy
|
||||
at <a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a>)</p>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
@ -1 +0,0 @@
|
||||
bin
|
37
test/Jamfile
37
test/Jamfile
@ -1,37 +0,0 @@
|
||||
# Boost.Optional Library test Jamfile
|
||||
#
|
||||
# Copyright (C) 2003, Fernando Luis Cacciola Carballal.
|
||||
#
|
||||
# This material is provided "as is", with absolutely no warranty expressed
|
||||
# or implied. Any use is at your own risk.
|
||||
#
|
||||
# Permission to use or copy this software for any purpose is hereby granted
|
||||
# without fee, provided the above notices are retained on all copies.
|
||||
# Permission to modify the code and to distribute modified code is granted,
|
||||
# provided the above notices are retained, and a notice that the code was
|
||||
# modified is included with the above copyright notice.
|
||||
#
|
||||
|
||||
subproject libs/optional/test ;
|
||||
|
||||
# bring in rules for testing
|
||||
SEARCH on testing.jam = $(BOOST_BUILD_PATH) ;
|
||||
include testing.jam ;
|
||||
|
||||
# Make tests run by default.
|
||||
DEPENDS all : test ;
|
||||
|
||||
{
|
||||
# look in BOOST_ROOT for sources first, just in this Jamfile
|
||||
local SEARCH_SOURCE = $(BOOST_ROOT) $(SEARCH_SOURCE) ;
|
||||
|
||||
test-suite optional :
|
||||
[ run libs/optional/test/optional_test.cpp ]
|
||||
[ compile-fail libs/optional/test/optional_test_fail1.cpp ]
|
||||
[ compile-fail libs/optional/test/optional_test_fail2.cpp ]
|
||||
[ compile-fail libs/optional/test/optional_test_fail3.cpp ]
|
||||
[ compile-fail libs/optional/test/optional_test_fail4.cpp ]
|
||||
[ compile-fail libs/optional/test/optional_test_fail5a.cpp ]
|
||||
[ compile-fail libs/optional/test/optional_test_fail5b.cpp ]
|
||||
;
|
||||
}
|
33
test/Jamfile.v2
Normal file
33
test/Jamfile.v2
Normal file
@ -0,0 +1,33 @@
|
||||
# Boost.Optional Library test Jamfile
|
||||
#
|
||||
# Copyright (C) 2003, Fernando Luis Cacciola Carballal.
|
||||
#
|
||||
# This material is provided "as is", with absolutely no warranty expressed
|
||||
# or implied. Any use is at your own risk.
|
||||
#
|
||||
# Permission to use or copy this software for any purpose is hereby granted
|
||||
# without fee, provided the above notices are retained on all copies.
|
||||
# Permission to modify the code and to distribute modified code is granted,
|
||||
# provided the above notices are retained, and a notice that the code was
|
||||
# modified is included with the above copyright notice.
|
||||
#
|
||||
|
||||
import testing ;
|
||||
|
||||
{
|
||||
test-suite optional :
|
||||
[ run optional_test.cpp ]
|
||||
[ run optional_test_tie.cpp ]
|
||||
[ run optional_test_ref.cpp ]
|
||||
[ run optional_test_inplace.cpp ]
|
||||
[ run optional_test_io.cpp ]
|
||||
[ compile-fail optional_test_fail1.cpp ]
|
||||
[ compile-fail optional_test_fail3a.cpp ]
|
||||
[ compile-fail optional_test_fail3b.cpp ]
|
||||
[ compile-fail optional_test_ref_fail1.cpp ]
|
||||
[ compile-fail optional_test_ref_fail3.cpp ]
|
||||
[ compile-fail optional_test_ref_fail4.cpp ]
|
||||
[ compile-fail optional_test_inplace_fail.cpp ]
|
||||
[ compile-fail optional_test_inplace_fail2.cpp ]
|
||||
;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
267
test/optional_test_common.cpp
Normal file
267
test/optional_test_common.cpp
Normal file
@ -0,0 +1,267 @@
|
||||
// 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
|
||||
//
|
||||
#ifdef ENABLE_TRACE
|
||||
#define TRACE(msg) std::cout << msg << std::endl ;
|
||||
#else
|
||||
#define TRACE(msg)
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
|
||||
void assertion_failed (char const * expr, char const * func, char const * file, long )
|
||||
{
|
||||
using std::string ;
|
||||
string msg = string("Boost assertion failure for \"")
|
||||
+ string(expr)
|
||||
+ string("\" at file \"")
|
||||
+ string(file)
|
||||
+ string("\" function \"")
|
||||
+ string(func)
|
||||
+ string("\"") ;
|
||||
|
||||
TRACE(msg);
|
||||
|
||||
throw std::logic_error(msg);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
using boost::optional ;
|
||||
|
||||
template<class T> inline void unused_variable ( T ) {}
|
||||
|
||||
#ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
|
||||
using boost::swap ;
|
||||
using boost::get ;
|
||||
using boost::get_pointer ;
|
||||
#endif
|
||||
|
||||
// MSVC6.0 does not support comparisons of optional against a literal null pointer value (0)
|
||||
// via the safe_bool operator.
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1300) ) // 1300 == VC++ 7.1
|
||||
#define BOOST_OPTIONAL_NO_NULL_COMPARE
|
||||
#endif
|
||||
|
||||
#define ARG(T) (static_cast< T const* >(0))
|
||||
|
||||
//
|
||||
// Helper class used to verify the lifetime managment of the values held by optional
|
||||
//
|
||||
class X
|
||||
{
|
||||
public :
|
||||
|
||||
X ( int av ) : v(av)
|
||||
{
|
||||
++ count ;
|
||||
|
||||
TRACE ( "X::X(" << av << "). this=" << this ) ;
|
||||
}
|
||||
|
||||
X ( X const& rhs ) : v(rhs.v)
|
||||
{
|
||||
pending_copy = false ;
|
||||
|
||||
TRACE ( "X::X( X const& rhs). this=" << this << " rhs.v=" << rhs.v ) ;
|
||||
|
||||
if ( throw_on_copy )
|
||||
{
|
||||
TRACE ( "throwing exception in X's copy ctor" ) ;
|
||||
throw 0 ;
|
||||
}
|
||||
|
||||
++ count ;
|
||||
}
|
||||
|
||||
~X()
|
||||
{
|
||||
pending_dtor = false ;
|
||||
|
||||
-- count ;
|
||||
|
||||
TRACE ( "X::~X(). v=" << v << " this=" << this );
|
||||
}
|
||||
|
||||
X& operator= ( X const& rhs )
|
||||
{
|
||||
pending_assign = false ;
|
||||
|
||||
if ( throw_on_assign )
|
||||
{
|
||||
TRACE ( "throwing exception in X's assignment" ) ;
|
||||
|
||||
v = -1 ;
|
||||
|
||||
throw 0 ;
|
||||
}
|
||||
else
|
||||
{
|
||||
v = rhs.v ;
|
||||
|
||||
TRACE ( "X::operator =( X const& rhs). this=" << this << " rhs.v=" << rhs.v ) ;
|
||||
}
|
||||
return *this ;
|
||||
}
|
||||
|
||||
friend bool operator == ( X const& a, X const& b )
|
||||
{ return a.v == b.v ; }
|
||||
|
||||
friend bool operator != ( X const& a, X const& b )
|
||||
{ return a.v != b.v ; }
|
||||
|
||||
friend bool operator < ( X const& a, X const& b )
|
||||
{ return a.v < b.v ; }
|
||||
|
||||
int V() const { return v ; }
|
||||
int& V() { return v ; }
|
||||
|
||||
static int count ;
|
||||
static bool pending_copy ;
|
||||
static bool pending_dtor ;
|
||||
static bool pending_assign ;
|
||||
static bool throw_on_copy ;
|
||||
static bool throw_on_assign ;
|
||||
|
||||
private :
|
||||
|
||||
int v ;
|
||||
|
||||
private :
|
||||
|
||||
X() ;
|
||||
} ;
|
||||
|
||||
|
||||
int X::count = 0 ;
|
||||
bool X::pending_copy = false ;
|
||||
bool X::pending_dtor = false ;
|
||||
bool X::pending_assign = false ;
|
||||
bool X::throw_on_copy = false ;
|
||||
bool X::throw_on_assign = false ;
|
||||
|
||||
inline void set_pending_copy ( X const* x ) { X::pending_copy = true ; }
|
||||
inline void set_pending_dtor ( X const* x ) { X::pending_dtor = true ; }
|
||||
inline void set_pending_assign ( X const* x ) { X::pending_assign = true ; }
|
||||
inline void set_throw_on_copy ( X const* x ) { X::throw_on_copy = true ; }
|
||||
inline void set_throw_on_assign ( X const* x ) { X::throw_on_assign = true ; }
|
||||
inline void reset_throw_on_copy ( X const* x ) { X::throw_on_copy = false ; }
|
||||
inline void reset_throw_on_assign ( X const* x ) { X::throw_on_assign = false ; }
|
||||
inline void check_is_pending_copy ( X const* x ) { BOOST_CHECK( X::pending_copy ) ; }
|
||||
inline void check_is_pending_dtor ( X const* x ) { BOOST_CHECK( X::pending_dtor ) ; }
|
||||
inline void check_is_pending_assign ( X const* x ) { BOOST_CHECK( X::pending_assign ) ; }
|
||||
inline void check_is_not_pending_copy ( X const* x ) { BOOST_CHECK( !X::pending_copy ) ; }
|
||||
inline void check_is_not_pending_dtor ( X const* x ) { BOOST_CHECK( !X::pending_dtor ) ; }
|
||||
inline void check_is_not_pending_assign( X const* x ) { BOOST_CHECK( !X::pending_assign ) ; }
|
||||
inline void check_instance_count ( int c, X const* x ) { BOOST_CHECK( X::count == c ) ; }
|
||||
inline int get_instance_count ( X const* x ) { return X::count ; }
|
||||
|
||||
inline void set_pending_copy (...) {}
|
||||
inline void set_pending_dtor (...) {}
|
||||
inline void set_pending_assign (...) {}
|
||||
inline void set_throw_on_copy (...) {}
|
||||
inline void set_throw_on_assign (...) {}
|
||||
inline void reset_throw_on_copy (...) {}
|
||||
inline void reset_throw_on_assign (...) {}
|
||||
inline void check_is_pending_copy (...) {}
|
||||
inline void check_is_pending_dtor (...) {}
|
||||
inline void check_is_pending_assign (...) {}
|
||||
inline void check_is_not_pending_copy (...) {}
|
||||
inline void check_is_not_pending_dtor (...) {}
|
||||
inline void check_is_not_pending_assign(...) {}
|
||||
inline void check_instance_count (...) {}
|
||||
inline int get_instance_count (...) { return 0 ; }
|
||||
|
||||
|
||||
template<class T>
|
||||
inline void check_uninitialized_const ( optional<T> const& opt )
|
||||
{
|
||||
#ifndef BOOST_OPTIONAL_NO_NULL_COMPARE
|
||||
BOOST_CHECK( opt == 0 ) ;
|
||||
#endif
|
||||
BOOST_CHECK( !opt ) ;
|
||||
BOOST_CHECK( !get_pointer(opt) ) ;
|
||||
BOOST_CHECK( !opt.get_ptr() ) ;
|
||||
}
|
||||
template<class T>
|
||||
inline void check_uninitialized ( optional<T>& opt )
|
||||
{
|
||||
#ifndef BOOST_OPTIONAL_NO_NULL_COMPARE
|
||||
BOOST_CHECK( opt == 0 ) ;
|
||||
#endif
|
||||
BOOST_CHECK( !opt ) ;
|
||||
BOOST_CHECK( !get_pointer(opt) ) ;
|
||||
BOOST_CHECK( !opt.get_ptr() ) ;
|
||||
|
||||
check_uninitialized_const(opt);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline void check_initialized_const ( optional<T> const& opt )
|
||||
{
|
||||
BOOST_CHECK( opt ) ;
|
||||
|
||||
#ifndef BOOST_OPTIONAL_NO_NULL_COMPARE
|
||||
BOOST_CHECK( opt != 0 ) ;
|
||||
#endif
|
||||
|
||||
BOOST_CHECK ( !!opt ) ;
|
||||
BOOST_CHECK ( get_pointer(opt) ) ;
|
||||
BOOST_CHECK ( opt.get_ptr() ) ;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline void check_initialized ( optional<T>& opt )
|
||||
{
|
||||
BOOST_CHECK( opt ) ;
|
||||
|
||||
#ifndef BOOST_OPTIONAL_NO_NULL_COMPARE
|
||||
BOOST_CHECK( opt != 0 ) ;
|
||||
#endif
|
||||
|
||||
BOOST_CHECK ( !!opt ) ;
|
||||
BOOST_CHECK ( get_pointer(opt) ) ;
|
||||
BOOST_CHECK ( opt.get_ptr() ) ;
|
||||
|
||||
check_initialized_const(opt);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline void check_value_const ( optional<T> const& opt, T const& v, T const& z )
|
||||
{
|
||||
BOOST_CHECK( *opt == v ) ;
|
||||
BOOST_CHECK( *opt != z ) ;
|
||||
BOOST_CHECK( opt.get() == v ) ;
|
||||
BOOST_CHECK( opt.get() != z ) ;
|
||||
BOOST_CHECK( (*(opt.operator->()) == v) ) ;
|
||||
BOOST_CHECK( *get_pointer(opt) == v ) ;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline void check_value ( optional<T>& opt, T const& v, T const& z )
|
||||
{
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, <= 1200) // 1200 == VC++ 6.0
|
||||
// For some reason, VC6.0 is creating a temporary while evaluating (*opt == v),
|
||||
// so we need to turn throw on copy off first.
|
||||
reset_throw_on_copy( ARG(T) ) ;
|
||||
#endif
|
||||
|
||||
BOOST_CHECK( *opt == v ) ;
|
||||
BOOST_CHECK( *opt != z ) ;
|
||||
BOOST_CHECK( opt.get() == v ) ;
|
||||
BOOST_CHECK( opt.get() != z ) ;
|
||||
BOOST_CHECK( (*(opt.operator->()) == v) ) ;
|
||||
BOOST_CHECK( *get_pointer(opt) == v ) ;
|
||||
|
||||
check_value_const(opt,v,z);
|
||||
}
|
||||
|
||||
|
@ -1,13 +1,10 @@
|
||||
// (C) 2003, Fernando Luis Cacciola Carballal.
|
||||
// Copyright (C) 2003, Fernando Luis Cacciola Carballal.
|
||||
//
|
||||
// This material is provided "as is", with absolutely no warranty expressed
|
||||
// or implied. Any use is at your own risk.
|
||||
// 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)
|
||||
//
|
||||
// Permission to use or copy this software for any purpose is hereby granted
|
||||
// without fee, provided the above notices are retained on all copies.
|
||||
// Permission to modify the code and to distribute modified code is granted,
|
||||
// provided the above notices are retained, and a notice that the code was
|
||||
// modified is included with the above copyright notice.
|
||||
// See http://www.boost.org/lib/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// fernando_cacciola@hotmail.com
|
||||
|
@ -1,13 +1,10 @@
|
||||
// (C) 2003, Fernando Luis Cacciola Carballal.
|
||||
// Copyright (C) 2003, Fernando Luis Cacciola Carballal.
|
||||
//
|
||||
// This material is provided "as is", with absolutely no warranty expressed
|
||||
// or implied. Any use is at your own risk.
|
||||
// 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)
|
||||
//
|
||||
// Permission to use or copy this software for any purpose is hereby granted
|
||||
// without fee, provided the above notices are retained on all copies.
|
||||
// Permission to modify the code and to distribute modified code is granted,
|
||||
// provided the above notices are retained, and a notice that the code was
|
||||
// modified is included with the above copyright notice.
|
||||
// See http://www.boost.org/lib/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// fernando_cacciola@hotmail.com
|
||||
@ -17,10 +14,13 @@
|
||||
//
|
||||
// THIS TEST SHOULD FAIL TO COMPILE
|
||||
//
|
||||
void test_no_direct_value_assignment()
|
||||
void test_no_implicit_conversion()
|
||||
{
|
||||
boost::optional<int> opt(3) ;
|
||||
opt = 4 ; // Cannot assign "int" to "optional<int>"
|
||||
boost::optional<int> opt(1) ;
|
||||
|
||||
// You can compare against 0 or against another optional<>,
|
||||
// but not against another value
|
||||
if ( opt == 1 ) ;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,13 +1,10 @@
|
||||
// (C) 2003, Fernando Luis Cacciola Carballal.
|
||||
// Copyright (C) 2003, Fernando Luis Cacciola Carballal.
|
||||
//
|
||||
// This material is provided "as is", with absolutely no warranty expressed
|
||||
// or implied. Any use is at your own risk.
|
||||
// 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)
|
||||
//
|
||||
// Permission to use or copy this software for any purpose is hereby granted
|
||||
// without fee, provided the above notices are retained on all copies.
|
||||
// Permission to modify the code and to distribute modified code is granted,
|
||||
// provided the above notices are retained, and a notice that the code was
|
||||
// modified is included with the above copyright notice.
|
||||
// See http://www.boost.org/lib/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// fernando_cacciola@hotmail.com
|
||||
|
25
test/optional_test_fail3a.cpp
Normal file
25
test/optional_test_fail3a.cpp
Normal file
@ -0,0 +1,25 @@
|
||||
// Copyright (C) 2003, Fernando Luis Cacciola Carballal.
|
||||
//
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/lib/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// fernando_cacciola@hotmail.com
|
||||
//
|
||||
#include<string>
|
||||
|
||||
#include "boost/optional.hpp"
|
||||
|
||||
//
|
||||
// THIS TEST SHOULD FAIL TO COMPILE
|
||||
//
|
||||
void test_no_unsupported_conversion()
|
||||
{
|
||||
boost::optional<int> opt1(1) ;
|
||||
boost::optional< std::string > opt2( opt1 ) ; // Cannot convert from "int" to "std::string"
|
||||
}
|
||||
|
||||
|
28
test/optional_test_fail3b.cpp
Normal file
28
test/optional_test_fail3b.cpp
Normal file
@ -0,0 +1,28 @@
|
||||
// Copyright (C) 2003, Fernando Luis Cacciola Carballal.
|
||||
//
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/lib/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// fernando_cacciola@hotmail.com
|
||||
//
|
||||
#include<string>
|
||||
|
||||
#include "boost/optional.hpp"
|
||||
|
||||
struct A {} ;
|
||||
struct B {} ;
|
||||
//
|
||||
// THIS TEST SHOULD FAIL TO COMPILE
|
||||
//
|
||||
void test_no_unsupported_conversion()
|
||||
{
|
||||
boost::optional<A> opt1;
|
||||
boost::optional<B> opt2;
|
||||
opt2 = opt1 ; // Cannot convert from "A" to "B"
|
||||
}
|
||||
|
||||
|
@ -1,29 +0,0 @@
|
||||
// (C) 2003, Fernando Luis Cacciola Carballal.
|
||||
//
|
||||
// This material is provided "as is", with absolutely no warranty expressed
|
||||
// or implied. Any use is at your own risk.
|
||||
//
|
||||
// Permission to use or copy this software for any purpose is hereby granted
|
||||
// without fee, provided the above notices are retained on all copies.
|
||||
// Permission to modify the code and to distribute modified code is granted,
|
||||
// provided the above notices are retained, and a notice that the code was
|
||||
// modified is included with the above copyright notice.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// fernando_cacciola@hotmail.com
|
||||
//
|
||||
#include "boost/optional.hpp"
|
||||
|
||||
//
|
||||
// THIS TEST SHOULD FAIL TO COMPILE
|
||||
//
|
||||
void test_no_implicit_conversion()
|
||||
{
|
||||
boost::optional<int> opt(1) ;
|
||||
|
||||
// You can compare against 0 or against another optional<>,
|
||||
// but not against another value
|
||||
if ( opt == 1 ) ;
|
||||
}
|
||||
|
||||
|
@ -1,28 +0,0 @@
|
||||
// (C) 2003, Fernando Luis Cacciola Carballal.
|
||||
//
|
||||
// This material is provided "as is", with absolutely no warranty expressed
|
||||
// or implied. Any use is at your own risk.
|
||||
//
|
||||
// Permission to use or copy this software for any purpose is hereby granted
|
||||
// without fee, provided the above notices are retained on all copies.
|
||||
// Permission to modify the code and to distribute modified code is granted,
|
||||
// provided the above notices are retained, and a notice that the code was
|
||||
// modified is included with the above copyright notice.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// fernando_cacciola@hotmail.com
|
||||
//
|
||||
#include<string>
|
||||
|
||||
#include "boost/optional.hpp"
|
||||
|
||||
//
|
||||
// THIS TEST SHOULD FAIL TO COMPILE
|
||||
//
|
||||
void test_no_unsupported_conversion()
|
||||
{
|
||||
boost::optional<int> opt1(1) ;
|
||||
boost::optional< std::string > opt2( opt1 ) ; // Cannot convert from "int" to "std::string"
|
||||
}
|
||||
|
||||
|
@ -1,29 +0,0 @@
|
||||
// (C) 2003, Fernando Luis Cacciola Carballal.
|
||||
//
|
||||
// This material is provided "as is", with absolutely no warranty expressed
|
||||
// or implied. Any use is at your own risk.
|
||||
//
|
||||
// Permission to use or copy this software for any purpose is hereby granted
|
||||
// without fee, provided the above notices are retained on all copies.
|
||||
// Permission to modify the code and to distribute modified code is granted,
|
||||
// provided the above notices are retained, and a notice that the code was
|
||||
// modified is included with the above copyright notice.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// fernando_cacciola@hotmail.com
|
||||
//
|
||||
#include<string>
|
||||
|
||||
#include "boost/optional.hpp"
|
||||
|
||||
//
|
||||
// THIS TEST SHOULD FAIL TO COMPILE
|
||||
//
|
||||
void test_no_unsupported_conversion()
|
||||
{
|
||||
boost::optional<int> opt1(1) ;
|
||||
boost::optional< std::string > opt2 ;
|
||||
opt2 = opt1 ; // Cannot convert from "int" to "std::string"
|
||||
}
|
||||
|
||||
|
84
test/optional_test_inplace.cpp
Normal file
84
test/optional_test_inplace.cpp
Normal file
@ -0,0 +1,84 @@
|
||||
// Copyright (C) 2003, Fernando Luis Cacciola Carballal.
|
||||
//
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/lib/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// fernando_cacciola@hotmail.com
|
||||
//
|
||||
#include<iostream>
|
||||
#include<stdexcept>
|
||||
#include<string>
|
||||
|
||||
#define BOOST_ENABLE_ASSERT_HANDLER
|
||||
|
||||
#include "boost/optional/optional.hpp"
|
||||
|
||||
#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
|
||||
#include "boost/utility/in_place_factory.hpp"
|
||||
#include "boost/utility/typed_in_place_factory.hpp"
|
||||
#endif
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#include "boost/test/minimal.hpp"
|
||||
|
||||
#include "optional_test_common.cpp"
|
||||
|
||||
#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
|
||||
struct A
|
||||
{
|
||||
A ( double a0, std::string a1 ) : m_a0(a0), m_a1(a1) {}
|
||||
|
||||
friend bool operator == ( A const& x, A const& y )
|
||||
{ return x.m_a0 == y.m_a0 && x.m_a1 == y.m_a1 ; }
|
||||
|
||||
double m_a0 ;
|
||||
std::string m_a1 ;
|
||||
} ;
|
||||
|
||||
int test_main( int, char* [] )
|
||||
{
|
||||
double a00 = 3.14, a10 = 6.02e-23;
|
||||
std::string a01("pi"), a11("mol");
|
||||
|
||||
A a0(a00,a01);
|
||||
A a1(a10,a11);
|
||||
|
||||
boost::optional<A> opt1(a0);
|
||||
|
||||
boost::optional<A> opt2 ( boost::in_place(a00,a01) ) ;
|
||||
|
||||
boost::optional<A> opt3 ( boost::in_place<A>(a00,a01) ) ;
|
||||
|
||||
BOOST_CHECK( opt1 == opt2 ) ;
|
||||
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
|
||||
int test_main( int, char* [] )
|
||||
{
|
||||
// If in-place factories are not supported there is nothing to test
|
||||
return 0 ;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
60
test/optional_test_inplace_fail.cpp
Normal file
60
test/optional_test_inplace_fail.cpp
Normal file
@ -0,0 +1,60 @@
|
||||
// Copyright (C) 2003, Fernando Luis Cacciola Carballal.
|
||||
//
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/lib/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// fernando_cacciola@hotmail.com
|
||||
//
|
||||
#include<iostream>
|
||||
#include<stdexcept>
|
||||
#include<string>
|
||||
|
||||
#define BOOST_ENABLE_ASSERT_HANDLER
|
||||
|
||||
#include "boost/optional/optional.hpp"
|
||||
|
||||
#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
|
||||
#include "boost/utility/in_place_factory.hpp"
|
||||
#endif
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#include "boost/test/minimal.hpp"
|
||||
|
||||
#include "optional_test_common.cpp"
|
||||
|
||||
#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
|
||||
struct A
|
||||
{
|
||||
A ( double a0, std::string a1 ) : m_a0(a0), m_a1(a1) {}
|
||||
|
||||
friend bool operator == ( A const& x, A const& y )
|
||||
{ return x.m_a0 == y.m_a0 && x.m_a1 == y.m_a1 ; }
|
||||
|
||||
double m_a0 ;
|
||||
std::string m_a1 ;
|
||||
} ;
|
||||
|
||||
int test_main( int, char* [] )
|
||||
{
|
||||
int invalid_extra_parameter ;
|
||||
boost::optional<A> opt2 ( boost::in_place(3.14,"pi",invalid_extra_parameter) ) ;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
int test_main( int, char* [] )
|
||||
{
|
||||
int invalid_extra_parameter ;
|
||||
boost::optional<A> opt2 ( A(3.14,"pi",invalid_extra_parameter) ) ;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
62
test/optional_test_inplace_fail2.cpp
Normal file
62
test/optional_test_inplace_fail2.cpp
Normal file
@ -0,0 +1,62 @@
|
||||
// Copyright (C) 2003, Fernando Luis Cacciola Carballal.
|
||||
//
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/lib/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// fernando_cacciola@hotmail.com
|
||||
//
|
||||
#include<iostream>
|
||||
#include<stdexcept>
|
||||
#include<string>
|
||||
|
||||
#define BOOST_ENABLE_ASSERT_HANDLER
|
||||
|
||||
#include "boost/optional/optional.hpp"
|
||||
|
||||
#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
|
||||
#include "boost/utility/typed_in_place_factory.hpp"
|
||||
#endif
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#include "boost/test/minimal.hpp"
|
||||
|
||||
#include "optional_test_common.cpp"
|
||||
|
||||
#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
|
||||
struct A
|
||||
{
|
||||
A ( double a0, std::string a1 ) : m_a0(a0), m_a1(a1) {}
|
||||
|
||||
friend bool operator == ( A const& x, A const& y )
|
||||
{ return x.m_a0 == y.m_a0 && x.m_a1 == y.m_a1 ; }
|
||||
|
||||
double m_a0 ;
|
||||
std::string m_a1 ;
|
||||
} ;
|
||||
|
||||
int test_main( int, char* [] )
|
||||
{
|
||||
// This must fail to compile.
|
||||
// The first template argument to in_place<> is the target-type,
|
||||
// not the first constructor parameter type.
|
||||
boost::optional<A> opt2 ( boost::in_place<int>(3.14,"pi") ) ;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
int test_main( int, char* [] )
|
||||
{
|
||||
boost::optional<A> opt2 ( int(3.14) ) ;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
92
test/optional_test_io.cpp
Normal file
92
test/optional_test_io.cpp
Normal file
@ -0,0 +1,92 @@
|
||||
// Copyright (C) 2003, Fernando Luis Cacciola Carballal.
|
||||
//
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/lib/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// fernando_cacciola@hotmail.com
|
||||
//
|
||||
#include<stdexcept>
|
||||
#include<string>
|
||||
#include<sstream>
|
||||
|
||||
#define BOOST_ENABLE_ASSERT_HANDLER
|
||||
|
||||
#include "boost/optional/optional.hpp"
|
||||
#include "boost/optional/optional_io.hpp"
|
||||
#include "boost/none.hpp"
|
||||
|
||||
#include "boost/test/minimal.hpp"
|
||||
|
||||
#ifdef ENABLE_TRACE
|
||||
#define TRACE(msg) std::cout << msg << std::endl ;
|
||||
#else
|
||||
#define TRACE(msg)
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
|
||||
void assertion_failed (char const * expr, char const * func, char const * file, long )
|
||||
{
|
||||
using std::string ;
|
||||
string msg = string("Boost assertion failure for \"")
|
||||
+ string(expr)
|
||||
+ string("\" at file \"")
|
||||
+ string(file)
|
||||
+ string("\" function \"")
|
||||
+ string(func)
|
||||
+ string("\"") ;
|
||||
|
||||
TRACE(msg);
|
||||
|
||||
throw std::logic_error(msg);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
using namespace std ;
|
||||
using namespace boost ;
|
||||
|
||||
template<class Opt>
|
||||
void test2( Opt o, Opt buff )
|
||||
{
|
||||
stringstream s ;
|
||||
|
||||
const int markv = 123 ;
|
||||
int mark = 0 ;
|
||||
|
||||
s << o << " " << markv ;
|
||||
s >> buff >> mark ;
|
||||
|
||||
BOOST_ASSERT( buff == o ) ;
|
||||
BOOST_ASSERT( mark == markv ) ;
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
void test( T v, T w )
|
||||
{
|
||||
test2( make_optional(v), optional<T> ());
|
||||
test2( make_optional(v), make_optional(w));
|
||||
test2( optional<T> () , optional<T> ());
|
||||
test2( optional<T> () , make_optional(w));
|
||||
}
|
||||
|
||||
int test_main( int, char* [] )
|
||||
{
|
||||
try
|
||||
{
|
||||
test(1,2);
|
||||
test(string("hello"),string("buffer"));
|
||||
}
|
||||
catch ( ... )
|
||||
{
|
||||
BOOST_ERROR("Unexpected Exception caught!");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
373
test/optional_test_ref.cpp
Normal file
373
test/optional_test_ref.cpp
Normal file
@ -0,0 +1,373 @@
|
||||
// Copyright (C) 2003, Fernando Luis Cacciola Carballal.
|
||||
//
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/lib/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// fernando_cacciola@hotmail.com
|
||||
//
|
||||
#include<iostream>
|
||||
#include<stdexcept>
|
||||
#include<string>
|
||||
|
||||
#define BOOST_ENABLE_ASSERT_HANDLER
|
||||
|
||||
#include "boost/optional.hpp"
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#include "boost/none.hpp"
|
||||
|
||||
#include "boost/test/minimal.hpp"
|
||||
|
||||
#include "optional_test_common.cpp"
|
||||
|
||||
template<class T>
|
||||
inline void check_ref_uninitialized_const ( optional<T&> const& opt )
|
||||
{
|
||||
#ifndef BOOST_OPTIONAL_NO_NULL_COMPARE
|
||||
BOOST_CHECK( opt == 0 ) ;
|
||||
#endif
|
||||
BOOST_CHECK( !opt ) ;
|
||||
}
|
||||
template<class T>
|
||||
inline void check_ref_uninitialized ( optional<T&>& opt )
|
||||
{
|
||||
#ifndef BOOST_OPTIONAL_NO_NULL_COMPARE
|
||||
BOOST_CHECK( opt == 0 ) ;
|
||||
#endif
|
||||
BOOST_CHECK( !opt ) ;
|
||||
|
||||
check_ref_uninitialized_const(opt);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline void check_ref_initialized_const ( optional<T&> const& opt )
|
||||
{
|
||||
BOOST_CHECK( opt ) ;
|
||||
|
||||
#ifndef BOOST_OPTIONAL_NO_NULL_COMPARE
|
||||
BOOST_CHECK( opt != 0 ) ;
|
||||
#endif
|
||||
|
||||
BOOST_CHECK ( !!opt ) ;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline void check_ref_initialized ( optional<T&>& opt )
|
||||
{
|
||||
BOOST_CHECK( opt ) ;
|
||||
|
||||
#ifndef BOOST_OPTIONAL_NO_NULL_COMPARE
|
||||
BOOST_CHECK( opt != 0 ) ;
|
||||
#endif
|
||||
|
||||
BOOST_CHECK ( !!opt ) ;
|
||||
|
||||
check_ref_initialized_const(opt);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline void check_ref_value_const ( optional<T&> const& opt, T const& v, T const& z )
|
||||
{
|
||||
BOOST_CHECK( *opt == v ) ;
|
||||
BOOST_CHECK( *opt != z ) ;
|
||||
BOOST_CHECK( opt.get() == v ) ;
|
||||
BOOST_CHECK( opt.get() != z ) ;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline void check_ref_value ( optional<T&>& opt, T const& v, T const& z )
|
||||
{
|
||||
BOOST_CHECK( *opt == v ) ;
|
||||
BOOST_CHECK( *opt != z ) ;
|
||||
BOOST_CHECK( opt.get() == v ) ;
|
||||
BOOST_CHECK( opt.get() != z ) ;
|
||||
|
||||
check_ref_value_const(opt,v,z);
|
||||
}
|
||||
|
||||
//
|
||||
// Basic test.
|
||||
// Check ordinary functionality:
|
||||
// Initialization, assignment, comparison and value-accessing.
|
||||
//
|
||||
template<class T>
|
||||
void test_basics( T const* )
|
||||
{
|
||||
TRACE( std::endl << BOOST_CURRENT_FUNCTION );
|
||||
|
||||
T z(0);
|
||||
|
||||
T original_a(1);
|
||||
|
||||
T a(1);
|
||||
|
||||
T b(2);
|
||||
|
||||
T c(10);
|
||||
|
||||
T& aref = a ;
|
||||
T& bref = b ;
|
||||
|
||||
// Default construction.
|
||||
// 'def' state is Uninitialized.
|
||||
// T::T() is not called
|
||||
optional<T&> def ;
|
||||
check_ref_uninitialized(def);
|
||||
|
||||
// Direct initialization.
|
||||
// 'oa' state is Initialized and binds to 'a'
|
||||
// T::T( T const& x ) is NOT used becasue the optional holds a reference.
|
||||
set_pending_copy( ARG(T) ) ;
|
||||
optional<T&> oa ( aref ) ;
|
||||
check_is_pending_copy( ARG(T) );
|
||||
check_ref_initialized(oa);
|
||||
check_ref_value(oa,a,z);
|
||||
*oa = b ; // changes the value of 'a' through the reference
|
||||
BOOST_CHECK( a == b ) ;
|
||||
|
||||
|
||||
// Copy initialization.
|
||||
// T::T ( T const& x ) is NOT used becasue the optional holds a reference.
|
||||
set_pending_copy( ARG(T) ) ;
|
||||
optional<T&> const oa2 ( oa ) ;
|
||||
check_is_pending_copy( ARG(T) ) ;
|
||||
check_ref_initialized_const(oa2);
|
||||
check_ref_value_const(oa2,a,z);
|
||||
*oa2 = original_a ; // restores the value of 'a' through the reference
|
||||
BOOST_CHECK( a == original_a ) ;
|
||||
|
||||
optional<T&> ob ;
|
||||
|
||||
// Value-Assignment upon Uninitialized optional.
|
||||
// T::T ( T const& x ) is NOT used becasue the optional holds a reference.
|
||||
set_pending_copy( ARG(T) ) ;
|
||||
ob = a ; // Binds ob to a temporary non-const refererence to 'a'
|
||||
check_is_pending_copy( ARG(T) ) ;
|
||||
check_ref_initialized(ob);
|
||||
check_ref_value(ob,a,z);
|
||||
a = c;
|
||||
check_ref_value(ob,a,z);
|
||||
|
||||
// Value-Assignment upon Initialized optional.
|
||||
// T::operator= ( T const& x ) is used.
|
||||
set_pending_assign( ARG(T) ) ;
|
||||
ob = b ; // Rebinds 'ob' to 'b' (without changing 'a')
|
||||
check_is_pending_assign( ARG(T) ) ;
|
||||
check_ref_initialized(ob);
|
||||
check_ref_value(ob,b,z);
|
||||
BOOST_CHECK(a == c); // From a=c in previous test
|
||||
b = c;
|
||||
check_ref_value(ob,b,z);
|
||||
|
||||
|
||||
// Assignment initialization.
|
||||
// T::T ( T const& x ) is NOT used becasue the optional holds a reference.
|
||||
set_pending_copy( ARG(T) ) ;
|
||||
optional<T&> const oa3 = b ;
|
||||
check_is_pending_copy( ARG(T) ) ;
|
||||
check_ref_initialized_const(oa3);
|
||||
check_ref_value_const(oa3,b,z);
|
||||
|
||||
|
||||
// Assignment
|
||||
// T::operator=( T const& x ) is used.
|
||||
set_pending_assign( ARG(T) ) ;
|
||||
oa = ob ; // Rebinds 'a' to 'b'
|
||||
check_is_pending_assign( ARG(T) ) ;
|
||||
check_ref_initialized(oa);
|
||||
a = original_a ;
|
||||
check_ref_value(oa,b,z);
|
||||
|
||||
// Uninitializing Assignment upon Initialized Optional
|
||||
// T::~T() is NOT used becasue the optional holds a reference.
|
||||
set_pending_dtor( ARG(T) ) ;
|
||||
set_pending_copy( ARG(T) ) ;
|
||||
oa = def ;
|
||||
check_is_pending_dtor( ARG(T) ) ;
|
||||
check_is_pending_copy( ARG(T) ) ;
|
||||
check_ref_uninitialized(oa);
|
||||
|
||||
// Uninitializing Assignment upon Uninitialized Optional
|
||||
// (Dtor is not called this time)
|
||||
set_pending_dtor( ARG(T) ) ;
|
||||
set_pending_copy( ARG(T) ) ;
|
||||
oa = def ;
|
||||
check_is_pending_dtor( ARG(T) ) ;
|
||||
check_is_pending_copy( ARG(T) ) ;
|
||||
check_ref_uninitialized(oa);
|
||||
|
||||
|
||||
// Deinitialization of Initialized Optional
|
||||
// T::~T() is NOT used becasue the optional holds a reference.
|
||||
set_pending_dtor( ARG(T) ) ;
|
||||
ob.reset();
|
||||
check_is_pending_dtor( ARG(T) ) ;
|
||||
check_ref_uninitialized(ob);
|
||||
|
||||
// Deinitialization of Uninitialized Optional
|
||||
// T::~T() is not called this time
|
||||
set_pending_dtor( ARG(T) ) ;
|
||||
ob.reset();
|
||||
check_is_pending_dtor( ARG(T) ) ;
|
||||
check_ref_uninitialized(ob);
|
||||
}
|
||||
|
||||
//
|
||||
// This verifies relational operators.
|
||||
//
|
||||
template<class T>
|
||||
void test_relops( T const* )
|
||||
{
|
||||
TRACE( std::endl << BOOST_CURRENT_FUNCTION );
|
||||
|
||||
reset_throw_on_copy( ARG(T) ) ;
|
||||
|
||||
T v0(18);
|
||||
T v1(19);
|
||||
T v2(19);
|
||||
|
||||
optional<T&> def0 ;
|
||||
optional<T&> def1 ;
|
||||
optional<T&> opt0(v0);
|
||||
optional<T&> opt1(v1);
|
||||
optional<T&> opt2(v2);
|
||||
|
||||
// Check identity
|
||||
BOOST_CHECK ( def0 == def0 ) ;
|
||||
BOOST_CHECK ( opt0 == opt0 ) ;
|
||||
BOOST_CHECK ( !(def0 != def0) ) ;
|
||||
BOOST_CHECK ( !(opt0 != opt0) ) ;
|
||||
|
||||
// Check when both are uininitalized.
|
||||
BOOST_CHECK ( def0 == def1 ) ; // both uninitialized compare equal
|
||||
BOOST_CHECK ( !(def0 < def1) ) ; // uninitialized is never less than uninitialized
|
||||
BOOST_CHECK ( !(def0 > def1) ) ; // uninitialized is never greater than uninitialized
|
||||
BOOST_CHECK ( !(def0 != def1) ) ;
|
||||
BOOST_CHECK ( def0 <= def1 ) ;
|
||||
BOOST_CHECK ( def0 >= def1 ) ;
|
||||
|
||||
// Check when only lhs is uninitialized.
|
||||
BOOST_CHECK ( def0 != opt0 ) ; // uninitialized is never equal to initialized
|
||||
BOOST_CHECK ( !(def0 == opt0) ) ;
|
||||
BOOST_CHECK ( def0 < opt0 ) ; // uninitialized is always less than initialized
|
||||
BOOST_CHECK ( !(def0 > opt0) ) ;
|
||||
BOOST_CHECK ( def0 <= opt0 ) ;
|
||||
BOOST_CHECK ( !(def0 >= opt0) ) ;
|
||||
|
||||
// Check when only rhs is uninitialized.
|
||||
BOOST_CHECK ( opt0 != def0 ) ; // initialized is never equal to uninitialized
|
||||
BOOST_CHECK ( !(opt0 == def0) ) ;
|
||||
BOOST_CHECK ( !(opt0 < def0) ) ; // initialized is never less than uninitialized
|
||||
BOOST_CHECK ( opt0 > def0 ) ;
|
||||
BOOST_CHECK ( !(opt0 <= def0) ) ;
|
||||
BOOST_CHECK ( opt0 >= opt0 ) ;
|
||||
|
||||
// If both are initialized, values are compared
|
||||
BOOST_CHECK ( opt0 != opt1 ) ;
|
||||
BOOST_CHECK ( opt1 == opt2 ) ;
|
||||
BOOST_CHECK ( opt0 < opt1 ) ;
|
||||
BOOST_CHECK ( opt1 > opt0 ) ;
|
||||
BOOST_CHECK ( opt1 <= opt2 ) ;
|
||||
BOOST_CHECK ( opt1 >= opt0 ) ;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void test_none( T const* )
|
||||
{
|
||||
TRACE( std::endl << BOOST_CURRENT_FUNCTION );
|
||||
|
||||
using boost::none ;
|
||||
|
||||
T a(1234);
|
||||
|
||||
optional<T&> def0 ;
|
||||
optional<T&> def1(none) ;
|
||||
optional<T&> non_def(a) ;
|
||||
|
||||
BOOST_CHECK ( def0 == none ) ;
|
||||
BOOST_CHECK ( non_def != none ) ;
|
||||
BOOST_CHECK ( !def1 ) ;
|
||||
|
||||
non_def = none ;
|
||||
BOOST_CHECK ( !non_def ) ;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void test_arrow( T const* )
|
||||
{
|
||||
TRACE( std::endl << BOOST_CURRENT_FUNCTION );
|
||||
|
||||
T a(1234);
|
||||
|
||||
optional<T&> oa(a) ;
|
||||
optional<T&> const coa(a) ;
|
||||
|
||||
BOOST_CHECK ( coa->V() == 1234 ) ;
|
||||
|
||||
oa->V() = 4321 ;
|
||||
|
||||
BOOST_CHECK ( a.V() = 4321 ) ;
|
||||
}
|
||||
|
||||
void test_with_builtin_types()
|
||||
{
|
||||
TRACE( std::endl << BOOST_CURRENT_FUNCTION );
|
||||
|
||||
test_basics( ARG(double) );
|
||||
test_relops( ARG(double) ) ;
|
||||
test_none ( ARG(double) ) ;
|
||||
}
|
||||
|
||||
void test_with_class_type()
|
||||
{
|
||||
TRACE( std::endl << BOOST_CURRENT_FUNCTION );
|
||||
|
||||
test_basics( ARG(X) );
|
||||
test_relops( ARG(X) ) ;
|
||||
test_none ( ARG(X) ) ;
|
||||
test_arrow ( ARG(X) ) ;
|
||||
|
||||
BOOST_CHECK ( X::count == 0 ) ;
|
||||
}
|
||||
|
||||
void test_binding()
|
||||
{
|
||||
int i = 0 ;
|
||||
optional<int&> ori1 = i ;
|
||||
BOOST_CHECK( &(*ori1) == &i ) ;
|
||||
|
||||
optional<int&> ori2(i) ;
|
||||
BOOST_CHECK( &(*ori2) == &i ) ;
|
||||
|
||||
int const ci = 0 ;
|
||||
optional<int const&> orci1 = ci ;
|
||||
BOOST_CHECK( &(*orci1) == &ci ) ;
|
||||
|
||||
optional<int const&> orci2(ci) ;
|
||||
BOOST_CHECK( &(*orci2) == &ci ) ;
|
||||
}
|
||||
|
||||
int test_main( int, char* [] )
|
||||
{
|
||||
try
|
||||
{
|
||||
test_with_class_type();
|
||||
test_with_builtin_types();
|
||||
test_binding();
|
||||
}
|
||||
catch ( ... )
|
||||
{
|
||||
BOOST_ERROR("Unexpected Exception caught!");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
25
test/optional_test_ref_fail1.cpp
Normal file
25
test/optional_test_ref_fail1.cpp
Normal file
@ -0,0 +1,25 @@
|
||||
// Copyright (C) 2003, Fernando Luis Cacciola Carballal.
|
||||
//
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/lib/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// fernando_cacciola@hotmail.com
|
||||
//
|
||||
#include "boost/optional.hpp"
|
||||
|
||||
//
|
||||
// THIS TEST SHOULD FAIL TO COMPILE
|
||||
//
|
||||
void optional_reference__test_no_converting_assignment()
|
||||
{
|
||||
boost::optional<int&> opt ;
|
||||
double v = 1 ;
|
||||
double& r = v ;
|
||||
opt = r ;
|
||||
}
|
||||
|
||||
|
23
test/optional_test_ref_fail3.cpp
Normal file
23
test/optional_test_ref_fail3.cpp
Normal file
@ -0,0 +1,23 @@
|
||||
// Copyright (C) 2003, Fernando Luis Cacciola Carballal.
|
||||
//
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/lib/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// fernando_cacciola@hotmail.com
|
||||
//
|
||||
#include "boost/optional.hpp"
|
||||
|
||||
//
|
||||
// THIS TEST SHOULD FAIL TO COMPILE
|
||||
//
|
||||
void optional_reference__test_no_converting_ctor()
|
||||
{
|
||||
boost::optional<short&> opt1 ;
|
||||
boost::optional<int&> opt2 = opt1 ;
|
||||
}
|
||||
|
||||
|
24
test/optional_test_ref_fail4.cpp
Normal file
24
test/optional_test_ref_fail4.cpp
Normal file
@ -0,0 +1,24 @@
|
||||
// Copyright (C) 2003, Fernando Luis Cacciola Carballal.
|
||||
//
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/lib/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// fernando_cacciola@hotmail.com
|
||||
//
|
||||
#include "boost/optional.hpp"
|
||||
|
||||
//
|
||||
// THIS TEST SHOULD FAIL TO COMPILE
|
||||
//
|
||||
void optional_reference__test_no_converting_initialization()
|
||||
{
|
||||
short v = 1 ;
|
||||
short& r = v;
|
||||
boost::optional<int&> opt(r) ;
|
||||
}
|
||||
|
||||
|
64
test/optional_test_tie.cpp
Normal file
64
test/optional_test_tie.cpp
Normal file
@ -0,0 +1,64 @@
|
||||
// Copyright (C) 2003, Fernando Luis Cacciola Carballal.
|
||||
//
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/lib/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// fernando_cacciola@hotmail.com
|
||||
//
|
||||
#include<iostream>
|
||||
#include<stdexcept>
|
||||
#include<string>
|
||||
|
||||
#define BOOST_ENABLE_ASSERT_HANDLER
|
||||
|
||||
#include "boost/optional.hpp"
|
||||
#include "boost/tuple/tuple.hpp"
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#include "boost/test/minimal.hpp"
|
||||
|
||||
#include "optional_test_common.cpp"
|
||||
|
||||
// Test boost::tie() interoperabiliy.
|
||||
int test_main( int, char* [] )
|
||||
{
|
||||
typedef X T ;
|
||||
|
||||
try
|
||||
{
|
||||
TRACE( std::endl << BOOST_CURRENT_FUNCTION );
|
||||
|
||||
T z(0);
|
||||
T a(1);
|
||||
T b(2);
|
||||
|
||||
optional<T> oa, ob ;
|
||||
|
||||
// T::T( T const& x ) is used
|
||||
set_pending_dtor( ARG(T) ) ;
|
||||
set_pending_copy( ARG(T) ) ;
|
||||
boost::tie(oa,ob) = std::make_pair(a,b) ;
|
||||
check_is_not_pending_dtor( ARG(T) ) ;
|
||||
check_is_not_pending_copy( ARG(T) ) ;
|
||||
check_initialized(oa);
|
||||
check_initialized(ob);
|
||||
check_value(oa,a,z);
|
||||
check_value(ob,b,z);
|
||||
|
||||
}
|
||||
catch ( ... )
|
||||
{
|
||||
BOOST_ERROR("Unexpected Exception caught!");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user