diff --git a/doc/00_optional.qbk b/doc/00_optional.qbk
index 9cceee1..fb5d584 100644
--- a/doc/00_optional.qbk
+++ b/doc/00_optional.qbk
@@ -23,6 +23,7 @@ Distributed under the Boost Software License, Version 1.0.
[/ Cited Boost resources ]
[def __BOOST_VARIANT__ [@../../../variant/index.html Boost.Variant]]
+[def __BOOST_TUPLE__ [@../../../tuple/index.html Boost.Tuple]]
[def __BOOST_TRIBOOL__ [@../../../../doc/html/tribool.html boost::tribool]]
[def __OPTIONAL_POINTEE__ [@../../../utility/OptionalPointee.html OptionalPointee]]
@@ -36,7 +37,9 @@ Distributed under the Boost Software License, Version 1.0.
[/ Other web resources ]
[def __HASKELL__ [@http://www.haskell.org/ Haskell]]
-[def __SGI_DEFAULT_CONSTRUCTIBLE__ [@http://www.sgi.com/tech/stl/DefaultConstructible.html Default Constructible]]
+[def __SGI_DEFAULT_CONSTRUCTIBLE__ [@http://www.sgi.com/tech/stl/DefaultConstructible.html `DefaultConstructible`]]
+[def __SGI_LESS_THAN_COMPARABLE__ [@http://www.sgi.com/tech/stl/LessThanComparable.html `LessThanComparable`]]
+[def __SGI_EQUALITY_COMPARABLE__ [@http://www.sgi.com/tech/stl/EqualityComparable.html `EqualityComparable`]]
[/ Icons ]
@@ -71,8 +74,10 @@ This is how you solve it with `boost::optional`:
[include 01_quick_start.qbk]
[section Tutorial]
-[include 12_motivation.qbk]
-[include 13_development.qbk]
+[include 10_motivation.qbk]
+[include 11_development.qbk]
+[include 12_when_to_use.qbk]
+[include 13_relational_operators.qbk]
[include 14_optional_references.qbk]
[include 15_in_place_factories.qbk]
[include 16_optional_bool.qbk]
diff --git a/doc/01_quick_start.qbk b/doc/01_quick_start.qbk
index 2b642df..10d55e6 100644
--- a/doc/01_quick_start.qbk
+++ b/doc/01_quick_start.qbk
@@ -88,12 +88,12 @@ Suppose we want to implement a ['lazy load] optimization. This is because we do
class Widget
{
- boost::optional resource_;
+ mutable boost::optional resource_;
public:
Widget() {}
- Resource& getResource() // not thread-safe
+ const Resource& getResource() const // not thread-safe
{
if (resource_ == boost::none)
resource_.emplace("resource", "arguments");
@@ -119,7 +119,7 @@ In other place we want to use the result of `getPeriod`, but want the two dates
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 invented initial 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:
+The second line works already, this is the capability of __BOOST_TUPLE__ library, but the first line won't work. We could set some invented initial 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();
@@ -138,7 +138,7 @@ Suppose you want to ask users to choose some number (an `int`). One of the valid
++choices[choice];
}
-This works because `optional` is `LessThanComparable` whenever `T` is `LessThanComparable`. In this case the state of being uninitialized is treated as a yet another value of `T`, which is compared less than any value of `T`. So the set of values that type `optional` can assume is {`boost::none`, -2147483648, -2147483647, ..., -1, 0, 1, ..., 2147483647} (assuming a 32-bit `int`).
+This works because `optional` is __SGI_LESS_THAN_COMPARABLE__ whenever `T` is __SGI_LESS_THAN_COMPARABLE__. In this case the state of being uninitialized is treated as a yet another value of `T`, which is compared less than any value of `T`.
[endsect]
[endsect]
diff --git a/doc/12_motivation.qbk b/doc/10_motivation.qbk
similarity index 100%
rename from doc/12_motivation.qbk
rename to doc/10_motivation.qbk
diff --git a/doc/13_development.qbk b/doc/11_development.qbk
similarity index 100%
rename from doc/13_development.qbk
rename to doc/11_development.qbk
diff --git a/doc/12_when_to_use.qbk b/doc/12_when_to_use.qbk
new file mode 100644
index 0000000..80dff54
--- /dev/null
+++ b/doc/12_when_to_use.qbk
@@ -0,0 +1,37 @@
+
+[section When to use Optional]
+
+It is recommended to use `optional` in situations where there is exactly one, clear (to all parties) reason for having no value of type `T`, and where the lack of value is as natural as having any regular value of `T`. One example of such situation is asking the user in some GUI form to optionally specify some limit on an `int` value, but the user is allowed to say 'I want the number not to be constrained by the maximum'.
+For another example, consider a config parameter specifying how many threads the application should launch. Leaving this parameter unspecified means that the application should decide itself. For yet another example, consider a function returning the index of the smallest element in a `vector`. We need to be prepared for the situation, where the `vector` is empty. Therefore a natural signature for such function would be:
+
+ template
+ optional find_smallest_elem(const std::vector& vec);
+
+Here, having received an empty `vec` and having no `size_t` to return is not a ['failure] but a ['normal], albeit irregular, situation.
+
+Another typical situation is to indicate that we do not have a value yet, but we expect to have it later. This notion can be used in implementing solutions like lazy initialization or a two-phase initialization.
+
+`optional` can be used to take a non-__SGI_DEFAULT_CONSTRUCTIBLE__ type `T` and create a sibling type with a default constructor. This is a way to add a ['null-state] to any type that doesn't have it already.
+
+Sometimes type `T` already provides a built-in null-state, but it may still be useful to wrap it into `optional`. Consider `std::string`. When you read a piece of text from a GUI form or a DB table, it is hardly ever that the empty string indicates anything else but a missing text. And some data bases do not even distinguish between a null string entry and a non-null string of length 0. Still, it may be practical to use `optional` to indicate in the returned type that we want to treat the empty string in a special dedicated program path:
+
+ if(boost::optional name = ask_user_name()) {
+ assert(*name != "");
+ logon_as(*name);
+ }
+ else {
+ skip_logon();
+ }
+
+In the example above, the assertion indicates that if we choose to use this technique, we must translate the empty string state to an optional object with no contained value (inside function `ask_user_name`).
+
+[heading Not recommended usages]
+
+It is not recommended to use `optional` to indicate that we were not able to compute a value because of a ['failure]. It is difficult to define what a failure is, but it usually has one common characteristic: an associated information on the cause of the failure. This can be the type and member data of an exception object, or an error code. It is a bad design to signal a failure and not inform about the cause. If you do not want to use exceptions, and do not like the fact that by returning error codes you cannot return the computed value, you can use [@https://github.com/ptal/Boost.Expected Expected] library. It is sort of __BOOST_VARIANT__ that contains either a computed value or a reason why the computation failed.
+
+Sometimes the distinction into what is a failure and what is a valid but irregular result is blurry and depends on a particular usage and personal preference. Consider a function that converts a `string` to an `int`. Is it a failure that you cannot convert? It might in some cases, but in other you may call it exactly for the purpose of figuring out if a given `string` is convertible, and you are not even interested in the resulting value. Sometimes when a conversion fails you may not consider it a failure, but you need to know why it cannot be converted; for instance at which character it is determined that the conversion is impossible. In this case returning `optional` will not suffice. Finally, there is a use case where an input string that does not represent an `int` is not a failure condition, but during the conversion we use resources whose acquisition may fail. In that case the natural representation is to both return `optional` and signal failure:
+
+ optional convert1(const string& str); // throws
+ expected> convert2(const string& str); // return either optional or error
+
+[endsect]
diff --git a/doc/13_relational_operators.qbk b/doc/13_relational_operators.qbk
new file mode 100644
index 0000000..a16d53b
--- /dev/null
+++ b/doc/13_relational_operators.qbk
@@ -0,0 +1,37 @@
+
+[section Relational operators]
+
+Type `optional` is __SGI_EQUALITY_COMPARABLE__ whenever `T` is __SGI_EQUALITY_COMPARABLE__. Two optional objects containing a value compare in the same as their contained values. The uninitialized state of `optional` is treated as a distinct value, equal to itself, and unequal to any value of type `T`:
+
+ boost::optional oN = boost::none;
+ boost::optional o0 = 0;
+ boost::optional o1 = 1;
+
+ assert(oN != o0);
+ assert(o1 != oN);
+ assert(o2 != o1);
+ assert(oN == oN);
+ assert(o0 == o0);
+
+The converting constructor from `T` as well as from `boost::none` implies the existence and semantics of the mixed comparison between `T` and `optional` as well as between `none_t` and `optionl`:
+
+ assert(oN != 0);
+ assert(o1 != boost::none);
+ assert(o2 != 1);
+ assert(oN == boost::none);
+ assert(o0 == 0);
+
+This mixed comparison has a practical interpretation, which is occasionally useful:
+
+ boost::optional choice = ask_user();
+ if (choice == 2)
+ start_procedure_2();
+
+In the above example, the meaning of the comparison is 'user chose number 2'. If user chose nothing, he didn't choose number 2.
+
+In case where `optional` is compared to `none`, it is not required that `T` be __SGI_EQUALITY_COMPARABLE__.
+
+In a similar manner, type `optional` is __SGI_LESS_THAN_COMPARABLE__ whenever `T` is __SGI_LESS_THAN_COMPARABLE__. The optional object containing no value is compared less than any value of `T`. To illustrate this, if the default ordering of `size_t` is {`0`, `1`, `2`, ...}, the default ordering of `optional` is {`boost::none`, `0`, `1`, `2`, ...}. This order does not have a practical interpretation. The goal is to have any semantically correct default ordering in order for `optional` to be usable in ordered associative containers (wherever `T` is usable).
+
+Mixed relational operators are the only case where the contained value of an optional object can be inspected without the usage of value accessing function (`operator*`, `value`, `value_or`).
+[endsect]
diff --git a/doc/18_type_requirements.qbk b/doc/18_type_requirements.qbk
index b8fd405..6faae48 100644
--- a/doc/18_type_requirements.qbk
+++ b/doc/18_type_requirements.qbk
@@ -1,10 +1,38 @@
[section Type requirements]
-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`.
+The very minimum requirement of `optional` is that `T` is a complete type and that it has a publicly accessible destructor. `T` doesn't even need to be constructible. You can use a very minimum interface:
-`T` [_is not] required to be __SGI_DEFAULT_CONSTRUCTIBLE__.
+ optional o; // uninitialized
+ assert(o == none); // check if initialized
+ assert(!o); //
+ o.value(); // always throws
+
+But this is practically useless. In order for `optional` to be able to do anything useful and offer all the spectrum of ways of accessing the contained value, `T` needs to have at least one accessible constructor. In that case you need to initialize the optional object with function `emplace()`, or if your compiler does not support it, resort to [link boost_optional.tutorial.in_place_factories In-Place Factories]:
+
+ optional o;
+ o.emplace("T", "ctor", "params");
+
+If `T` is `MoveConstructible`, `optional` is also `MoveConstructible` and can be easily initialized from an rvalue of type `T` and be passed by value:
+
+ optional o = make_T();
+ optional p = optional();
+
+If `T` is `CopyConstructible`, `optional` is also `CopyConstructible` and can be easily initialized from an lvalue of type `T`:
+
+ T v = make_T();
+ optional o = v;
+ optional p = o;
+
+If `T` is not `MoveAssignable`, it is still possible to reset the value of `optional` using function `emplace()`:
+
+ optional o = make_T();
+ o.emplace(make_another_T());
+
+If `T` is `Moveable` (both `MoveConstructible` and `MoveAssignable`) then `optional` is also `Moveable` and additionally can be constructed and assigned from an rvalue of type `T`.
+
+Similarly, if `T` is `Copyable` (both `CopyConstructible` and `CopyAssignable`) then `optional` is also `Copyable` and additionally can be constructed and assigned from an lvalue of type `T`.
+
+`T` ['is not] required to be __SGI_DEFAULT_CONSTRUCTIBLE__.
[endsect]
diff --git a/doc/20_reference.qbk b/doc/20_reference.qbk
index 966f8ec..82cd932 100644
--- a/doc/20_reference.qbk
+++ b/doc/20_reference.qbk
@@ -761,8 +761,16 @@ __SPACE__
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`.
+* [*Notes:] `T` need not be `MoveConstructible` or `MoveAssignable`. On compilers that do not support variadic templates, the signature falls back to single-argument: `template void emplace(Arg&& arg)`. On compilers that do not support rvalue references, the signature falls back to two overloads: taking `const` and non-`const` lvalue reference.
* [*Exception Safety:] If an exception is thrown during the initialization of `T`, `*this` is ['uninitialized].
+* [*Example:]
+``
+T v;
+optional opt;
+opt.emplace(0); // create in-place using ctor T(int)
+opt.emplace(); // destroy previous and default-construct another T
+opt.emplace(v); // destroy and copy-construct in-place (no assignment called)
+``
__SPACE__
diff --git a/doc/html/boost_optional/quick_start/bypassing_unnecessary_default_construction.html b/doc/html/boost_optional/quick_start/bypassing_unnecessary_default_construction.html
index 844742b..ed964cf 100644
--- a/doc/html/boost_optional/quick_start/bypassing_unnecessary_default_construction.html
+++ b/doc/html/boost_optional/quick_start/bypassing_unnecessary_default_construction.html
@@ -44,10 +44,10 @@
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 invented initial 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:
+ The second line works already, this is the capability of Boost.Tuple
+ library, but the first line won't work. We could set some invented initial
+ 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:
classWidget{
- boost::optional<Resource>resource_;
+ mutableboost::optional<constResource>resource_;public:Widget(){}
- Resource&getResource()// not thread-safe
+ constResource&getResource()const// not thread-safe{if(resource_==boost::none)resource_.emplace("resource","arguments");
@@ -53,13 +53,15 @@
optional's default constructor
creates an uninitialized optional. No call to Resource's
default constructor is attempted. Resource
- doesn't have to be 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 have to be DefaultConstructible. 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.
This works because optional<T>
- is LessThanComparable whenever
- T is LessThanComparable.
- In this case the state of being uninitialized is treated as a yet another
- value of T, which is compared
- less than any value of T.
- So the set of values that type optional<T>
- can assume is {boost::none, -2147483648, -2147483647, ..., -1,
- 0, 1, ..., 2147483647} (assuming a 32-bit int).
+ is LessThanComparable whenever T is LessThanComparable. In this case
+ the state of being uninitialized is treated as a yet another value of T, which is compared less than any value
+ of T.
Notes:T
need not be MoveConstructible
- or MoveAssignable.
+ or MoveAssignable. On
+ compilers that do not support variadic templates, the signature falls
+ back to single-argument: template<classArg>voidemplace(Arg&&arg). On compilers that do not support rvalue
+ references, the signature falls back to two overloads: taking const and non-const
+ lvalue reference.
Exception Safety: If an exception is
@@ -1102,6 +1106,15 @@
*this
is uninitialized.
+
+ Example:
+
Tv;
+optional<constT>opt;
+opt.emplace(0);// create in-place using ctor T(int)
+opt.emplace();// destroy previous and default-construct another T
+opt.emplace(v);// destroy and copy-construct in-place (no assignment called)
+