Compare commits

...

52 Commits

Author SHA1 Message Date
face89c114 Branch for working on the documentation tools documentation.
[SVN r68640]
2011-02-04 21:18:24 +00:00
e9989b260e Refs #4987. Added forward declaration of namespace-scope swap for boost::optional, this should fix GCC compilation errors. Also swap implementation now uses Boost.Utility.Swap to make use of the workarounds for some broken compilers. If it breaks for your compiler, let me know in the mentioned ticket.
[SVN r67288]
2010-12-17 21:12:56 +00:00
646488e0e2 operator>> behavior changed slightly so that the stream is not accessed when unrecognized character sequence is detected.
[SVN r67184]
2010-12-12 11:35:19 +00:00
64d8062621 The may_alias workaround is also disabled for GCC prior to 3.2. Also added description for this workaround.
[SVN r67112]
2010-12-08 18:32:36 +00:00
d39627c5b6 boost/optional/optional.hpp: avoid gcc 3.2 warnings
[SVN r67109]
2010-12-08 17:53:29 +00:00
f88c8ae423 Refs #3395. Optional construction and assignment now works correctly for types with overridden operator&. Also silenced some GCC warnings about broken strict aliasing rules.
[SVN r67020]
2010-12-05 14:43:18 +00:00
ab01dfff7e Fully qualify ios flags. Fixes compilation of PropertyTree, bug 4459.
[SVN r64342]
2010-07-25 22:21:45 +00:00
8608ad1497 Fixed behaviour in case of invalid input
[SVN r64208]
2010-07-20 19:21:44 +00:00
c93e5a88c7 Fixed extraction operator for empty optionals
[SVN r64206]
2010-07-20 18:20:40 +00:00
425d141cbf Test for fixed extraction operator for empty optinals
[SVN r64205]
2010-07-20 18:20:01 +00:00
57c07c7a57 Fix doc build for 2 libraries which use own css.
I changed the default to use doc/src/boostbook.css. So add an explicit
location to libraries which use their own stylesheet.

[SVN r64170]
2010-07-19 20:17:58 +00:00
97e314f03a Fix some header links.
[SVN r64006]
2010-07-14 08:15:33 +00:00
bccd75c72f Update various libraries' documentation build.
Mostly to use the images and css files under doc/src instead of
doc/html, usually be deleting the settings in order to use the defaults.
Also add 'boost.root' to some builds in order to fix links which rely on
it.

[SVN r63146]
2010-06-20 18:00:48 +00:00
16f0a0aaaf Expose the "types" typedef of boost::optional_detail::operator_base as
public, rather than protected, since Spirit pokes at this typedef. 


[SVN r61832]
2010-05-06 21:44:18 +00:00
a63dbe0f14 Rebuild optional docs.
[SVN r57812]
2009-11-20 10:26:23 +00:00
066dd6f345 rm cmake from trunk. I'm not entirely sure this is necessary to satisfy the inspect script, but I'm not taking any chances, and it is easy to put back
[SVN r56942]
2009-10-17 02:07:38 +00:00
4e628ed4a6 Copyrights on CMakeLists.txt to keep them from clogging up the inspect
reports.  This is essentially the same commit as r55095 on the release
branch.



[SVN r55159]
2009-07-26 00:49:56 +00:00
8682f2bbaa avoid C style casts
[SVN r53671]
2009-06-06 09:42:41 +00:00
fea89e84f3 Fixed most tab and min/max issues from trunk inspection report
[SVN r53141]
2009-05-20 19:19:00 +00:00
2772bfc08d optional docs in cmakeland
[SVN r52251]
2009-04-08 12:09:58 +00:00
361943e033 Add PDF generation options to fix external links to point to the web site.
Added a few more Boostbook based libs that were missed first time around.
Fixed PDF naming issues.

[SVN r51284]
2009-02-17 10:05:58 +00:00
20c9fc8ebe Fix the optional and numeric/conversion docs so they generate valid Docbook XML that can be transformed into PDF's.
Regenerated HTML versions of the docs.

[SVN r51218]
2009-02-12 14:01:48 +00:00
fd38be1636 Fix an incorrectly escaped right arrow.
[SVN r50839]
2009-01-28 09:14:56 +00:00
9f655c6932 Updating dependency information for modularized libraries.
[SVN r49628]
2008-11-07 17:05:27 +00:00
e7d7b014d2 Updating CMake files to latest trunk. Added dependency information for regression tests and a few new macros for internal use.
[SVN r49627]
2008-11-07 17:02:56 +00:00
2af3ec341b Continuing merge of CMake build system files into trunk with the encouragement of Doug Gregor
[SVN r49510]
2008-11-01 13:15:41 +00:00
3ebabcb2d8 Fixed syntax of optional_swap_should_use_default_constructor and swap template specializations that I added 2 days ago (changeset [45265]). Was accepted by MSVC, but rejected by other compilers.
[SVN r45295]
2008-05-12 13:29:52 +00:00
63f6e7f45e Added more optional::swap tests, especially on self swap, on specializing boost::swap for optional<T>, and on swapping optional<T> when T is a template class.
[SVN r45265]
2008-05-10 14:53:51 +00:00
43eac5bb12 Added forward declaration of boost::optional_swap_should_use_default_constructor.
[SVN r45264]
2008-05-10 14:42:49 +00:00
74674531c8 Replaced "using std::swap" by "using boost::swap" within optional::swap member function, hoping to fix GCC test failures, as mentioned at http://article.gmane.org/gmane.comp.lib.boost.devel/174350 "Re: [optional] problems with swap()"
[SVN r44826]
2008-04-27 21:09:50 +00:00
a4572497be Added forward declaration of optional<T>'s boost::swap overload, as mentioned at http://article.gmane.org/gmane.comp.lib.boost.devel/174350 "Re: [optional] problems with swap()"
[SVN r44825]
2008-04-27 21:07:10 +00:00
951b49f992 Merge in documentation fixes. Apart from the change to optional's documenation
Jamfile, which I included by mistake.

Fixes #1659, #1661, #1684, #1685, 1687, #1690, #1801

I wrote about this at:

http://lists.boost.org/Archives/boost/2008/04/136405.php

Merged revisions 44585-44806 via svnmerge from 
https://svn.boost.org/svn/boost/branches/doc

........
  r44585 | danieljames | 2008-04-19 16:25:27 +0100 (Sat, 19 Apr 2008) | 2 lines
  
  Fix broken link to vacpp in bjam docs. Refs #1512
........
  r44586 | danieljames | 2008-04-19 16:27:36 +0100 (Sat, 19 Apr 2008) | 2 lines
  
  Fix broken link to bcpp in bjam docs. Refs #1513
........
  r44587 | danieljames | 2008-04-19 16:33:58 +0100 (Sat, 19 Apr 2008) | 2 lines
  
  DateTime documentation - Fix a link to the serialization library. Refs #1659
........
  r44588 | danieljames | 2008-04-19 16:35:36 +0100 (Sat, 19 Apr 2008) | 2 lines
  
  Fix some links in interprocess & intrusive. Refs #1661
........
  r44589 | danieljames | 2008-04-19 16:37:39 +0100 (Sat, 19 Apr 2008) | 2 lines
  
  Fix some links in the python docs. Refs #1684.
........
  r44590 | danieljames | 2008-04-19 16:38:29 +0100 (Sat, 19 Apr 2008) | 2 lines
  
  Work around a quickbook bug which is affecting the python docs. Refs #1684.
........
  r44591 | danieljames | 2008-04-19 16:39:34 +0100 (Sat, 19 Apr 2008) | 2 lines
  
  Fix a broken link in the numeric conversion docs. Refs #1685
........
  r44592 | danieljames | 2008-04-19 16:40:45 +0100 (Sat, 19 Apr 2008) | 2 lines
  
  Fix some links in the optional docs. Refs #1687
........
  r44593 | danieljames | 2008-04-19 16:42:09 +0100 (Sat, 19 Apr 2008) | 2 lines
  
  Fix link to the hash documentation from bimap. Refs #1690
........
  r44599 | danieljames | 2008-04-19 18:07:33 +0100 (Sat, 19 Apr 2008) | 2 lines
  
  Fix a typo in the format library. Refs #1801
........
  r44600 | danieljames | 2008-04-19 19:20:59 +0100 (Sat, 19 Apr 2008) | 1 line
  
  Initialise svnmerge.
........
  r44641 | danieljames | 2008-04-20 18:59:47 +0100 (Sun, 20 Apr 2008) | 2 lines
  
  Fix the lincense url in shared container iterator documentation.
........
  r44642 | danieljames | 2008-04-20 19:00:00 +0100 (Sun, 20 Apr 2008) | 2 lines
  
  Fix image link in the mpi documentation.
........
  r44643 | danieljames | 2008-04-20 19:00:11 +0100 (Sun, 20 Apr 2008) | 2 lines
  
  Fix a typo in the spirit docs.
........
  r44644 | danieljames | 2008-04-20 19:00:23 +0100 (Sun, 20 Apr 2008) | 2 lines
  
  Escape the slash so that quickbook doesn't think it the start of an italic section, and mess up the link. Refs #1844
........
  r44647 | danieljames | 2008-04-20 19:39:47 +0100 (Sun, 20 Apr 2008) | 2 lines
  
  Fix another typo in spirit docs.
........


[SVN r44807]
2008-04-27 07:39:49 +00:00
1afed544db Added unit tests, testing optional<T> swap improvements of revision [44766]
[SVN r44767]
2008-04-25 16:52:34 +00:00
66c366d18a Improved swap for optional<T>, co-written by Thorsten and Fernando: added support for tweaking whether swap should use T's default constructor. Added swap member function. Discussed at Boost developers' mailing list, "[optional] problems with swap()", http://lists.boost.org/Archives/boost/2008/04/135882.php
[SVN r44766]
2008-04-25 16:50:32 +00:00
472a68c920 redirect optional docs to new version
[SVN r43248]
2008-02-14 17:44:21 +00:00
3e33d4a200 optional docs fixes
[SVN r43247]
2008-02-14 17:43:52 +00:00
95c864e119 Cast to base added to avoid a call to the convertir constructor/assignment (see Tickes 1419 and 1420)
[SVN r41381]
2007-11-25 20:26:14 +00:00
9afdbe65e7 // Add or correct comment identifying Boost library this header is associated with.
[SVN r41173]
2007-11-17 20:13:16 +00:00
f6518df0c4 Get rid of .cvsignore files
[SVN r41107]
2007-11-15 15:20:27 +00:00
05a685b035 Fixed intention in the added binding test
[SVN r40860]
2007-11-06 22:21:43 +00:00
3b5b5d82a0 Added test to ensure proper binding of optional references (in reference to Ticket 1301)
[SVN r40707]
2007-11-02 23:41:37 +00:00
06ba35cd42 Fixed error reported by Edward Diener
[SVN r40706]
2007-11-02 23:06:42 +00:00
3499d477dc Merged changests from RC_1_34_0 - base rev 33417
[SVN r40705]
2007-11-02 22:56:23 +00:00
a690c8e7a2 Merged changests from RC_1_34_0 - base rev 33417
[SVN r40704]
2007-11-02 22:55:49 +00:00
c8e54ef488 Remove V1 Jamfiles
[SVN r38516]
2007-08-08 19:02:26 +00:00
07ce2fc860 new quickbook docs for optional
[SVN r37809]
2007-05-29 06:40:25 +00:00
be7249b537 Add copyright, license
[SVN r35905]
2006-11-07 19:11:57 +00:00
1b7002f663 misused "precedence" changed to "precedent"
[SVN r35831]
2006-11-04 02:13:53 +00:00
16a8ccbecc removed unnamed namespace (see http://lists.boost.org/Archives/boost/2006/07/107873.php); usual copyright/license/url fixes
[SVN r34646]
2006-07-20 23:17:22 +00:00
734e5b5283 Some additional functions added to optional (being new there won't be regressions)
[SVN r34411]
2006-06-26 18:01:38 +00:00
a77dff3e11 workaround for Borland
[SVN r34288]
2006-06-12 19:02:41 +00:00
9516a779fe Disambiguated certain constructs.
[SVN r34227]
2006-06-08 01:47:33 +00:00
43 changed files with 6883 additions and 1803 deletions

35
doc/Jamfile.v2 Normal file
View 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
View 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
View 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
View 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 precedence for a variable-size
fixed-capacity (of 1) stack-based container model for optional values, yet I
believe this is the consequence of the lack of practical implementations of
such a container rather than an inherent shortcoming of the container model.
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 inexistent 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 inexistent) 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
View 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
View 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

View File

@ -0,0 +1,84 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>A note about optional&lt;bool&gt;</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<65>1.<2E>Boost.Optional">
<link rel="up" href="../index.html" title="Chapter<65>1.<2E>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="../../../../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/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="exception_safety_guarantees.html"><img src="../../../../../doc/html/images/next.png" alt="Next"></a>
</div>
<div class="section" title="A note about optional&lt;bool&gt;">
<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&lt;bool&gt;">A note about
optional&lt;bool&gt;</a>
</h2></div></div></div>
<p>
<code class="computeroutput"><span class="identifier">optional</span><span class="special">&lt;</span><span class="keyword">bool</span><span class="special">&gt;</span></code> should
be used with special caution and consideration.
</p>
<p>
First, it is functionally similar to a tristate boolean (false,maybe,true)
&#8212;such as <a href="../../../../../doc/html/tribool.html" target="_top">boost::tribool</a>&#8212;
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">&lt;</span><span class="keyword">bool</span><span class="special">&gt;</span></code>. It
should be carefully considered if an <code class="computeroutput"><span class="identifier">optional</span><span class="special">&lt;</span><span class="keyword">bool</span><span class="special">&gt;</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">&lt;&gt;</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">&lt;</span><span class="keyword">bool</span><span class="special">&gt;</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">&lt;</span><span class="keyword">bool</span><span class="special">&gt;</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 <20> 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/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="exception_safety_guarantees.html"><img src="../../../../../doc/html/images/next.png" alt="Next"></a>
</div>
</body>
</html>

View File

@ -0,0 +1,125 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<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<65>1.<2E>Boost.Optional">
<link rel="up" href="../index.html" title="Chapter<65>1.<2E>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="../../../../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/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/html/images/home.png" alt="Home"></a>
</div>
<div class="section" title="Acknowledgments">
<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="id583998"></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="id584068"></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&lt;&gt;/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&lt;&gt; 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&lt;&gt; can be seen as an API on top
of variant&lt;T,nil_t&gt;.
</li>
<li class="listitem">
Dave Gomboc explained the meaning and usage of the Haskell analog to optional&lt;&gt;:
the Maybe type constructor (analogy originally pointed out by David Sankel).
</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 <20> 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/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/html/images/home.png" alt="Home"></a>
</div>
</body>
</html>

View File

@ -0,0 +1,48 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<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<65>1.<2E>Boost.Optional">
<link rel="up" href="../index.html" title="Chapter<65>1.<2E>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="../../../../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/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="acknowledgments.html"><img src="../../../../../doc/html/images/next.png" alt="Next"></a>
</div>
<div class="section" title="Dependencies and Portability">
<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 <20> 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/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="acknowledgments.html"><img src="../../../../../doc/html/images/next.png" alt="Next"></a>
</div>
</body>
</html>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,412 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<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<65>1.<2E>Boost.Optional">
<link rel="up" href="../index.html" title="Chapter<65>1.<2E>Boost.Optional">
<link rel="prev" href="../index.html" title="Chapter<65>1.<2E>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="../../../../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/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="synopsis.html"><img src="../../../../../doc/html/images/next.png" alt="Next"></a>
</div>
<div class="section" title="Development">
<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" title="The models">
<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">&lt;</span><span class="identifier">T</span><span class="special">&gt;</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">&lt;</span><span class="identifier">T</span><span class="special">&gt;</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>&#8212;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">&lt;</span><span class="identifier">T</span><span class="special">,</span><span class="identifier">nil_t</span><span class="special">&gt;</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">&lt;</span><span class="identifier">T</span><span class="special">,</span><span class="identifier">nil_t</span><span class="special">&gt;</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">&lt;</span><span class="identifier">T</span><span class="special">&gt;</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 precedence for a variable-size fixed-capacity
(of 1) stack-based container model for optional values, yet I believe this
is the consequence of the lack of practical implementations of such a container
rather than an inherent shortcoming of the container model.
</p>
<p>
In any event, both the discriminated-union or the single-element container
models serve as a conceptual ground for a class representing optional&#8212;i.e.
possibly uninitialized&#8212;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" title="The semantics">
<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">&lt;</span><span class="identifier">T</span><span class="special">&gt;</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">&lt;</span><span class="identifier">T</span><span class="special">&gt;</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">&lt;</span><span class="identifier">T</span><span class="special">&gt;</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">&lt;</span><span class="identifier">T</span><span class="special">&gt;</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">&lt;</span><span class="identifier">T</span><span class="special">&gt;</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">&lt;</span><span class="identifier">T</span><span class="special">&gt;</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" title="The Interface">
<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">&lt;</span><span class="identifier">T</span><span class="special">&gt;</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">&lt;</span><span class="identifier">T</span><span class="special">&gt;</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="id555569"></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 -&gt;</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 inexistent 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&#8212;from
the days of C APIs to modern C++ libraries&#8212;to <span class="emphasis"><em>refer</em></span>
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 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">-&gt;</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">-&gt;</span></code> tell by themselves
&#8212;without any additional context&#8212; 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">-&gt;</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">&lt;</span><span class="identifier">X</span><span class="special">&gt;</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="id555831"></a>
<a class="link" href="development.html#boost_optional.development.the_interface.optional_lt_t_gt__as_a_model_of_optionalpointee">Optional&lt;T&gt;
as a model of OptionalPointee</a>
</h5>
<p>
For value access operations <code class="computeroutput"><span class="identifier">optional</span><span class="special">&lt;&gt;</span></code> uses operators <code class="computeroutput"><span class="special">*</span></code>
and <code class="computeroutput"><span class="special">-&gt;</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" title="Warning"><table border="0" summary="Warning">
<tr>
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Warning]" src="../../../../../doc/html/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">&lt;&gt;</span></code> objects are not pointers. <span class="underline"><code class="computeroutput"><span class="identifier">optional</span><span class="special">&lt;&gt;</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">&lt;&gt;</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">&lt;</span><span class="identifier">T</span><span class="special">&gt;</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">&lt;</span><span class="identifier">T</span><span class="special">&gt;</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">&lt;</span><span class="identifier">T</span><span class="special">&gt;</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 <20> 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/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="synopsis.html"><img src="../../../../../doc/html/images/next.png" alt="Next"></a>
</div>
</body>
</html>

View File

@ -0,0 +1,147 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<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<65>1.<2E>Boost.Optional">
<link rel="up" href="../index.html" title="Chapter<65>1.<2E>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="../../../../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/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="optional_references.html"><img src="../../../../../doc/html/images/next.png" alt="Next"></a>
</div>
<div class="section" title="Examples">
<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" title="Optional return values">
<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">&lt;</span><span class="keyword">char</span><span class="special">&gt;</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">&lt;</span><span class="keyword">char</span><span class="special">&gt;(</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">&lt;</span><span class="keyword">char</span><span class="special">&gt;();</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">&lt;</span><span class="keyword">char</span><span class="special">&gt;</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">&amp;&amp;</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" title="Optional local variables">
<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">&lt;</span><span class="identifier">string</span><span class="special">&gt;</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" title="Optional data members">
<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">&amp;</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">&amp;</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">&lt;</span><span class="identifier">rect</span><span class="special">&gt;</span> <span class="identifier">m_clipping_rect</span> <span class="special">;</span>
<span class="special">};</span>
</pre>
</div>
<div class="section" title="Bypassing expensive unnecessary default construction">
<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">&lt;</span> <span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">ExpensiveCtor</span><span class="special">&gt;</span> <span class="special">&gt;</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 <20> 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/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="optional_references.html"><img src="../../../../../doc/html/images/next.png" alt="Next"></a>
</div>
</body>
</html>

View File

@ -0,0 +1,140 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<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<65>1.<2E>Boost.Optional">
<link rel="up" href="../index.html" title="Chapter<65>1.<2E>Boost.Optional">
<link rel="prev" href="a_note_about_optional_bool_.html" title="A note about optional&lt;bool&gt;">
<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="../../../../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/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="type_requirements.html"><img src="../../../../../doc/html/images/next.png" alt="Next"></a>
</div>
<div class="section" title="Exception Safety Guarantees">
<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">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</span><span class="keyword">operator</span><span class="special">=</span> <span class="special">(</span> <span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">const</span><span class="special">&amp;</span>
<span class="special">)</span></code></li>
<li class="listitem"><code class="computeroutput"><span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</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">&amp;</span> <span class="special">)</span></code></li>
<li class="listitem"><code class="computeroutput"><span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">U</span><span class="special">&gt;</span> <span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</span><span class="keyword">operator</span><span class="special">=</span> <span class="special">(</span> <span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">U</span><span class="special">&gt;</span>
<span class="keyword">const</span><span class="special">&amp;</span>
<span class="special">)</span></code></li>
<li class="listitem"><code class="computeroutput"><span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">InPlaceFactory</span><span class="special">&gt;</span> <span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</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">&amp;</span>
<span class="special">)</span></code></li>
<li class="listitem"><code class="computeroutput"><span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">TypedInPlaceFactory</span><span class="special">&gt;</span> <span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</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">&amp;</span>
<span class="special">)</span> </code></li>
<li class="listitem"><code class="computeroutput"><span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;:::</span><span class="identifier">reset</span> <span class="special">(</span> <span class="identifier">T</span> <span class="keyword">const</span><span class="special">&amp;)</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">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</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">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</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">&lt;&gt;</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">&amp;</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">&lt;</span><span class="identifier">T</span><span class="special">&gt;</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">&lt;</span><span class="identifier">T</span><span class="special">&gt;</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">&lt;</span><span class="identifier">T</span><span class="special">&gt;</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="id583497"></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">&lt;</span><span class="identifier">T</span><span class="special">&gt;&amp;,</span>
<span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;&amp;</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">&amp;,</span><span class="identifier">T</span><span class="special">&amp;)</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">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</span><span class="identifier">reset</span><span class="special">(</span> <span class="identifier">T</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="special">)</span></code> (since
<code class="computeroutput"><span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;::</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 <20> 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/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="type_requirements.html"><img src="../../../../../doc/html/images/next.png" alt="Next"></a>
</div>
</body>
</html>

View File

@ -0,0 +1,55 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<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<65>1.<2E>Boost.Optional">
<link rel="up" href="../index.html" title="Chapter<65>1.<2E>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="../../../../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/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="dependencies_and_portability.html"><img src="../../../../../doc/html/images/next.png" alt="Next"></a>
</div>
<div class="section" title="Implementation Notes">
<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">&lt;</span><span class="identifier">T</span><span class="special">&gt;</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 <20> 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/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="dependencies_and_portability.html"><img src="../../../../../doc/html/images/next.png" alt="Next"></a>
</div>
</body>
</html>

View File

@ -0,0 +1,196 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<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<65>1.<2E>Boost.Optional">
<link rel="up" href="../index.html" title="Chapter<65>1.<2E>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&lt;bool&gt;">
</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="../../../../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/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="a_note_about_optional_bool_.html"><img src="../../../../../doc/html/images/next.png" alt="Next"></a>
</div>
<div class="section" title="In-Place Factories">
<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">&amp;</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">&amp;</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">&lt;</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">&gt;</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">&amp;</span> <span class="identifier">a0</span><span class="special">,</span> <span class="identifier">A1</span> <span class="keyword">const</span><span class="special">&amp;</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">&amp;</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">&amp;</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">(&amp;</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">&lt;</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">&gt;(</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">&lt;</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">&gt;</span>
<span class="identifier">InPlaceFactoryN</span> <span class="special">&lt;</span><span class="identifier">A0</span><span class="special">,...,</span><span class="identifier">AN</span><span class="special">&gt;</span> <span class="identifier">in_place</span> <span class="special">(</span> <span class="identifier">A0</span> <span class="keyword">const</span><span class="special">&amp;</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">&amp;</span> <span class="identifier">aN</span><span class="special">)</span> <span class="special">;</span>
<span class="keyword">template</span><span class="special">&lt;</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">&gt;</span>
<span class="identifier">TypedInPlaceFactoryN</span> <span class="special">&lt;</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">&gt;</span> <span class="identifier">in_place</span> <span class="special">(</span> <span class="identifier">T</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">a0</span><span class="special">,</span> <span class="identifier">A0</span> <span class="keyword">const</span><span class="special">&amp;</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">&amp;</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">&amp;</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">&lt;</span> <span class="keyword">class</span> <span class="identifier">InPlaceFactory</span> <span class="special">&gt;</span>
<span class="identifier">W</span> <span class="special">(</span> <span class="identifier">InPlaceFactory</span> <span class="keyword">const</span><span class="special">&amp;</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">&lt;</span><span class="identifier">X</span><span class="special">&gt;</span><span class="identifier">construct</span><span class="special">(&amp;</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 <20> 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/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="a_note_about_optional_bool_.html"><img src="../../../../../doc/html/images/next.png" alt="Next"></a>
</div>
</body>
</html>

View File

@ -0,0 +1,85 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<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<65>1.<2E>Boost.Optional">
<link rel="up" href="../index.html" title="Chapter<65>1.<2E>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="../../../../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/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="rebinding_semantics_for_assignment_of_optional_references.html"><img src="../../../../../doc/html/images/next.png" alt="Next"></a>
</div>
<div class="section" title="Optional references">
<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">&amp;</span></code>, and to some extent, <code class="computeroutput"><span class="identifier">T</span>
<span class="keyword">const</span><span class="special">&amp;</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">&lt;</span><span class="identifier">T</span><span class="special">&amp;&gt;</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">&lt;</span><span class="identifier">T</span><span class="special">&amp;&gt;</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 <20> 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/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="rebinding_semantics_for_assignment_of_optional_references.html"><img src="../../../../../doc/html/images/next.png" alt="Next"></a>
</div>
</body>
</html>

View File

@ -0,0 +1,148 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<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<65>1.<2E>Boost.Optional">
<link rel="up" href="../index.html" title="Chapter<65>1.<2E>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="../../../../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/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="in_place_factories.html"><img src="../../../../../doc/html/images/next.png" alt="Next"></a>
</div>
<div class="section" title="Rebinding semantics for assignment of optional references">
<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">&lt;</span><span class="identifier">T</span><span class="special">&amp;&gt;</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">&amp;</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">&lt;</span><span class="keyword">int</span><span class="special">&amp;&gt;</span> <span class="identifier">ora</span> <span class="special">;</span>
<span class="identifier">optional</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&amp;&gt;</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; it's 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">&amp;</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">&amp;</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">&lt;</span><span class="identifier">T</span><span class="special">&amp;&gt;</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">&amp;</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">&amp;</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">&lt;</span><span class="keyword">int</span><span class="special">&amp;&gt;</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">&lt;</span><span class="keyword">int</span><span class="special">&amp;&gt;</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="id579234"></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">&lt;</span><span class="identifier">U</span><span class="special">&gt;</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">&amp;</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">&lt;</span><span class="identifier">T</span><span class="special">&amp;&gt;</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">&lt;</span><span class="keyword">int</span><span class="special">&amp;&gt;</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">&amp;</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">&lt;</span><span class="keyword">int</span><span class="special">&amp;&gt;</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">&lt;</span><span class="identifier">T</span><span class="special">&amp;&gt;</span></code>
would assign just like <code class="computeroutput"><span class="identifier">T</span><span class="special">&amp;</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 consistency.
</p>
<p>
If in your code rebinding to another object is not an option, then is very
likely that binding for the fist time isn't either. In such case, assignment
to an <span class="emphasis"><em>uninitialized </em></span> <code class="computeroutput"><span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&amp;&gt;</span></code>
shall be prohibited. It is quite possible that in such scenario the precondition
that the lvalue must be already initialized exist. If it doesn't, then binding
for the first time is OK while rebinding is not which is IMO very unlikely.
In such 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 <20> 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/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="in_place_factories.html"><img src="../../../../../doc/html/images/next.png" alt="Next"></a>
</div>
</body>
</html>

View File

@ -0,0 +1,150 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<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<65>1.<2E>Boost.Optional">
<link rel="up" href="../index.html" title="Chapter<65>1.<2E>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="../../../../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/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="detailed_semantics.html"><img src="../../../../../doc/html/images/next.png" alt="Next"></a>
</div>
<div class="section" title="Synopsis">
<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"><span class="keyword">namespace</span> <span class="identifier">boost</span> <span class="special">{</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</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">&amp;</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">&amp;</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">&amp;</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">&lt;</span><span class="keyword">class</span> <span class="identifier">U</span><span class="special">&gt;</span> <span class="keyword">explicit</span> <span class="identifier">optional</span> <span class="special">(</span> <span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">U</span><span class="special">&gt;</span> <span class="keyword">const</span><span class="special">&amp;</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">&lt;</span><span class="keyword">class</span> <span class="identifier">InPlaceFactory</span><span class="special">&gt;</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">&amp;</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">&lt;</span><span class="keyword">class</span> <span class="identifier">TypedInPlaceFactory</span><span class="special">&gt;</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">&amp;</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">&amp;</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">&amp;</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">&amp;</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">&amp;</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">&amp;</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">&lt;</span><span class="keyword">class</span> <span class="identifier">U</span><span class="special">&gt;</span> <span class="identifier">optional</span><span class="special">&amp;</span> <span class="keyword">operator</span> <span class="special">=</span> <span class="special">(</span> <span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">U</span><span class="special">&gt;</span> <span class="keyword">const</span><span class="special">&amp;</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">&lt;</span><span class="keyword">class</span> <span class="identifier">InPlaceFactory</span><span class="special">&gt;</span> <span class="identifier">optional</span><span class="special">&amp;</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">&amp;</span> <span class="identifier">f</span> <span class="special">)</span> <span class="special">;</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">TypedInPlaceFactory</span><span class="special">&gt;</span> <span class="identifier">optional</span><span class="special">&amp;</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">&amp;</span> <span class="identifier">f</span> <span class="special">)</span> <span class="special">;</span>
<span class="identifier">T</span> <span class="keyword">const</span><span class="special">&amp;</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">&amp;</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">&amp;</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">&amp;</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">-&gt;()</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">-&gt;()</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">&amp;</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">&amp;</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">&amp;</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">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</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">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">x</span><span class="special">,</span> <span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="keyword">const</span><span class="special">&amp;</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">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</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">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">x</span><span class="special">,</span> <span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="keyword">const</span><span class="special">&amp;</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">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span> <span class="keyword">inline</span> <span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">&lt;</span> <span class="special">(</span> <span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">x</span><span class="special">,</span> <span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="keyword">const</span><span class="special">&amp;</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">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span> <span class="keyword">inline</span> <span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">&gt;</span> <span class="special">(</span> <span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">x</span><span class="special">,</span> <span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="keyword">const</span><span class="special">&amp;</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">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span> <span class="keyword">inline</span> <span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">&lt;=</span> <span class="special">(</span> <span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">x</span><span class="special">,</span> <span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="keyword">const</span><span class="special">&amp;</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">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span> <span class="keyword">inline</span> <span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">&gt;=</span> <span class="special">(</span> <span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">x</span><span class="special">,</span> <span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="keyword">const</span><span class="special">&amp;</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">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span> <span class="keyword">inline</span> <span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="identifier">make_optional</span> <span class="special">(</span> <span class="identifier">T</span> <span class="keyword">const</span><span class="special">&amp;</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">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span> <span class="keyword">inline</span> <span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</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">&amp;</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">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span> <span class="keyword">inline</span> <span class="identifier">T</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">get_optional_value_or</span> <span class="special">(</span> <span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">opt</span><span class="special">,</span> <span class="identifier">T</span> <span class="keyword">const</span><span class="special">&amp;</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">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span> <span class="keyword">inline</span> <span class="identifier">T</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">get</span> <span class="special">(</span> <span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="keyword">const</span><span class="special">&amp;</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">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span> <span class="keyword">inline</span> <span class="identifier">T</span><span class="special">&amp;</span> <span class="identifier">get</span> <span class="special">(</span> <span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</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">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</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">&lt;</span><span class="identifier">T</span><span class="special">&gt;</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">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</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">&lt;</span><span class="identifier">T</span><span class="special">&gt;*</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">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</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">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="keyword">const</span><span class="special">&amp;</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">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</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">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&amp;</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">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</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">&lt;</span><span class="identifier">T</span><span class="special">&gt;&amp;</span> <span class="identifier">x</span><span class="special">,</span> <span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;&amp;</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 <20> 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/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="detailed_semantics.html"><img src="../../../../../doc/html/images/next.png" alt="Next"></a>
</div>
</body>
</html>

View File

@ -0,0 +1,53 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<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<65>1.<2E>Boost.Optional">
<link rel="up" href="../index.html" title="Chapter<65>1.<2E>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="../../../../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/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="implementation_notes.html"><img src="../../../../../doc/html/images/next.png" alt="Next"></a>
</div>
<div class="section" title="Type requirements">
<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 <20> 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/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="implementation_notes.html"><img src="../../../../../doc/html/images/next.png" alt="Next"></a>
</div>
</body>
</html>

582
doc/html/boostbook.css Normal file
View 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;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 293 B

BIN
doc/html/images/space.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 B

175
doc/html/index.html Normal file
View File

@ -0,0 +1,175 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Chapter<EFBFBD>1.<2E>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<65>1.<2E>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="../../../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/html/images/next.png" alt="Next"></a></div>
<div class="chapter" title="Chapter<65>1.<2E>Boost.Optional">
<div class="titlepage"><div>
<div><h2 class="title">
<a name="optional"></a>Chapter<EFBFBD>1.<2E>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 <20> 2003 -2007 Fernando Luis Cacciola Carballal</p></div>
<div><div class="legalnotice" title="Legal Notice">
<a name="id553943"></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&lt;bool&gt;</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" title="Motivation">
<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">&lt;</span><span class="identifier">point</span><span class="special">,</span><span class="keyword">bool</span><span class="special">&gt;</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">&lt;</span><span class="identifier">T</span><span class="special">,</span><span class="keyword">bool</span><span class="special">&gt;</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">&lt;</span><span class="keyword">char</span><span class="special">,</span><span class="keyword">bool</span><span class="special">&gt;</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">&lt;</span><span class="identifier">point</span><span class="special">,</span><span class="keyword">bool</span><span class="special">&gt;</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 inexistent
results:
</p>
<pre class="programlisting"><span class="identifier">std</span><span class="special">::</span><span class="identifier">pair</span><span class="special">&lt;</span><span class="identifier">point</span><span class="special">,</span><span class="keyword">bool</span><span class="special">&gt;</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>
<p>
</p>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"><p><small>Last revised: November 20, 2009 at 10:24:28 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/html/images/next.png" alt="Next"></a></div>
</body>
</html>

View 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]

File diff suppressed because it is too large Load Diff

126
doc/optional.qbk Normal file
View 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 inexistent
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]

881
doc/reference.qbk Normal file
View File

@ -0,0 +1,881 @@
[/
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]
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& const& rhs ) ;`]
* [*Effect:] (Re)binds thee 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_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
View 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; it's 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 consistency.
If in your code rebinding to another object is not an option, then is very
likely that binding for the fist time isn't either. In such case, assignment
to an ['uninitialized ] `optional<T&>` shall be prohibited. It is quite possible
that in such scenario the precondition that the lvalue must be already
initialized exist. If it doesn't, then binding for the first time is OK
while rebinding is not which is IMO very unlikely.
In such 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]

View File

@ -4,7 +4,7 @@
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/lib/optional for documentation.
// See http://www.boost.org/libs/optional for documentation.
//
// You are welcome to contact the author at:
// fernando_cacciola@hotmail.com

View File

@ -1,10 +1,10 @@
// 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
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/lib/optional for documentation.
// See http://www.boost.org/libs/optional for documentation.
//
// You are welcome to contact the author at:
// fernando_cacciola@hotmail.com
@ -16,14 +16,11 @@
// 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 {
namespace {
none_t const none = ((none_t)0) ;
}
none_t const none = (static_cast<none_t>(0)) ;
} // namespace boost

View File

@ -4,7 +4,7 @@
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/lib/optional for documentation.
// See http://www.boost.org/libs/optional for documentation.
//
// You are welcome to contact the author at:
// fernando_cacciola@hotmail.com

View File

@ -4,7 +4,7 @@
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/lib/optional for documentation.
// See http://www.boost.org/libs/optional for documentation.
//
// You are welcome to contact the author at:
// fernando_cacciola@hotmail.com

View File

@ -1,35 +1,42 @@
// Copyright (C) 2003, Fernando Luis Cacciola Carballal.
// 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/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
//
// 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 <new>
#include <algorithm>
#include "boost/config.hpp"
#include "boost/assert.hpp"
#include "boost/type.hpp"
#include "boost/type_traits/alignment_of.hpp"
#include "boost/type_traits/type_with_alignment.hpp"
#include "boost/type_traits/remove_reference.hpp"
#include "boost/type_traits/is_reference.hpp"
#include "boost/mpl/if.hpp"
#include "boost/mpl/bool.hpp"
#include "boost/mpl/not.hpp"
#include "boost/detail/reference_content.hpp"
#include "boost/none_t.hpp"
#include "boost/utility/compare_pointees.hpp"
#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"
#include <boost/optional/optional_fwd.hpp>
#if BOOST_WORKAROUND(BOOST_MSVC, == 1200)
// VC6.0 has the following bug:
@ -76,12 +83,37 @@
#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"
@ -92,7 +124,12 @@ template <class T>
class aligned_storage
{
// Borland ICEs if unnamed unions are used for this!
union dummy_u
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<
@ -101,8 +138,13 @@ class aligned_storage
public:
void const* address() const { return &dummy_.data[0]; }
void * address() { return &dummy_.data[0]; }
#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>
@ -133,7 +175,11 @@ class optional_base : public optional_tag
{
private :
typedef BOOST_DEDUCED_TYPENAME detail::make_reference_content<T>::type internal_type ;
typedef
#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
BOOST_DEDUCED_TYPENAME
#endif
::boost::detail::make_reference_content<T>::type internal_type ;
typedef aligned_storage<internal_type> storage_type ;
@ -151,8 +197,10 @@ class optional_base : public optional_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 ;
@ -169,7 +217,7 @@ class optional_base : public optional_tag
// Creates an optional<T> uninitialized.
// No-throw
optional_base ( none_t const& )
optional_base ( none_t )
:
m_initialized(false) {}
@ -182,6 +230,16 @@ class optional_base : public optional_tag
construct(val);
}
// Creates an optional<T> initialized with 'val' IFF cond is true, otherwise creates an uninitialzed optional<T>.
// Can throw if T::T(T const&) does
optional_base ( bool cond, argument_type val )
:
m_initialized(false)
{
if ( cond )
construct(val);
}
// Creates a deep copy of another optional<T>
// Can throw if T::T(T const&) does
optional_base ( optional_base const& rhs )
@ -252,7 +310,7 @@ class optional_base : public optional_tag
// Assigns from "none", destroying the current value, if any, leaving this UNINITIALIZED
// No-throw (assuming T::~T() doesn't)
void assign ( none_t const& ) { destroy(); }
void assign ( none_t ) { destroy(); }
#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
template<class Expr>
@ -295,7 +353,7 @@ class optional_base : public optional_tag
void construct ( Expr const& factory, in_place_factory_base const* )
{
BOOST_STATIC_ASSERT ( ::boost::mpl::not_<is_reference_predicate>::value ) ;
factory.BOOST_NESTED_TEMPLATE apply<value_type>(m_storage.address()) ;
boost_optional_detail::construct<value_type>(factory, m_storage.address());
m_initialized = true ;
}
@ -392,8 +450,22 @@ class optional_base : public optional_tag
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 ; }
@ -414,6 +486,8 @@ class optional_base : public optional_tag
// the following olverloads are used to filter out the case and guarantee an error in case of T being a reference.
pointer_const_type cast_ptr( internal_type const* p, is_not_reference_tag ) const { return p ; }
pointer_type cast_ptr( internal_type * p, is_not_reference_tag ) { return p ; }
pointer_const_type cast_ptr( internal_type const* p, is_reference_tag ) const { return &p->get() ; }
pointer_type cast_ptr( internal_type * p, is_reference_tag ) { return &p->get() ; }
bool m_initialized ;
storage_type m_storage ;
@ -445,12 +519,15 @@ class optional : public optional_detail::optional_base<T>
// Creates an optional<T> uninitialized.
// No-throw
optional( none_t const& none_ ) : base(none_) {}
optional( none_t none_ ) : base(none_) {}
// Creates an optional<T> initialized with 'val'.
// Can throw if T::T(T const&) does
optional ( argument_type val ) : base(val) {}
// Creates an optional<T> initialized with 'val' IFF cond is true, otherwise creates an uninitialized optional.
// Can throw if T::T(T const&) does
optional ( bool cond, argument_type val ) : base(cond,val) {}
#ifndef BOOST_OPTIONAL_NO_CONVERTING_COPY_CTOR
// NOTE: MSVC needs templated versions first
@ -479,12 +556,12 @@ class optional : public optional_detail::optional_base<T>
// Depending on the above some T ctor is called.
// Can throw is the resolved T ctor throws.
template<class Expr>
explicit optional ( Expr const& expr ) : base(expr,&expr) {}
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(rhs) {}
optional ( optional const& rhs ) : base( static_cast<base const&>(rhs) ) {}
// No-throw (assuming T::~T() doesn't)
~optional() {}
@ -493,9 +570,9 @@ class optional : public optional_detail::optional_base<T>
// Assigns from an expression. See corresponding constructor.
// Basic Guarantee: If the resolved T ctor throws, this is left UNINITIALIZED
template<class Expr>
optional& operator= ( Expr expr )
optional& operator= ( Expr const& expr )
{
this->assign_expr(expr,&expr);
this->assign_expr(expr,boost::addressof(expr));
return *this ;
}
#endif
@ -518,7 +595,7 @@ class optional : public optional_detail::optional_base<T>
// (NOTE: On BCB, this operator is not actually called and left is left UNMODIFIED in case of a throw)
optional& operator= ( optional const& rhs )
{
this->assign( rhs ) ;
this->assign( static_cast<base const&>(rhs) ) ;
return *this ;
}
@ -533,18 +610,30 @@ class optional : public optional_detail::optional_base<T>
// Assigns from a "none"
// Which destroys the current value, if any, leaving this UNINITIALIZED
// No-throw (assuming T::~T() doesn't)
optional& operator= ( none_t const& none_ )
optional& operator= ( none_t none_ )
{
this->assign( none_ ) ;
return *this ;
}
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
@ -561,11 +650,27 @@ class optional : public optional_detail::optional_base<T>
// 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() ; }
// 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>
@ -602,6 +707,24 @@ get ( optional<T>* opt )
return opt->get_ptr() ;
}
// Returns a reference to the value if this is initialized, otherwise, the behaviour is UNDEFINED.
// No-throw
template<class T>
inline
BOOST_DEDUCED_TYPENAME optional<T>::reference_const_type
get_optional_value_or ( optional<T> const& opt, BOOST_DEDUCED_TYPENAME optional<T>::reference_const_type v )
{
return opt.get_value_or(v) ;
}
template<class T>
inline
BOOST_DEDUCED_TYPENAME optional<T>::reference_type
get_optional_value_or ( optional<T>& opt, BOOST_DEDUCED_TYPENAME optional<T>::reference_type v )
{
return opt.get_value_or(v) ;
}
// Returns a pointer to the value if this is initialized, otherwise, returns NULL.
// No-throw
template<class T>
@ -623,6 +746,11 @@ get_pointer ( optional<T>& opt )
// optional's relational operators ( ==, !=, <, >, <=, >= ) have deep-semantics (compare values).
// WARNING: This is UNLIKE pointers. Use equal_pointees()/less_pointess() in generic code instead.
//
// optional<T> vs optional<T> cases
//
template<class T>
inline
bool operator == ( optional<T> const& x, optional<T> const& y )
@ -653,122 +781,211 @@ inline
bool operator >= ( optional<T> const& x, optional<T> const& y )
{ return !( x < y ) ; }
//
// optional<T> vs T cases
//
template<class T>
inline
bool operator == ( optional<T> const& x, none_t const& )
bool operator == ( optional<T> const& x, T const& y )
{ return equal_pointees(x, optional<T>(y)); }
template<class T>
inline
bool operator < ( optional<T> const& x, T const& y )
{ return less_pointees(x, optional<T>(y)); }
template<class T>
inline
bool operator != ( optional<T> const& x, T const& y )
{ return !( x == y ) ; }
template<class T>
inline
bool operator > ( optional<T> const& x, T const& y )
{ return y < x ; }
template<class T>
inline
bool operator <= ( optional<T> const& x, T const& y )
{ return !( y < x ) ; }
template<class T>
inline
bool operator >= ( optional<T> const& x, T const& y )
{ return !( x < y ) ; }
//
// T vs optional<T> cases
//
template<class T>
inline
bool operator == ( T const& x, optional<T> const& y )
{ return equal_pointees( optional<T>(x), y ); }
template<class T>
inline
bool operator < ( T const& x, optional<T> const& y )
{ return less_pointees( optional<T>(x), y ); }
template<class T>
inline
bool operator != ( T const& x, optional<T> const& y )
{ return !( x == y ) ; }
template<class T>
inline
bool operator > ( T const& x, optional<T> const& y )
{ return y < x ; }
template<class T>
inline
bool operator <= ( T const& x, optional<T> const& y )
{ return !( y < x ) ; }
template<class T>
inline
bool operator >= ( T const& x, optional<T> const& y )
{ return !( x < y ) ; }
//
// optional<T> vs none cases
//
template<class T>
inline
bool operator == ( optional<T> const& x, none_t )
{ return equal_pointees(x, optional<T>() ); }
template<class T>
inline
bool operator < ( optional<T> const& x, none_t const& )
bool operator < ( optional<T> const& x, none_t )
{ return less_pointees(x,optional<T>() ); }
template<class T>
inline
bool operator != ( optional<T> const& x, none_t const& y )
bool operator != ( optional<T> const& x, none_t y )
{ return !( x == y ) ; }
template<class T>
inline
bool operator > ( optional<T> const& x, none_t const& y )
bool operator > ( optional<T> const& x, none_t y )
{ return y < x ; }
template<class T>
inline
bool operator <= ( optional<T> const& x, none_t const& y )
bool operator <= ( optional<T> const& x, none_t y )
{ return !( y < x ) ; }
template<class T>
inline
bool operator >= ( optional<T> const& x, none_t const& y )
bool operator >= ( optional<T> const& x, none_t y )
{ return !( x < y ) ; }
//
// none vs optional<T> cases
//
template<class T>
inline
bool operator == ( none_t const& x, optional<T> const& y )
bool operator == ( none_t x, optional<T> const& y )
{ return equal_pointees(optional<T>() ,y); }
template<class T>
inline
bool operator < ( none_t const& x, optional<T> const& y )
bool operator < ( none_t x, optional<T> const& y )
{ return less_pointees(optional<T>() ,y); }
template<class T>
inline
bool operator != ( none_t const& x, optional<T> const& y )
bool operator != ( none_t x, optional<T> const& y )
{ return !( x == y ) ; }
template<class T>
inline
bool operator > ( none_t const& x, optional<T> const& y )
bool operator > ( none_t x, optional<T> const& y )
{ return y < x ; }
template<class T>
inline
bool operator <= ( none_t const& x, optional<T> const& y )
bool operator <= ( none_t x, optional<T> const& y )
{ return !( y < x ) ; }
template<class T>
inline
bool operator >= ( none_t const& x, optional<T> const& y )
bool operator >= ( none_t x, optional<T> const& y )
{ return !( x < y ) ; }
//
// The following swap implementation follows the GCC workaround as found in
// "boost/detail/compressed_pair.hpp"
//
namespace optional_detail {
// GCC < 3.2 gets the using declaration at namespace scope (FLC, DWA)
#if BOOST_WORKAROUND(__GNUC__, < 3) \
|| BOOST_WORKAROUND(__GNUC__, == 3) && __GNUC_MINOR__ <= 2
using std::swap;
#define BOOST_OPTIONAL_STD_SWAP_INTRODUCED_AT_NS_SCOPE
#endif
template<bool use_default_constructor> struct swap_selector;
// optional's swap:
// If both are initialized, calls swap(T&, T&). If this swap throws, both will remain initialized but their values are now unspecified.
// If only one is initialized, calls U.reset(*I), THEN I.reset().
// If U.reset(*I) throws, both are left UNCHANGED (U is kept uinitialized and I is never reset)
// If both are uninitialized, do nothing (no-throw)
template<class T>
inline
void optional_swap ( optional<T>& x, optional<T>& y )
template<>
struct swap_selector<true>
{
if ( !x && !!y )
{
x.reset(*y);
y.reset();
}
else if ( !!x && !y )
{
y.reset(*x);
x.reset();
}
else if ( !!x && !!y )
{
// GCC > 3.2 and all other compilers have the using declaration at function scope (FLC)
#ifndef BOOST_OPTIONAL_STD_SWAP_INTRODUCED_AT_NS_SCOPE
// allow for Koenig lookup
using std::swap ;
#endif
swap(*x,*y);
}
}
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::optional_swap(x,y);
}
template<class T> inline optional<T> make_optional ( T const& v )
{
return optional<T>(v);
optional_detail::swap_selector<optional_swap_should_use_default_constructor<T>::value>::optional_swap(x, y);
}
} // namespace boost
#endif

View File

@ -1,14 +1,17 @@
// Copyright (C) 2003, Fernando Luis Cacciola Carballal.
// 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/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
//
// 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
@ -16,6 +19,10 @@ 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

View File

@ -4,7 +4,7 @@
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/lib/optional for documentation.
// See http://www.boost.org/libs/optional for documentation.
//
// You are welcome to contact the author at:
// fernando_cacciola@hotmail.com
@ -13,19 +13,20 @@
#define BOOST_OPTIONAL_OPTIONAL_IO_FLC_19NOV2002_HPP
#if defined __GNUC__
# if (__GNUC__ == 2 && __GNUC_MINOR__ <= 97)
# 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
#else
# include <istream>
# include <ostream>
#endif
#endif
#include <boost/none.hpp>
#include <boost/assert.hpp>
#include "boost/optional/optional.hpp"
#include "boost/utility/value_init.hpp"
@ -62,17 +63,30 @@ std::basic_istream<CharType, CharTrait>&
operator>>(std::basic_istream<CharType, CharTrait>& in, optional<T>& v)
#endif
{
if ( in.good() )
if (in.good())
{
int d = in.get();
if ( d == ' ' )
if (d == ' ')
{
T x ;
T x;
in >> x;
v = x ;
v = x;
}
else
v = optional<T>() ;
{
if (d == '-')
{
d = in.get();
if (d == '-')
{
v = none;
return in;
}
}
in.setstate( std::ios::failbit );
}
}
return in;

View File

@ -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>.&nbsp;<hr>
<p><EFBFBD> Copyright Beman Dawes, 2001</p>
<p>Distributed under the Boost Software License, Version 1.0. (See accompanying
file <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or copy
at <a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a>)</p>
</body>
</html>
</html>

View File

@ -1 +0,0 @@
bin

View File

@ -1,37 +0,0 @@
# Boost.Optional Library test Jamfile
#
# Copyright (C) 2003, Fernando Luis Cacciola Carballal.
#
# Use, modification, and distribution is subject to the Boost Software
# License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
#
subproject libs/optional/test ;
# bring in rules for testing
SEARCH on testing.jam = $(BOOST_BUILD_PATH) ;
include testing.jam ;
# Make tests run by default.
DEPENDS all : test ;
{
test-suite optional :
[ run optional_test.cpp ]
[ run optional_test_tie.cpp ]
[ run optional_test_ref.cpp ]
[ run optional_test_inplace.cpp ]
[ run optional_test_io.cpp ]
[ compile-fail optional_test_fail1.cpp ]
[ compile-fail optional_test_fail2.cpp ]
[ compile-fail optional_test_fail3a.cpp ]
[ compile-fail optional_test_fail3b.cpp ]
[ compile-fail optional_test_ref_fail1.cpp ]
[ compile-fail optional_test_ref_fail2.cpp ]
[ compile-fail optional_test_ref_fail3.cpp ]
[ compile-fail optional_test_ref_fail4.cpp ]
[ compile-fail optional_test_inplace_fail.cpp ]
[ compile-fail optional_test_inplace_fail2.cpp ]
;
}

View File

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

View File

@ -1,4 +1,4 @@
// Copyright (C) 2003, Fernando Luis Cacciola Carballal.
// 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
@ -9,13 +9,20 @@
// You are welcome to contact the author at:
// fernando_cacciola@hotmail.com
//
// Revisions:
// 12 May 2008 (added more swap tests)
//
#include<iostream>
#include<stdexcept>
#include<string>
#define BOOST_ENABLE_ASSERT_HANDLER
#include "boost/optional.hpp"
#include "boost/bind/apply.hpp" // Included just to test proper interaction with boost::apply<> as reported by Daniel Wallin
#include "boost/mpl/bool.hpp"
#include "boost/mpl/bool_fwd.hpp" // For mpl::true_ and mpl::false_
#include "boost/optional/optional.hpp"
#ifdef __BORLANDC__
#pragma hdrstop
@ -151,6 +158,95 @@ void test_basics( T const* )
ob.reset();
check_is_pending_dtor( ARG(T) ) ;
check_uninitialized(ob);
}
template<class T>
void test_conditional_ctor_and_get_valur_or ( T const* )
{
TRACE( std::endl << BOOST_CURRENT_FUNCTION );
T a(321);
T z(123);
optional<T> const cdef0(false,a);
optional<T> def0(false,a);
optional<T> def1 = boost::make_optional(false,a); // T is not within boost so ADL won't find make_optional unqualified
check_uninitialized(def0);
check_uninitialized(def1);
optional<T> const co0(true,a);
optional<T> o0(true,a);
optional<T> o1 = boost::make_optional(true,a); // T is not within boost so ADL won't find make_optional unqualified
check_initialized(o0);
check_initialized(o1);
check_value(o0,a,z);
check_value(o1,a,z);
T b = def0.get_value_or(z);
BOOST_CHECK( b == z ) ;
b = get_optional_value_or(def0,z);
BOOST_CHECK( b == z ) ;
b = o0.get_value_or(z);
BOOST_CHECK( b == a ) ;
b = get_optional_value_or(o0,z);
BOOST_CHECK( b == a ) ;
T const& crz = z ;
T& rz = z ;
T const& crzz = def0.get_value_or(crz);
BOOST_CHECK( crzz == crz ) ;
T& rzz = def0.get_value_or(rz);
BOOST_CHECK( rzz == rz ) ;
T const& crzzz = get_optional_value_or(cdef0,crz);
BOOST_CHECK( crzzz == crz ) ;
T& rzzz = get_optional_value_or(def0,rz);
BOOST_CHECK( rzzz == rz ) ;
T const& crb = o0.get_value_or(crz);
BOOST_CHECK( crb == a ) ;
T& rb = o0.get_value_or(rz);
BOOST_CHECK( rb == b ) ;
T const& crbb = get_optional_value_or(co0,crz);
BOOST_CHECK( crbb == b ) ;
T const& crbbb = get_optional_value_or(o0,crz);
BOOST_CHECK( crbbb == b ) ;
T& rbb = get_optional_value_or(o0,rz);
BOOST_CHECK( rbb == b ) ;
T& ra = a ;
optional<T&> defref(false,ra);
BOOST_CHECK(!defref);
optional<T&> ref(true,ra);
BOOST_CHECK(!!ref);
a = T(432);
BOOST_CHECK( *ref == a ) ;
T& r1 = defref.get_value_or(z);
BOOST_CHECK( r1 == z ) ;
T& r2 = ref.get_value_or(z);
BOOST_CHECK( r2 == a ) ;
}
//
@ -613,9 +709,9 @@ void test_relops( T const* )
{
TRACE( std::endl << BOOST_CURRENT_FUNCTION );
T v0(18);
T v1(19);
T v2(19);
T v0(0);
T v1(1);
T v2(1);
optional<T> def0 ;
optional<T> def1 ;
@ -660,6 +756,33 @@ void test_relops( T const* )
BOOST_CHECK ( opt1 > opt0 ) ;
BOOST_CHECK ( opt1 <= opt2 ) ;
BOOST_CHECK ( opt1 >= opt0 ) ;
// Compare against a value directly
BOOST_CHECK ( opt0 == v0 ) ;
BOOST_CHECK ( opt0 != v1 ) ;
BOOST_CHECK ( opt1 == v2 ) ;
BOOST_CHECK ( opt0 < v1 ) ;
BOOST_CHECK ( opt1 > v0 ) ;
BOOST_CHECK ( opt1 <= v2 ) ;
BOOST_CHECK ( opt1 >= v0 ) ;
BOOST_CHECK ( v0 != opt1 ) ;
BOOST_CHECK ( v1 == opt2 ) ;
BOOST_CHECK ( v0 < opt1 ) ;
BOOST_CHECK ( v1 > opt0 ) ;
BOOST_CHECK ( v1 <= opt2 ) ;
BOOST_CHECK ( v1 >= opt0 ) ;
BOOST_CHECK ( def0 != v0 ) ;
BOOST_CHECK ( !(def0 == v0) ) ;
BOOST_CHECK ( def0 < v0 ) ;
BOOST_CHECK ( !(def0 > v0) ) ;
BOOST_CHECK ( def0 <= v0 ) ;
BOOST_CHECK ( !(def0 >= v0) ) ;
BOOST_CHECK ( v0 != def0 ) ;
BOOST_CHECK ( !(v0 == def0) ) ;
BOOST_CHECK ( !(v0 < def0) ) ;
BOOST_CHECK ( v0 > def0 ) ;
BOOST_CHECK ( !(v0 <= def0) ) ;
BOOST_CHECK ( v0 >= opt0 ) ;
}
template<class T>
@ -676,6 +799,10 @@ void test_none( T const* )
BOOST_CHECK ( def0 == none ) ;
BOOST_CHECK ( non_def != none ) ;
BOOST_CHECK ( !def1 ) ;
BOOST_CHECK ( !(non_def < none) ) ;
BOOST_CHECK ( non_def > none ) ;
BOOST_CHECK ( !(non_def <= none) ) ;
BOOST_CHECK ( non_def >= none ) ;
non_def = none ;
BOOST_CHECK ( !non_def ) ;
@ -683,11 +810,30 @@ void test_none( T const* )
test_default_implicit_construction(T(1),none);
}
template<class T>
void test_arrow( T const* )
{
TRACE( std::endl << BOOST_CURRENT_FUNCTION );
T a(1234);
optional<T> oa(a) ;
optional<T> const coa(a) ;
BOOST_CHECK ( coa->V() == 1234 ) ;
oa->V() = 4321 ;
BOOST_CHECK ( a.V() = 1234 ) ;
BOOST_CHECK ( (*oa).V() = 4321 ) ;
}
void test_with_builtin_types()
{
TRACE( std::endl << BOOST_CURRENT_FUNCTION );
test_basics( ARG(double) );
test_conditional_ctor_and_get_valur_or( ARG(double) );
test_uninitialized_access( ARG(double) );
test_no_throwing_swap( ARG(double) );
test_relops( ARG(double) ) ;
@ -699,6 +845,7 @@ void test_with_class_type()
TRACE( std::endl << BOOST_CURRENT_FUNCTION );
test_basics( ARG(X) );
test_conditional_ctor_and_get_valur_or( ARG(X) );
test_direct_value_manip( ARG(X) );
test_uninitialized_access( ARG(X) );
test_throwing_direct_init( ARG(X) );
@ -711,6 +858,7 @@ void test_with_class_type()
test_throwing_swap( ARG(X) );
test_relops( ARG(X) ) ;
test_none( ARG(X) ) ;
test_arrow( ARG(X) ) ;
BOOST_CHECK ( X::count == 0 ) ;
}
@ -784,6 +932,364 @@ void test_conversions2()
BOOST_CHECK(*get(&opt1) == static_cast<double>(f));
}
namespace optional_swap_test
{
class default_ctor_exception : public std::exception {} ;
class copy_ctor_exception : public std::exception {} ;
class assignment_exception : public std::exception {} ;
//
// Base class for swap test classes. Its assignment should not be called, when swapping
// optional<T> objects. (The default std::swap would do so.)
//
class base_class_with_forbidden_assignment
{
public:
base_class_with_forbidden_assignment & operator=(const base_class_with_forbidden_assignment &)
{
BOOST_CHECK(!"The assignment should not be used while swapping!");
throw assignment_exception();
}
virtual ~base_class_with_forbidden_assignment() {}
};
//
// Class without default constructor
//
class class_without_default_ctor : public base_class_with_forbidden_assignment
{
public:
char data;
explicit class_without_default_ctor(char arg) : data(arg) {}
};
//
// Class whose default constructor should not be used by optional::swap!
//
class class_whose_default_ctor_should_not_be_used : public base_class_with_forbidden_assignment
{
public:
char data;
explicit class_whose_default_ctor_should_not_be_used(char arg) : data(arg) {}
class_whose_default_ctor_should_not_be_used()
{
BOOST_CHECK(!"This default constructor should not be used while swapping!");
throw default_ctor_exception();
}
};
//
// Class whose default constructor should be used by optional::swap.
// Its copy constructor should be avoided!
//
class class_whose_default_ctor_should_be_used : public base_class_with_forbidden_assignment
{
public:
char data;
explicit class_whose_default_ctor_should_be_used(char arg) : data(arg) { }
class_whose_default_ctor_should_be_used() : data('\0') { }
class_whose_default_ctor_should_be_used(const class_whose_default_ctor_should_be_used &)
{
BOOST_CHECK(!"This copy constructor should not be used while swapping!");
throw copy_ctor_exception();
}
};
//
// Class template whose default constructor should be used by optional::swap.
// Its copy constructor should be avoided!
//
template <class T>
class template_whose_default_ctor_should_be_used : public base_class_with_forbidden_assignment
{
public:
T data;
explicit template_whose_default_ctor_should_be_used(T arg) : data(arg) { }
template_whose_default_ctor_should_be_used() : data('\0') { }
template_whose_default_ctor_should_be_used(const template_whose_default_ctor_should_be_used &)
{
BOOST_CHECK(!"This copy constructor should not be used while swapping!");
throw copy_ctor_exception();
}
};
//
// Class whose explicit constructor should be used by optional::swap.
// Its other constructors should be avoided!
//
class class_whose_explicit_ctor_should_be_used : public base_class_with_forbidden_assignment
{
public:
char data;
explicit class_whose_explicit_ctor_should_be_used(char arg) : data(arg) { }
class_whose_explicit_ctor_should_be_used()
{
BOOST_CHECK(!"This default constructor should not be used while swapping!");
throw default_ctor_exception();
}
class_whose_explicit_ctor_should_be_used(const class_whose_explicit_ctor_should_be_used &)
{
BOOST_CHECK(!"This copy constructor should not be used while swapping!");
throw copy_ctor_exception();
}
};
void swap(class_whose_default_ctor_should_not_be_used & lhs, class_whose_default_ctor_should_not_be_used & rhs)
{
std::swap(lhs.data, rhs.data);
}
void swap(class_whose_default_ctor_should_be_used & lhs, class_whose_default_ctor_should_be_used & rhs)
{
std::swap(lhs.data, rhs.data);
}
void swap(class_without_default_ctor & lhs, class_without_default_ctor & rhs)
{
std::swap(lhs.data, rhs.data);
}
void swap(class_whose_explicit_ctor_should_be_used & lhs, class_whose_explicit_ctor_should_be_used & rhs)
{
std::swap(lhs.data, rhs.data);
}
template <class T>
void swap(template_whose_default_ctor_should_be_used<T> & lhs, template_whose_default_ctor_should_be_used<T> & rhs)
{
std::swap(lhs.data, rhs.data);
}
//
// optional<T>::swap should be customized when neither the copy constructor
// nor the default constructor of T are supposed to be used when swapping, e.g.,
// for the following type T = class_whose_explicit_ctor_should_be_used.
//
void swap(boost::optional<class_whose_explicit_ctor_should_be_used> & x, boost::optional<class_whose_explicit_ctor_should_be_used> & y)
{
bool hasX = x;
bool hasY = y;
if ( !hasX && !hasY )
return;
if( !hasX )
x = boost::in_place('\0');
else if ( !hasY )
y = boost::in_place('\0');
optional_swap_test::swap(*x,*y);
if( !hasX )
y = boost::none ;
else if( !hasY )
x = boost::none ;
}
} // End of namespace optional_swap_test.
namespace boost {
//
// Compile time tweaking on whether or not swap should use the default constructor:
//
template <> struct optional_swap_should_use_default_constructor<
optional_swap_test::class_whose_default_ctor_should_be_used> : mpl::true_ {} ;
template <> struct optional_swap_should_use_default_constructor<
optional_swap_test::class_whose_default_ctor_should_not_be_used> : mpl::false_ {} ;
template <class T> struct optional_swap_should_use_default_constructor<
optional_swap_test::template_whose_default_ctor_should_be_used<T> > : mpl::true_ {} ;
//
// Specialization of boost::swap:
//
template <>
void swap(optional<optional_swap_test::class_whose_explicit_ctor_should_be_used> & x, optional<optional_swap_test::class_whose_explicit_ctor_should_be_used> & y)
{
optional_swap_test::swap(x, y);
}
} // namespace boost
namespace std {
//
// Specializations of std::swap:
//
template <>
void swap(optional_swap_test::class_whose_default_ctor_should_be_used & x, optional_swap_test::class_whose_default_ctor_should_be_used & y)
{
optional_swap_test::swap(x, y);
}
template <>
void swap(optional_swap_test::class_whose_default_ctor_should_not_be_used & x, optional_swap_test::class_whose_default_ctor_should_not_be_used & y)
{
optional_swap_test::swap(x, y);
}
template <>
void swap(optional_swap_test::class_without_default_ctor & x, optional_swap_test::class_without_default_ctor & y)
{
optional_swap_test::swap(x, y);
}
template <>
void swap(optional_swap_test::class_whose_explicit_ctor_should_be_used & x, optional_swap_test::class_whose_explicit_ctor_should_be_used & y)
{
optional_swap_test::swap(x, y);
}
} // namespace std
//
// Tests whether the swap function works properly for optional<T>.
// Assumes that T has one data member, of type char.
// Returns true iff the test is passed.
//
template <class T>
bool test_swap_function( T const* )
{
const boost::unit_test::counter_t counter_before_test = boost::minimal_test::errors_counter();
try
{
optional<T> obj1;
optional<T> obj2('a');
// Self-swap should not have any effect.
swap(obj1, obj1);
swap(obj2, obj2);
BOOST_CHECK(!obj1);
BOOST_CHECK(!!obj2 && obj2->data == 'a');
// Call non-member swap.
swap(obj1, obj2);
// Test if obj1 and obj2 are really swapped.
BOOST_CHECK(!!obj1 && obj1->data == 'a');
BOOST_CHECK(!obj2);
// Call non-member swap one more time.
swap(obj1, obj2);
// Test if obj1 and obj2 are swapped back.
BOOST_CHECK(!obj1);
BOOST_CHECK(!!obj2 && obj2->data == 'a');
}
catch(const std::exception &)
{
// The swap function should not throw, for our test cases.
return false ;
}
return boost::minimal_test::errors_counter() == counter_before_test ;
}
//
// Tests whether the optional<T>::swap member function works properly.
// Assumes that T has one data member, of type char.
// Returns true iff the test is passed.
//
template <class T>
bool test_swap_member_function( T const* )
{
const boost::unit_test::counter_t counter_before_test = boost::minimal_test::errors_counter();
try
{
optional<T> obj1;
optional<T> obj2('a');
// Self-swap should not have any effect.
obj1.swap(obj1);
obj2.swap(obj2);
BOOST_CHECK(!obj1);
BOOST_CHECK(!!obj2 && obj2->data == 'a');
// Call member swap.
obj1.swap(obj2);
// Test if obj1 and obj2 are really swapped.
BOOST_CHECK(!!obj1 && obj1->data == 'a');
BOOST_CHECK(!obj2);
// Call member swap one more time.
obj1.swap(obj2);
// Test if obj1 and obj2 are swapped back.
BOOST_CHECK(!obj1);
BOOST_CHECK(!!obj2 && obj2->data == 'a');
}
catch(const std::exception &)
{
// The optional<T>::swap member function should not throw, for our test cases.
return false ;
}
return boost::minimal_test::errors_counter() == counter_before_test ;
}
//
// Tests compile time tweaking of swap, by means of
// optional_swap_should_use_default_constructor.
//
void test_swap_tweaking()
{
BOOST_CHECK( test_swap_function( ARG(optional_swap_test::class_without_default_ctor) ) );
BOOST_CHECK( test_swap_function( ARG(optional_swap_test::class_whose_default_ctor_should_be_used) ) );
BOOST_CHECK( test_swap_function( ARG(optional_swap_test::class_whose_default_ctor_should_not_be_used) ) );
BOOST_CHECK( test_swap_function( ARG(optional_swap_test::class_whose_explicit_ctor_should_be_used) ) );
BOOST_CHECK( test_swap_function( ARG(optional_swap_test::template_whose_default_ctor_should_be_used<char>) ) );
BOOST_CHECK( test_swap_member_function( ARG(optional_swap_test::class_without_default_ctor) ) );
BOOST_CHECK( test_swap_member_function( ARG(optional_swap_test::class_whose_default_ctor_should_be_used) ) );
BOOST_CHECK( test_swap_member_function( ARG(optional_swap_test::class_whose_default_ctor_should_not_be_used) ) );
BOOST_CHECK( test_swap_member_function( ARG(optional_swap_test::class_whose_explicit_ctor_should_be_used) ) );
BOOST_CHECK( test_swap_member_function( ARG(optional_swap_test::template_whose_default_ctor_should_be_used<char>) ) );
}
// Test for support for classes with overridden operator&
class CustomAddressOfClass
{
int n;
public:
CustomAddressOfClass() : n(0) {}
CustomAddressOfClass(CustomAddressOfClass const& that) : n(that.n) {}
explicit CustomAddressOfClass(int m) : n(m) {}
int* operator& () { return &n; }
bool operator== (CustomAddressOfClass const& that) const { return n == that.n; }
};
void test_custom_addressof_operator()
{
boost::optional< CustomAddressOfClass > o1(CustomAddressOfClass(10));
BOOST_CHECK(!!o1);
BOOST_CHECK(o1.get() == CustomAddressOfClass(10));
o1 = CustomAddressOfClass(20);
BOOST_CHECK(!!o1);
BOOST_CHECK(o1.get() == CustomAddressOfClass(20));
o1 = boost::none;
BOOST_CHECK(!o1);
}
int test_main( int, char* [] )
{
try
@ -793,6 +1299,8 @@ int test_main( int, char* [] )
test_no_implicit_conversions();
test_conversions1();
test_conversions2();
test_swap_tweaking();
test_custom_addressof_operator();
}
catch ( ... )
{

View File

@ -55,10 +55,14 @@ void test2( Opt o, Opt buff )
{
stringstream s ;
s << o ;
s >> buff ;
const int markv = 123 ;
int mark = 0 ;
s << o << " " << markv ;
s >> buff >> mark ;
BOOST_ASSERT( buff == o ) ;
BOOST_ASSERT( mark == markv ) ;
}
@ -77,7 +81,6 @@ int test_main( int, char* [] )
{
test(1,2);
test(string("hello"),string("buffer"));
test(string(""),string("buffer"));
}
catch ( ... )
{

View File

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

View File

@ -1,23 +0,0 @@
// Copyright (C) 2003, Fernando Luis Cacciola Carballal.
//
// Use, modification, and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/lib/optional for documentation.
//
// You are welcome to contact the author at:
// fernando_cacciola@hotmail.com
//
#include "boost/optional.hpp"
//
// THIS TEST SHOULD FAIL TO COMPILE
//
void optional_reference__test_no_ptr_access()
{
boost::optional<int&> opt ;
opt.get_ptr();
}