Unless T's constructor or assignment
- throws, optional<T> does
- not throw anything else on its own. A throw during assignment never changes
+ throws, assignments to optional<T>
+ do not throw anything else on its own. A throw during assignment never changes
the initialization state of any optional object involved:
+ Throws: Any exception thrown by the selected
+ constructor of T.
+
+
+ Notes: On compilers without rvalue reference
+ support the type of v becomes
+ Uconst&.
@@ -1264,6 +1288,9 @@
o,T&default);
+
+ Deprecated: Use value_or() instead.
+
Returns: A reference to the contained
value, if any, or default.
diff --git a/doc/html/boost_optional/synopsis.html b/doc/html/boost_optional/synopsis.html
index 0e2b20e..8a22968 100644
--- a/doc/html/boost_optional/synopsis.html
+++ b/doc/html/boost_optional/synopsis.html
@@ -81,9 +81,6 @@
Tconst&get()const;T&get();
- // [new in 1.34]
- Tconst&get_value_or(Tconst&default)const;
-
Tconst*operator->()const;T*operator->();
@@ -93,6 +90,8 @@
Tconst&value()const;T&value();
+ template<classU>Tvalue_or(U&&v)const;
+
Tconst*get_ptr()const;T*get_ptr();
@@ -111,6 +110,8 @@
// (deprecated)boolis_initialized()const;
+ // (deprecated)
+ Tconst&get_value_or(Tconst&default)const;};template<classT>inlinebooloperator==(optional<T>const&x,optional<T>const&y);
@@ -129,13 +130,10 @@
template<classT>inlinebooloperator!=(optional<T>const&x,none_t)noexcept;
-// [new in 1.34]template<classT>inlineoptional<T>make_optional(Tconst&v);
-// [new in 1.34]template<classT>inlineoptional<T>make_optional(boolcondition,Tconst&v);
-// [new in 1.34]template<classT>inlineTconst&get_optional_value_or(optional<T>const&opt,Tconst&default);template<classT>inlineTconst&get(optional<T>const&opt);
diff --git a/doc/html/index.html b/doc/html/index.html
index 5c74f5b..9854163 100644
--- a/doc/html/index.html
+++ b/doc/html/index.html
@@ -92,7 +92,7 @@
-
Last revised: May 22, 2014 at 21:28:38 GMT
+
Last revised: May 23, 2014 at 14:35:08 GMT
diff --git a/doc/reference.qbk b/doc/reference.qbk
index 80c6927..cd2e354 100644
--- a/doc/reference.qbk
+++ b/doc/reference.qbk
@@ -66,9 +66,6 @@
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__]``
@@ -77,6 +74,8 @@
T const& value() const ; ``[link reference_optional_value __GO_TO__]``
T& value() ; ``[link reference_optional_value __GO_TO__]``
+
+ template T value_or( U && v ) const ; ``[link reference_optional_value_or __GO_TO__]``
T const* get_ptr() const ; ``[link reference_optional_get_ptr __GO_TO__]``
T* get_ptr() ; ``[link reference_optional_get_ptr __GO_TO__]``
@@ -96,6 +95,8 @@
// (deprecated)
bool is_initialized() const ; ``[link reference_optional_is_initialized __GO_TO__]``
+ // (deprecated)
+ T const& get_value_or( T const& default ) const ; ``[link reference_optional_get_value_or_value __GO_TO__]``
};
template inline bool operator == ( optional const& x, optional const& y ) ; ``[link reference_operator_compare_equal_optional_optional __GO_TO__]``
@@ -114,13 +115,10 @@
template inline bool operator != ( optional const& x, none_t ) noexcept ; ``[link reference_operator_compare_not_equal_optional_none __GO_TO__]``
- // [new in 1.34]
template inline optional make_optional ( T const& v ) ; ``[link reference_make_optional_value __GO_TO__]``
- // [new in 1.34]
template inline optional make_optional ( bool condition, T const& v ) ; ``[link reference_make_optional_bool_value __GO_TO__]``
- // [new in 1.34]
template inline T const& get_optional_value_or ( optional const& opt, T const& default ) ; ``[link reference_optional_get_value_or_value __GO_TO__]``
template inline T const& get ( optional const& opt ) ; ``[link reference_optional_get __GO_TO__]``
@@ -828,6 +826,17 @@ catch(bad_optional_access&) {
asert ( true );
}
``
+__SPACE__
+
+
+[#reference_optional_value_or]
+
+[: `template T optional::value_or(U && v) const ;`]
+
+* [*Requires:] `T` is CopyConstructible.
+* [*Returns:] `bool(*this) ? **this : static_cast(forward(v))`.
+* [*Throws:] Any exception thrown by the selected constructor of `T`.
+* [*Notes:] On compilers without rvalue reference support the type of `v` becomes `U const&`.
__SPACE__
@@ -839,6 +848,7 @@ __SPACE__
[: `inline T const& get_optional_value_or ( optional const& o, T const& default ) ;`]
[: `inline T& get_optional_value_or ( optional& o, T& default ) ;`]
+* [*Deprecated:] Use `value_or()` instead.
* [*Returns:] A reference to the contained value, if any, or `default`.
* [*Throws:] Nothing.
* [*Example:]
diff --git a/include/boost/bad_optional_access.hpp b/include/boost/optional/bad_optional_access.hpp
similarity index 100%
rename from include/boost/bad_optional_access.hpp
rename to include/boost/optional/bad_optional_access.hpp
diff --git a/include/boost/optional/optional.hpp b/include/boost/optional/optional.hpp
index b6ca7e9..5a9cc46 100644
--- a/include/boost/optional/optional.hpp
+++ b/include/boost/optional/optional.hpp
@@ -23,7 +23,7 @@
#include
#include
-#include
+#include
#include
#include
#include
@@ -441,11 +441,11 @@ class optional_base : public optional_tag
public :
- // Destroys the current value, if any, leaving this UNINITIALIZED
+ // **DEPPRECATED** Destroys the current value, if any, leaving this UNINITIALIZED
// No-throw (assuming T::~T() doesn't)
void reset() BOOST_NOEXCEPT { destroy(); }
- // Replaces the current value -if any- with 'val'
+ // **DEPPRECATED** Replaces the current value -if any- with 'val'
void reset ( argument_type val ) { assign(val); }
// Returns a pointer to the value if this is initialized, otherwise,
@@ -954,6 +954,14 @@ class optional : public optional_detail::optional_base
throw_exception(bad_optional_access("Attempted to access the value of an uninitialized optional object."));
}
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ template
+ value_type value_or ( U&& v ) const { return this->is_initialized() ? get() : static_cast(boost::forward(v)); }
+#else
+ template
+ value_type value_or ( U const& v ) const { return this->is_initialized() ? get() : static_cast(v); }
+#endif
+
bool operator!() const BOOST_NOEXCEPT { return !this->is_initialized() ; }
BOOST_EXPLICIT_OPERATOR_BOOL()
diff --git a/test/optional_test_value_access.cpp b/test/optional_test_value_access.cpp
index 5cff1b7..73dc3fd 100644
--- a/test/optional_test_value_access.cpp
+++ b/test/optional_test_value_access.cpp
@@ -40,6 +40,20 @@ struct IntWrapper
bool operator==(IntWrapper const& rhs) const { return _i == rhs._i; }
};
+template
+void test_function_value_or_for()
+{
+ optional oM0;
+ const optional oC0;
+ optional oM1(1);
+ const optional oC2(2);
+
+ BOOST_CHECK(oM0.value_or(5) == 5);
+ BOOST_CHECK(oC0.value_or(5) == 5);
+ BOOST_CHECK(oM1.value_or(5) == 1);
+ BOOST_CHECK(oC2.value_or(5) == 2);
+}
+
template
void test_function_value_for()
{
@@ -85,16 +99,41 @@ void test_function_value_for()
void test_function_value()
{
test_function_value_for();
- test_function_value_for();
+ test_function_value_for();
test_function_value_for();
}
+struct FatToIntConverter
+{
+ static int conversions;
+ int _val;
+ FatToIntConverter(int val) : _val(val) {}
+ operator int() { conversions += 1; return _val; }
+};
+
+int FatToIntConverter::conversions = 0;
+
+void test_function_value_or()
+{
+ test_function_value_or_for();
+ test_function_value_or_for();
+ test_function_value_or_for();
+
+ optional oi(1);
+ BOOST_CHECK(oi.value_or(FatToIntConverter(2)) == 1);
+ BOOST_CHECK(FatToIntConverter::conversions == 0);
+
+ oi = boost::none;
+ BOOST_CHECK(oi.value_or(FatToIntConverter(2)) == 2);
+ BOOST_CHECK(FatToIntConverter::conversions == 1);
+}
+
int test_main( int, char* [] )
{
try
{
test_function_value();
-
+ test_function_value_or();
}
catch ( ... )
{
From 22baf1dd09153e07589e0cb3015724f4e355b27e Mon Sep 17 00:00:00 2001
From: Andrzej Krzemienski
Date: Sat, 24 May 2014 13:44:07 +0200
Subject: [PATCH 4/9] Fixed bug in test on compiler with no rvalue refs
---
test/optional_test_value_access.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/test/optional_test_value_access.cpp b/test/optional_test_value_access.cpp
index 73dc3fd..bd3ea9e 100644
--- a/test/optional_test_value_access.cpp
+++ b/test/optional_test_value_access.cpp
@@ -108,7 +108,7 @@ struct FatToIntConverter
static int conversions;
int _val;
FatToIntConverter(int val) : _val(val) {}
- operator int() { conversions += 1; return _val; }
+ operator int() const { conversions += 1; return _val; }
};
int FatToIntConverter::conversions = 0;
From 2e583aaf30964afd66c1284aa71d0d8b42fa440d Mon Sep 17 00:00:00 2001
From: Andrzej Krzemienski
Date: Tue, 3 Jun 2014 17:36:18 +0200
Subject: [PATCH 5/9] Fixed code, updated docs, added emplace()
---
doc/{optional.qbk => 00_optional.qbk} | 46 ++--
doc/01_tutorial.qbk | 113 +++++++++
doc/{motivation.qbk => 02_discussion.qbk} | 2 +-
doc/{development.qbk => 03_development.qbk} | 8 +-
doc/{reference.qbk => 04_reference.qbk} | 19 +-
doc/{examples.qbk => 05_examples.qbk} | 0
doc/10_optional_references.qbk | 120 +++++++++
...special_cases.qbk => 11_special_cases.qbk} | 127 +---------
doc/{dependencies.qbk => 90_dependencies.qbk} | 0
...owledgments.qbk => 91_acknowledgments.qbk} | 0
doc/Jamfile.v2 | 2 +-
.../boost_optional/detailed_semantics.html | 38 ++-
doc/html/boost_optional/development.html | 27 +-
doc/html/boost_optional/discussion.html | 128 ++++++++++
.../exception_safety_guarantees.html | 7 +
doc/html/boost_optional/synopsis.html | 2 +
doc/html/boost_optional/tutorial.html | 239 ++++++++++++++++++
.../boost_optional/type_requirements.html | 14 +-
doc/html/index.html | 73 +++++-
include/boost/detail/none_t.hpp | 28 --
include/boost/optional/optional.hpp | 27 +-
test/Jamfile.v2 | 1 +
test/optional_test_emplace.cpp | 169 +++++++++++++
23 files changed, 986 insertions(+), 204 deletions(-)
rename doc/{optional.qbk => 00_optional.qbk} (53%)
create mode 100644 doc/01_tutorial.qbk
rename doc/{motivation.qbk => 02_discussion.qbk} (99%)
rename doc/{development.qbk => 03_development.qbk} (98%)
rename doc/{reference.qbk => 04_reference.qbk} (97%)
rename doc/{examples.qbk => 05_examples.qbk} (100%)
create mode 100644 doc/10_optional_references.qbk
rename doc/{special_cases.qbk => 11_special_cases.qbk} (63%)
rename doc/{dependencies.qbk => 90_dependencies.qbk} (100%)
rename doc/{acknowledgments.qbk => 91_acknowledgments.qbk} (100%)
create mode 100644 doc/html/boost_optional/discussion.html
create mode 100644 doc/html/boost_optional/tutorial.html
delete mode 100644 include/boost/detail/none_t.hpp
create mode 100644 test/optional_test_emplace.cpp
diff --git a/doc/optional.qbk b/doc/00_optional.qbk
similarity index 53%
rename from doc/optional.qbk
rename to doc/00_optional.qbk
index 3a74566..abf5fd7 100644
--- a/doc/optional.qbk
+++ b/doc/00_optional.qbk
@@ -46,23 +46,39 @@ Distributed under the Boost Software License, Version 1.0.
[section Introduction]
-This library can be used to represent 'optional' (or 'nullable') objects that can be safely passed by value:
+Class template `optional` is a wrapper for representing 'optional' (or 'nullable') objects who may not (yet) contain a valid value. Optional objects offer full value semantics; they are good for passing by value and usage inside STL containers. This is a header-only library.
- optional readInt(); // this function may return either an int or a not-an-int
-
- if (optional oi = readInt()) // did I get a real int
- cout << "my int is: " << *oi; // use my int
- else
- cout << "I have no int";
-
+[section Problem]
+Suppose we want to read a parameter form a config file which represents some integral value, let's call it `"MaxValue"`. It is possible that this parameter is not specified; such situation is no error. It is valid to not specify the parameter and in that case the program is supposed to behave slightly different. Also suppose that any possible value of type `int` is a valid value for `"MaxValue"`, so we cannot jut use `-1` to represent the absence of the parameter in the config file.
[endsect]
-[include motivation.qbk]
-[include development.qbk]
-[include reference.qbk]
-[include examples.qbk]
-[include special_cases.qbk]
-[include dependencies.qbk]
-[include acknowledgments.qbk]
+[section Solution]
+
+This is how you solve it with `boost::optional`:
+
+ #include
+
+ boost::optional getConfigParam(std::string name); // return either an int or a `not-an-int`
+
+ int main()
+ {
+ if (boost::optional oi = getConfigParam("MaxValue")) // did I get a real int?
+ runWithMax(*oi); // use my int
+ else
+ runWithNoMax();
+ }
+
+[endsect]
+[endsect]
+
+[include 01_tutorial.qbk]
+[include 02_discussion.qbk]
+[include 03_development.qbk]
+[include 04_reference.qbk]
+[include 05_examples.qbk]
+[include 10_optional_references.qbk]
+[include 11_special_cases.qbk]
+[include 90_dependencies.qbk]
+[include 91_acknowledgments.qbk]
diff --git a/doc/01_tutorial.qbk b/doc/01_tutorial.qbk
new file mode 100644
index 0000000..cf8be16
--- /dev/null
+++ b/doc/01_tutorial.qbk
@@ -0,0 +1,113 @@
+[/
+ Boost.Optional
+
+ Copyright (c) 2003-2007 Fernando Luis Cacciola Carballal
+ Copyright (c) 2014 Andrzej Krzemienski
+
+ 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 Tutorial]
+
+[section Optional return values]
+
+Let's write and use a converter function that converts an a `std::string` to an `int`. It is possible that for a given string (e.g. `"cat"`) there exist no value of type `int` capable of representing the conversion result. We do not consider such situation an error. We expect that the converter can be used only to check if the conversion is possible. A natural signature for this function can be:
+
+ #include
+ boost::optionl convert(const std::string& text);
+
+All necessary functionality can be included with one header ``. The above function signature means that the function can either return a value of type `int` or a flag indicating that no value of `int` is available. This does not indicate an error. It is like one additional value of `int`. This is how we can use our function:
+
+ const std::string& text = /*... */;
+ boost::optionl oi = convert(text); // move-construct
+ if (oi) // contextual conversion to bool
+ int i = *oi; // operator*
+
+In order to test if `optional` contains a value, we use the contextual conversion to type `bool`. Because of this we can combine the initialization of the optional object and the test into one instruction:
+
+ if (boost::optionl oi = convert(text))
+ int i = *oi;
+
+We extract the contained value with `operator*` (and with `operator->` where it makes sense). An attempt to extract the contained value of an uninitialized optional object is an ['undefined behaviour] (UB). This implementation guards the call with `BOOST_ASSERT`. Therefore you should be sure that the contained value is there before extracting. For instance, the following code is reasonably UB-safe:
+
+ int i = *convert("100");
+
+This is because we know that string value `"100"` converts to a valid value of `int`. If you do not like this potential UB, you can use an alternative way of extracting the contained value:
+
+ try {
+ int j = convert(text).value();
+ }
+ catch (const boost::bad_optional_access&) {
+ // deal with it
+ }
+
+This version throws an exception upon an attempt to access a non-existent contained value. If your way of dealing with the missing value is to use some default, like `0`, there exists a yet another alternative:
+
+ int k = convert(text).value_or(0);
+
+This uses the `atoi`-like approach to conversions: if `text` does not represent an integral number just return `0`. Now, let's consider how function `convert` can be implemented.
+
+ boost::optionl convert(const std::string& text)
+ {
+ std::stringstream s(text);
+ int i;
+ if ((s >> i) && s.get() == std::char_traits::eof())
+ return i;
+ else
+ return boost::none;
+ }
+
+Observe the two return statements. `return i` uses the converting constructor that can create `optional` from `T`. Thus constructed optional object is initialized and its value is a copy of `i`. The other return statement uses another converting constructor from a special tag `boost::none`. It is used to indicate that we want to create an uninitialized optional object.
+
+
+[endsect]
+
+[section Optional data members]
+Suppose we want to implement a ['lazy load] optimization. This is because we do not want to perform an expensive initialization of our `Resource` until (if at all) it is really used. We can do it this way:
+
+ class Widget
+ {
+ boost::optional resource_;
+
+ public:
+ Widget() {}
+
+ Resource& getResource() // not thread-safe
+ {
+ if (resource_ == boost::none)
+ resource_.emplace("resource", "arguments");
+
+ return *resource_;
+ }
+ };
+
+`optional`'s default constructor creates an uninitialized optional. No call to `Resource`'s default constructor is attempted. `Resource` doesn't have to be __SGI_DEFAULT_CONSTRUCTIBLE__. In function `getResource` we first check if `resource_` is initialized. This time we do not use the contextual conversion to `bool`, but a comparison with `boost::none`. These two ways are equivalent. Function `emplace` initializes the optional in-place by perfect-forwarding the arguments to the constructor of `Resource`. No copy- or move-construction is involved here. `Resource` doesn't even have to be `MoveConstructible`.
+
+[note Function `emplace` is only available on compilers that support rvalue references and variadic templates. If your compiler does not support these features and you still need to avoid any move-constructions, use [link boost_optional.in_place_factories In-Place Factories].]
+
+[endsect]
+
+[section Bypassing unnecessary default construction]
+Suppose we have class `Date`, which does not have a default constructor: there is no good candidate for a default date. We have a function that returns two dates in form of a `boost::tuple`:
+
+ boost::tuple getPeriod();
+
+In other place we want to use the result of `getPeriod`, but want the two dates to be named: `begin` and `end`. We want to implement something like 'multiple return values':
+
+ Date begin, end; // Error: no default ctor!
+ boost::tie(begin, end) = getPeriod();
+
+The second line works already, this is the capability of Boost.Tuple library, but the first line won't work. We could set some initial invented dates, but it is confusing and may be an unacceptable cost, given that these values will be overwritten in the next line anyway. This is where `optional` can help:
+
+ boost::optional begin, end;
+ boost::tie(begin, end) = getPeriod();
+
+It works because inside `boost::tie` a move-assignment from `T` is invoked on `optional`, which internally calls a move-constructor of `T`.
+[endsect]
+
+[endsect]
+
+
diff --git a/doc/motivation.qbk b/doc/02_discussion.qbk
similarity index 99%
rename from doc/motivation.qbk
rename to doc/02_discussion.qbk
index fc014c3..ee69444 100644
--- a/doc/motivation.qbk
+++ b/doc/02_discussion.qbk
@@ -9,7 +9,7 @@
http://www.boost.org/LICENSE_1_0.txt)
]
-[section Motivation]
+[section Discussion]
Consider these functions which should return a value but which might not have
a value to return:
diff --git a/doc/development.qbk b/doc/03_development.qbk
similarity index 98%
rename from doc/development.qbk
rename to doc/03_development.qbk
index 9340407..bb89134 100644
--- a/doc/development.qbk
+++ b/doc/03_development.qbk
@@ -13,13 +13,13 @@
[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)).
+variable an ['initial value] (through an ['initializer]. (cf. 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).
+(cf. 8.5/11).
`optional` 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
@@ -38,7 +38,7 @@ 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
+`T` plus some ['nil_t]—where `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`.
@@ -197,7 +197,7 @@ 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.
+contextual 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
diff --git a/doc/reference.qbk b/doc/04_reference.qbk
similarity index 97%
rename from doc/reference.qbk
rename to doc/04_reference.qbk
index cd2e354..fbeb821 100644
--- a/doc/reference.qbk
+++ b/doc/04_reference.qbk
@@ -58,6 +58,8 @@
template optional& operator = ( optional const& rhs ) ; ``[link reference_optional_operator_equal_other_optional __GO_TO__]``
template optional& operator = ( optional&& rhs ) ; ``[link reference_optional_operator_move_equal_other_optional __GO_TO__]``
+
+ template void emplace ( Args...&& args ) ; ``[link reference_optional_emplace __GO_TO__]``
template optional& operator = ( InPlaceFactory const& f ) ; ``[link reference_optional_operator_equal_factory __GO_TO__]``
@@ -746,6 +748,21 @@ assert ( *opt1 == static_cast(v) ) ;
__SPACE__
+[#reference_optional_emplace]
+
+[: `template void optional::emplace( Args...&& args );`]
+
+* [*Requires:] The compiler supports rvalue references and variadic templates.
+* [*Effect:] If `*this` is initialized calls `*this = none`.
+ Then initializes in-place the contained value as if direct-initializing an object
+ of type `T` with `std::forward(args)...`.
+* [*Postconditions: ] `*this` is [_initialized].
+* [*Throws:] Whatever the selected `T`'s constructor throws.
+* [*Notes:] `T` need not be `MoveConstructible` or `MoveAssignable`.
+* [*Exception Safety:] If an exception is thrown during the initialization of `T`, `*this` is ['uninitialized].
+
+__SPACE__
+
[#reference_optional_operator_equal_factory]
[: `template optional& optional::operator=( InPlaceFactory const& f );`]
@@ -823,7 +840,7 @@ try {
assert ( false );
}
catch(bad_optional_access&) {
- asert ( true );
+ assert ( true );
}
``
__SPACE__
diff --git a/doc/examples.qbk b/doc/05_examples.qbk
similarity index 100%
rename from doc/examples.qbk
rename to doc/05_examples.qbk
diff --git a/doc/10_optional_references.qbk b/doc/10_optional_references.qbk
new file mode 100644
index 0000000..2f8b3c6
--- /dev/null
+++ b/doc/10_optional_references.qbk
@@ -0,0 +1,120 @@
+
+[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` treats it wrapped pseudo-object much as
+a real value, a true real reference is stored so aliasing will ocurr:
+
+* Copies of `optional` will copy the references but all these references
+will nonetheless refer to the same object.
+* Value-access will actually provide access to the referenced object
+rather than the reference itself.
+
+[warning On compilers that do not conform to Standard C++ rules of reference binding, operations on optional references might give adverse results: rather than binding a reference to a designated object they may create an unexpected temporary and bind to it. For more details see [link boost_optional.dependencies_and_portability.optional_reference_binding Dependencies and Portability section].]
+
+[heading Rvalue references]
+
+Rvalue references and lvalue references to const have the ability in C++ to extend the life time of a temporary they bind to. Optional references do not have this capability, therefore to avoid surprising effects it is not possible to initialize an optional references from a temporary. Optional rvalue references are disabled altogether. Also, the initialization and assignment of an optional reference to const from rvalue reference is disabled.
+
+ const int& i = 1; // legal
+ optional oi = 1; // illegal
+
+[endsect]
+
+[section Rebinding semantics for assignment of optional references]
+
+If you assign to an ['uninitialized ] `optional` 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 ora ;
+ optional orb(x) ;
+ ora = orb ; // now 'ora' is bound to 'x' through 'rx'
+ *ora = 2 ; // Changes value of 'x' through 'ora'
+ assert(x==2);
+
+If you assign to a bare C++ reference, the assignment is forwarded to the
+referenced object; its value changes but the reference is never rebound.
+
+ int a = 1 ;
+ int& ra = a ;
+ int b = 2 ;
+ int& rb = b ;
+ ra = rb ; // Changes the value of 'a' to 'b'
+ assert(a==b);
+ b = 3 ;
+ assert(ra!=b); // 'ra' is not rebound to 'b'
+
+Now, if you assign to an ['initialized ] `optional`, 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 ora(ra) ;
+ optional 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` 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` forwarding assignment to the referenced object (thus
+changing the referenced object value but not rebinding), and consider the
+following code:
+
+ optional a = get();
+ int x = 1 ;
+ int& rx = x ;
+ optional 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` would assign just like `T&` does, you would never be able to
+use Optional's assignment without explicitly handling the previous
+initialization state unless your code is capable of functioning whether
+after the assignment, `a` aliases the same object as `b` or not.
+
+That is, you would have to discriminate in order to be consistent.
+
+If in your code rebinding to another object is not an option, then it is very
+likely that binding for the first time isn't either. In such case, assignment
+to an ['uninitialized ] `optional` shall be prohibited. It is quite possible
+that in such a scenario it is a precondition that the lvalue must be already
+initialized. If it isn't, then binding for the first time is OK
+while rebinding is not which is IMO very unlikely.
+In such a scenario, you can assign the value itself directly, as in:
+
+ assert(!!opt);
+ *opt=value;
+
+[endsect]
diff --git a/doc/special_cases.qbk b/doc/11_special_cases.qbk
similarity index 63%
rename from doc/special_cases.qbk
rename to doc/11_special_cases.qbk
index 6173c16..110ef78 100644
--- a/doc/special_cases.qbk
+++ b/doc/11_special_cases.qbk
@@ -1,124 +1,4 @@
-[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` treats it wrapped pseudo-object much as
-a real value, a true real reference is stored so aliasing will ocurr:
-
-* Copies of `optional` will copy the references but all these references
-will nonetheless refer to the same object.
-* Value-access will actually provide access to the referenced object
-rather than the reference itself.
-
-[warning On compilers that do not conform to Standard C++ rules of reference binding, operations on optional references might give adverse results: rather than binding a reference to a designated object they may create an unexpected temporary and bind to it. For more details see [link boost_optional.dependencies_and_portability.optional_reference_binding Dependencies and Portability section].]
-
-[heading Rvalue references]
-
-Rvalue references and lvalue references to const have the ability in C++ to extend the life time of a temporary they bind to. Optional references do not have this capability, therefore to avoid surprising effects it is not possible to initialize an optional references from a temporary. Optional rvalue references are disabled altogether. Also, the initialization and assignment of an optional reference to const from rvalue reference is disabled.
-
- const int& i = 1; // legal
- optional oi = 1; // illegal
-
-[endsect]
-
-[section Rebinding semantics for assignment of optional references]
-
-If you assign to an ['uninitialized ] `optional` 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 ora ;
- optional orb(x) ;
- ora = orb ; // now 'ora' is bound to 'x' through 'rx'
- *ora = 2 ; // Changes value of 'x' through 'ora'
- assert(x==2);
-
-If you assign to a bare C++ reference, the assignment is forwarded to the
-referenced object; its value changes but the reference is never rebound.
-
- int a = 1 ;
- int& ra = a ;
- int b = 2 ;
- int& rb = b ;
- ra = rb ; // Changes the value of 'a' to 'b'
- assert(a==b);
- b = 3 ;
- assert(ra!=b); // 'ra' is not rebound to 'b'
-
-Now, if you assign to an ['initialized ] `optional`, 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 ora(ra) ;
- optional 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` 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` forwarding assignment to the referenced object (thus
-changing the referenced object value but not rebinding), and consider the
-following code:
-
- optional a = get();
- int x = 1 ;
- int& rx = x ;
- optional 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` would assign just like `T&` does, you would never be able to
-use Optional's assignment without explicitly handling the previous
-initialization state unless your code is capable of functioning whether
-after the assignment, `a` aliases the same object as `b` or not.
-
-That is, you would have to discriminate in order to be consistent.
-
-If in your code rebinding to another object is not an option, then it is very
-likely that binding for the first time isn't either. In such case, assignment
-to an ['uninitialized ] `optional` shall be prohibited. It is quite possible
-that in such a scenario it is a precondition that the lvalue must be already
-initialized. If it isn't, then binding for the first time is OK
-while rebinding is not which is IMO very unlikely.
-In such a scenario, you can assign the value itself directly, as in:
-
- assert(!!opt);
- *opt=value;
-
-[endsect]
-
[section In-Place Factories]
One of the typical problems with wrappers and containers is that their
@@ -356,6 +236,8 @@ Unless `T`'s constructor or assignment throws, assignments to `optional` do n
This also applies to move assignments/constructors. However, move operations are made no-throw more often.
+Operation `emplace` provides basic exception safety guarantee. If it throws, the optional object becomes uninitialized regardless of its initial state, and its previous contained value (if any) is destroyed. It doesn't call any assignment or move/copy constructor on `T`.
+
[heading Swap]
Unless `swap` on optional is customized, its primary implementation forwards calls to `T`'s `swap` or move constructor (depending on the initialization state of the optional objects). Thus, if both `T`'s `swap` and move constructor never throw, `swap` on `optional` never throws. similarly, if both `T`'s `swap` and move constructor offer strong guarantee, `swap` on `optional` also offers a strong guarantee.
@@ -365,8 +247,9 @@ In case `swap` on optional is customized, the call to `T`'s move constructor are
[section Type requirements]
-In general, `T` must be `MoveConstructible` and have a no-throw destructor.
-The `MoveConstructible` requirement is not needed if [*InPlaceFactories] are used.
+At the very minimum for `optional` to work with a minimum interface it is required that `T` has a publicly accessible no-throw destructor. In that case you need to initialize the optional object with function `emplace()` or use [*InPlaceFactories].
+Additionally, if `T` is `Moveable`, `optional` is also `Moveable` and can be easily initialized from an rvalue of type `T` and be passed by value.
+Additionally if `T` is `Copyable`, `optional` is also `Copyable` and can be easily initialized from an lvalue of type `T`.
`T` [_is not] required to be __SGI_DEFAULT_CONSTRUCTIBLE__.
diff --git a/doc/dependencies.qbk b/doc/90_dependencies.qbk
similarity index 100%
rename from doc/dependencies.qbk
rename to doc/90_dependencies.qbk
diff --git a/doc/acknowledgments.qbk b/doc/91_acknowledgments.qbk
similarity index 100%
rename from doc/acknowledgments.qbk
rename to doc/91_acknowledgments.qbk
diff --git a/doc/Jamfile.v2 b/doc/Jamfile.v2
index 95de749..5014bb2 100644
--- a/doc/Jamfile.v2
+++ b/doc/Jamfile.v2
@@ -17,7 +17,7 @@ path-constant images : html ;
xml optional
:
- optional.qbk
+ 00_optional.qbk
;
boostbook standalone
diff --git a/doc/html/boost_optional/detailed_semantics.html b/doc/html/boost_optional/detailed_semantics.html
index 8495d41..8374254 100644
--- a/doc/html/boost_optional/detailed_semantics.html
+++ b/doc/html/boost_optional/detailed_semantics.html
@@ -1080,6 +1080,42 @@
+
+
+
+
+ template<class...Args>voidoptional<T
+ (not a ref)>::emplace(Args...&&
+ args);
+
+
+
+ Requires: The compiler supports rvalue
+ references and variadic templates.
+
+
+ Effect: If *this is initialized calls *this=
+ none. Then initializes in-place
+ the contained value as if direct-initializing an object of type T with std::forward<Args>(args)....
+
+
+ Postconditions: *this is initialized.
+
+
+ Throws: Whatever the selected T's constructor throws.
+
+
+ Notes:T
+ need not be MoveConstructible
+ or MoveAssignable.
+
+
+ Exception Safety: If an exception is thrown
+ during the initialization of T,
+ *this
+ is uninitialized.
+
@@ -39,12 +39,12 @@
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
+ (cf. 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
+ has an indeterminate initial value (cf. 8.5/11). 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
@@ -67,13 +67,12 @@
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>.
+ nil_t—where 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 HaskellMaybe
built-in type constructor. Thus, a discriminated union T+nil_t
@@ -329,8 +328,8 @@
Such a de facto idiom for referring to optional objects
can be formalized in the form of a concept: the OptionalPointee
concept. This concept captures the syntactic usage of operators *, ->
- and conversion to bool to convey
- the notion of optionality.
+ and contextual conversion to bool
+ to convey the notion of optionality.
However, pointers are good to refer
@@ -407,7 +406,7 @@