From 3dd614fd91c8ff4efb7bb14a39ede8d703b5dd4a Mon Sep 17 00:00:00 2001 From: Andrzej Krzemienski Date: Wed, 4 Jun 2014 18:13:06 +0200 Subject: [PATCH] Reorganized docs. Minor code fix wrt opt refs --- doc/00_optional.qbk | 30 +- doc/{01_tutorial.qbk => 01_quick_start.qbk} | 37 +- doc/05_examples.qbk | 102 - doc/11_special_cases.qbk | 258 --- doc/{02_discussion.qbk => 12_motivation.qbk} | 4 +- ...{03_development.qbk => 13_development.qbk} | 2 +- ...erences.qbk => 14_optional_references.qbk} | 0 doc/15_in_place_factories.qbk | 139 ++ doc/16_optional_bool.qbk | 52 + doc/17_exception_safety.qbk | 57 + doc/18_type_requirements.qbk | 10 + doc/{04_reference.qbk => 20_reference.qbk} | 108 +- doc/Jamfile.v2 | 3 +- .../a_note_about_optional_bool_.html | 6 +- doc/html/boost_optional/acknowledgments.html | 6 +- .../dependencies_and_portability.html | 72 +- .../optional_reference_binding.html | 100 + .../boost_optional/detailed_semantics.html | 227 +- doc/html/boost_optional/development.html | 6 +- doc/html/boost_optional/discussion.html | 6 +- .../boost_optional/in_place_factories.html | 6 +- .../boost_optional/optional_references.html | 8 +- doc/html/boost_optional/quick_start.html | 261 +++ ...sing_unnecessary_default_construction.html | 75 + .../optional_automatic_variables.html | 75 + .../quick_start/optional_data_members.html | 92 + .../quick_start/optional_return_values.html | 135 ++ .../reference/detailed_semantics.html | 1963 +++++++++++++++++ .../boost_optional/reference/synopsis.html | 174 ++ doc/html/boost_optional/synopsis.html | 19 +- doc/html/boost_optional/tutorial.html | 630 ++++-- .../tutorial/a_note_about_optional_bool_.html | 108 + .../tutorial/design_overview.html | 423 ++++ .../tutorial/exception_safety_guarantees.html | 175 ++ .../tutorial/in_place_factories.html | 197 ++ .../boost_optional/tutorial/motivation.html | 129 ++ .../tutorial/optional_references.html | 115 + ...for_assignment_of_optional_references.html | 149 ++ .../tutorial/type_requirements.html | 61 + .../boost_optional/type_requirements.html | 2 +- doc/html/index.html | 133 +- doc/html/optional/introduction.html | 82 + doc/html/optional/introduction/problem.html | 54 + doc/html/optional/introduction/solution.html | 58 + doc/html/optional/reference.html | 48 + doc/html/optional/tutorial.html | 58 + include/boost/optional/optional.hpp | 8 +- 47 files changed, 5607 insertions(+), 856 deletions(-) rename doc/{01_tutorial.qbk => 01_quick_start.qbk} (81%) delete mode 100644 doc/05_examples.qbk delete mode 100644 doc/11_special_cases.qbk rename doc/{02_discussion.qbk => 12_motivation.qbk} (99%) rename doc/{03_development.qbk => 13_development.qbk} (99%) rename doc/{10_optional_references.qbk => 14_optional_references.qbk} (100%) create mode 100644 doc/15_in_place_factories.qbk create mode 100644 doc/16_optional_bool.qbk create mode 100644 doc/17_exception_safety.qbk create mode 100644 doc/18_type_requirements.qbk rename doc/{04_reference.qbk => 20_reference.qbk} (92%) create mode 100644 doc/html/boost_optional/dependencies_and_portability/optional_reference_binding.html create mode 100644 doc/html/boost_optional/quick_start.html create mode 100644 doc/html/boost_optional/quick_start/bypassing_unnecessary_default_construction.html create mode 100644 doc/html/boost_optional/quick_start/optional_automatic_variables.html create mode 100644 doc/html/boost_optional/quick_start/optional_data_members.html create mode 100644 doc/html/boost_optional/quick_start/optional_return_values.html create mode 100644 doc/html/boost_optional/reference/detailed_semantics.html create mode 100644 doc/html/boost_optional/reference/synopsis.html create mode 100644 doc/html/boost_optional/tutorial/a_note_about_optional_bool_.html create mode 100644 doc/html/boost_optional/tutorial/design_overview.html create mode 100644 doc/html/boost_optional/tutorial/exception_safety_guarantees.html create mode 100644 doc/html/boost_optional/tutorial/in_place_factories.html create mode 100644 doc/html/boost_optional/tutorial/motivation.html create mode 100644 doc/html/boost_optional/tutorial/optional_references.html create mode 100644 doc/html/boost_optional/tutorial/rebinding_semantics_for_assignment_of_optional_references.html create mode 100644 doc/html/boost_optional/tutorial/type_requirements.html create mode 100644 doc/html/optional/introduction.html create mode 100644 doc/html/optional/introduction/problem.html create mode 100644 doc/html/optional/introduction/solution.html create mode 100644 doc/html/optional/reference.html create mode 100644 doc/html/optional/tutorial.html diff --git a/doc/00_optional.qbk b/doc/00_optional.qbk index abf5fd7..7a63714 100644 --- a/doc/00_optional.qbk +++ b/doc/00_optional.qbk @@ -45,14 +45,13 @@ Distributed under the Boost Software License, Version 1.0. [def __GO_TO__ [$images/callouts/R.png]] -[section Introduction] +[heading Introduction] 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. -[section Problem] +[heading 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] -[section Solution] +[heading Solution] This is how you solve it with `boost::optional`: @@ -68,16 +67,21 @@ This is how you solve it with `boost::optional`: 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 01_quick_start.qbk] +[section Tutorial] +[include 12_motivation.qbk] +[include 13_development.qbk] +[include 14_optional_references.qbk] +[include 15_in_place_factories.qbk] +[include 16_optional_bool.qbk] +[include 17_exception_safety.qbk] +[include 18_type_requirements.qbk] +[endsect] +[section Reference] +[include 20_reference.qbk] +[endsect] [include 90_dependencies.qbk] [include 91_acknowledgments.qbk] diff --git a/doc/01_tutorial.qbk b/doc/01_quick_start.qbk similarity index 81% rename from doc/01_tutorial.qbk rename to doc/01_quick_start.qbk index cf8be16..03f6eee 100644 --- a/doc/01_tutorial.qbk +++ b/doc/01_quick_start.qbk @@ -10,9 +10,9 @@ ] -[section Tutorial] +[section Quick Start] -[section Optional return values] +[heading 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: @@ -62,10 +62,28 @@ This uses the `atoi`-like approach to conversions: if `text` does not represent 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] -[endsect] +[heading Optional automatic variables] + +We could write function `convert` in a slightly different manner, so that it has a single `return`-statement: + + boost::optionl convert(const std::string& text) + { + boost::optionl ans; + std::stringstream s(text); + int i; + if ((s >> i) && s.get() == std::char_traits::eof()) + ans = i; + + return ans; + } + +The default constructor of `optional` creates an unitialized optional object. Unlike with `int`s you cannot have an `optional` in an indeterminate state. Its state is always well defined. Instruction `ans = i` initializes the optional object. It uses the assignment from `int`. In general, for `optional`, when an assignment from `T` is invoked, it can do two things. If the optional object is not initialized our case here), it initializes it with `T`'s copy constructor. If the optional object is already initialized, it assigns the new value to it using `T`'s copy assignment. +[/endsect] + +[heading Optional data members] -[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 @@ -86,11 +104,12 @@ Suppose we want to implement a ['lazy load] optimization. This is because we do `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].] +[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.tutorial.in_place_factories In-Place Factories].] -[endsect] +[/endsect] + +[heading Bypassing unnecessary default construction] -[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(); @@ -100,13 +119,13 @@ 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 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: +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(); 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] [endsect] diff --git a/doc/05_examples.qbk b/doc/05_examples.qbk deleted file mode 100644 index 00dbd99..0000000 --- a/doc/05_examples.qbk +++ /dev/null @@ -1,102 +0,0 @@ -[/ - 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 get_async_input() - { - if ( !queue.empty() ) - return optional(queue.top()); - else return optional(); // uninitialized - } - - void receive_async_message() - { - optional rcv ; - // The safe boolean conversion from 'rcv' is used here. - while ( (rcv = get_async_input()) && !timeout() ) - output(*rcv); - } - -[endsect] - -[section Optional local variables] - - optional name ; - if ( database.open() ) - { - name = database.lookup(employer_name) ; - } - else - { - if ( can_ask_user ) - name = 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 = 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 m_clipping_rect ; - - }; - -[endsect] - -[section Bypassing expensive unnecessary default construction] - - class ExpensiveCtor { ... } ; - class Fred - { - Fred() : mLargeVector(10000) {} - - std::vector< optional > mLargeVector ; - } ; - -[endsect] - -[endsect] - - diff --git a/doc/11_special_cases.qbk b/doc/11_special_cases.qbk deleted file mode 100644 index 110ef78..0000000 --- a/doc/11_special_cases.qbk +++ /dev/null @@ -1,258 +0,0 @@ - -[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 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(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 - InPlaceFactoryN in_place ( A0 const& a0, ..., AN const& aN) ; - - template - TypedInPlaceFactoryN 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 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] - -`optional` 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`. -It should be carefully considered if an `optional` instead of a `tribool` -is really needed. - -Second, although `optional<>` provides a contextual conversion to `bool` in C++11, - this falls back to an implicit conversion on older compilers. This conversion refers - to the initialization state and not to the contained value. Using `optional` - can lead to subtle errors due to the implicit `bool` conversion: - - void foo ( bool v ) ; - void bar() - { - optional 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). - -Third, mixed comparisons with `bool` work differently than similar mixed comparisons between pointers and `bool`, so the results might surprise you: - - optional oEmpty(none), oTrue(true), oFalse(false); - - if (oEmpty == none); // renders true - if (oEmpty == false); // renders false! - if (oEmpty == true); // renders false! - - if (oFalse == none); // renders false - if (oFalse == false); // renders true! - if (oFalse == true); // renders false - - if (oTrue == none); // renders false - if (oTrue == false); // renders false - if (oTrue == true); // renders true - -In other words, for `optional<>`, the following assertion does not hold: - - assert((opt == false) == (!opt)); -[endsect] - -[section Exception Safety Guarantees] - -This library assumes that `T`'s destructor does not throw exceptions. If it does, the behaviour of many operations on `optional` is undefined. - -The following mutating operations never throw exceptions: - -* `optional::operator= ( none_t ) noexcept` -* `optional::reset() noexcept` - -In addition, the following constructors and the destructor never throw exceptions: - -* `optional::optional() noexcept` -* `optional::optional( none_t ) noexcept` - - -Regarding the following assignment functions: - -* `optional::operator= ( optional const& )` -* `optional::operator= ( T const& )` -* `template optional::operator= ( optional const& )` -* `template optional::operator= ( InPlaceFactory const& )` -* `template optional::operator= ( TypedInPlaceFactory const& ) ` -* `optional::reset( T const& )` - -They forward calls to the corresponding `T`'s constructors or assignments (depending on whether the optional object is initialized or not); so if both `T`'s constructor and the assignment provide strong exception safety guarantee, `optional`'s assignment also provides strong exception safety guarantee; otherwise we only get the basic guarantee. Additionally, if both involved `T`'s constructor and the assignment never throw, `optional`'s assignment also never throws. - -Unless `T`'s constructor or assignment throws, assignments to `optional` do not throw anything else on its own. A throw during assignment never changes the initialization state of any optional object involved: - - - optional opt1(val1); - optional opt2(val2); - assert(opt1); - assert(opt2); - - try - { - opt1 = opt2; // throws - } - catch(...) - { - assert(opt1); - assert(opt2); - } - -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. - -In case `swap` on optional is customized, the call to `T`'s move constructor are replaced with the calls to `T`'s default constructor followed by `swap`. (This is more useful on older compilers that do not support move semantics, when one wants to acheive stronger exception safety guarantees.) In this case the exception safety guarantees for `swap` are reliant on the guarantees of `T`'s `swap` and default constructor -[endsect] - -[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`. - -`T` [_is not] required to be __SGI_DEFAULT_CONSTRUCTIBLE__. - -[endsect] - - diff --git a/doc/02_discussion.qbk b/doc/12_motivation.qbk similarity index 99% rename from doc/02_discussion.qbk rename to doc/12_motivation.qbk index ee69444..fe5b6da 100644 --- a/doc/02_discussion.qbk +++ b/doc/12_motivation.qbk @@ -9,7 +9,7 @@ http://www.boost.org/LICENSE_1_0.txt) ] -[section Discussion] +[section Motivation] Consider these functions which should return a value but which might not have a value to return: @@ -77,4 +77,4 @@ without ever checking if it has a valid value. Clearly, we need a better idiom. -[endsect] \ No newline at end of file +[endsect] diff --git a/doc/03_development.qbk b/doc/13_development.qbk similarity index 99% rename from doc/03_development.qbk rename to doc/13_development.qbk index bb89134..d2f1b1f 100644 --- a/doc/03_development.qbk +++ b/doc/13_development.qbk @@ -8,7 +8,7 @@ http://www.boost.org/LICENSE_1_0.txt) ] -[section Development] +[section Design Overview] [section The models] diff --git a/doc/10_optional_references.qbk b/doc/14_optional_references.qbk similarity index 100% rename from doc/10_optional_references.qbk rename to doc/14_optional_references.qbk diff --git a/doc/15_in_place_factories.qbk b/doc/15_in_place_factories.qbk new file mode 100644 index 0000000..d9df24d --- /dev/null +++ b/doc/15_in_place_factories.qbk @@ -0,0 +1,139 @@ + +[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 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(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 + InPlaceFactoryN in_place ( A0 const& a0, ..., AN const& aN) ; + + template + TypedInPlaceFactoryN 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 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] diff --git a/doc/16_optional_bool.qbk b/doc/16_optional_bool.qbk new file mode 100644 index 0000000..6f3664f --- /dev/null +++ b/doc/16_optional_bool.qbk @@ -0,0 +1,52 @@ + +[section A note about optional] + +`optional` 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`. +It should be carefully considered if an `optional` instead of a `tribool` +is really needed. + +Second, although `optional<>` provides a contextual conversion to `bool` in C++11, + this falls back to an implicit conversion on older compilers. This conversion refers + to the initialization state and not to the contained value. Using `optional` + can lead to subtle errors due to the implicit `bool` conversion: + + void foo ( bool v ) ; + void bar() + { + optional 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). + +Third, mixed comparisons with `bool` work differently than similar mixed comparisons between pointers and `bool`, so the results might surprise you: + + optional oEmpty(none), oTrue(true), oFalse(false); + + if (oEmpty == none); // renders true + if (oEmpty == false); // renders false! + if (oEmpty == true); // renders false! + + if (oFalse == none); // renders false + if (oFalse == false); // renders true! + if (oFalse == true); // renders false + + if (oTrue == none); // renders false + if (oTrue == false); // renders false + if (oTrue == true); // renders true + +In other words, for `optional<>`, the following assertion does not hold: + + assert((opt == false) == (!opt)); +[endsect] diff --git a/doc/17_exception_safety.qbk b/doc/17_exception_safety.qbk new file mode 100644 index 0000000..331104b --- /dev/null +++ b/doc/17_exception_safety.qbk @@ -0,0 +1,57 @@ + +[section Exception Safety Guarantees] + +This library assumes that `T`'s destructor does not throw exceptions. If it does, the behaviour of many operations on `optional` is undefined. + +The following mutating operations never throw exceptions: + +* `optional::operator= ( none_t ) noexcept` +* `optional::reset() noexcept` + +In addition, the following constructors and the destructor never throw exceptions: + +* `optional::optional() noexcept` +* `optional::optional( none_t ) noexcept` + + +Regarding the following assignment functions: + +* `optional::operator= ( optional const& )` +* `optional::operator= ( T const& )` +* `template optional::operator= ( optional const& )` +* `template optional::operator= ( InPlaceFactory const& )` +* `template optional::operator= ( TypedInPlaceFactory const& ) ` +* `optional::reset( T const& )` + +They forward calls to the corresponding `T`'s constructors or assignments (depending on whether the optional object is initialized or not); so if both `T`'s constructor and the assignment provide strong exception safety guarantee, `optional`'s assignment also provides strong exception safety guarantee; otherwise we only get the basic guarantee. Additionally, if both involved `T`'s constructor and the assignment never throw, `optional`'s assignment also never throws. + +Unless `T`'s constructor or assignment throws, assignments to `optional` do not throw anything else on its own. A throw during assignment never changes the initialization state of any optional object involved: + + + optional opt1(val1); + optional opt2(val2); + assert(opt1); + assert(opt2); + + try + { + opt1 = opt2; // throws + } + catch(...) + { + assert(opt1); + assert(opt2); + } + +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. + +In case `swap` on optional is customized, the call to `T`'s move constructor are replaced with the calls to `T`'s default constructor followed by `swap`. (This is more useful on older compilers that do not support move semantics, when one wants to acheive stronger exception safety guarantees.) In this case the exception safety guarantees for `swap` are reliant on the guarantees of `T`'s `swap` and default constructor +[endsect] + + diff --git a/doc/18_type_requirements.qbk b/doc/18_type_requirements.qbk new file mode 100644 index 0000000..b8fd405 --- /dev/null +++ b/doc/18_type_requirements.qbk @@ -0,0 +1,10 @@ + +[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`. + +`T` [_is not] required to be __SGI_DEFAULT_CONSTRUCTIBLE__. + +[endsect] diff --git a/doc/04_reference.qbk b/doc/20_reference.qbk similarity index 92% rename from doc/04_reference.qbk rename to doc/20_reference.qbk index fbeb821..966f8ec 100644 --- a/doc/04_reference.qbk +++ b/doc/20_reference.qbk @@ -71,13 +71,16 @@ 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& operator *() const& ; ``[link reference_optional_operator_asterisk __GO_TO__]`` + T& operator *() &; ``[link reference_optional_operator_asterisk __GO_TO__]`` + T&& operator *() &&; ``[link reference_optional_operator_asterisk __GO_TO__]`` - T const& value() const ; ``[link reference_optional_value __GO_TO__]`` - T& value() ; ``[link reference_optional_value __GO_TO__]`` + T const& value() const& ; ``[link reference_optional_value __GO_TO__]`` + T& value() & ; ``[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__]`` + template T value_or( U && v ) const& ; ``[link reference_optional_value_or __GO_TO__]`` + template T value_or( U && v ) && ; ``[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__]`` @@ -467,7 +470,7 @@ 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] +* [*Notes:] See [link boost_optional.tutorial.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. @@ -530,7 +533,7 @@ __SPACE__ * [*Postconditions: ] `*this` is initialized and it references the same object referenced by `rhs`. * [*Notes:] If `*this` was initialized, it is ['rebound] to the new object. -See [link boost_optional.rebinding_semantics_for_assignment_of_optional_references here] for details on this behavior. +See [link boost_optional.tutorial.rebinding_semantics_for_assignment_of_optional_references here] for details on this behavior. * [*Example:] `` int a = 1 ; @@ -625,7 +628,7 @@ __SPACE__ 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 ['rebound] to -the new object. See [link boost_optional.rebinding_semantics_for_assignment_of_optional_references here] for details on this behavior. +the new object. See [link boost_optional.tutorial.rebinding_semantics_for_assignment_of_optional_references here] for details on this behavior. * [*Example:] `` int a = 1 ; @@ -773,7 +776,7 @@ 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] +* [*Notes:] See [link boost_optional.tutorial.in_place_factories In-Place Factories] * [*Exception Safety:] Exceptions can only be thrown during the call to the `T` constructor used by the factory; in that case, the `optional` object will be reset to be ['uninitialized]. @@ -790,14 +793,12 @@ __SPACE__ [#reference_optional_reset] [: `void optional::reset() noexcept ;`] -* [*Deprecated:] Same as `operator=( detail::none_t );` +* [*Deprecated:] Same as `operator=( none_t );` __SPACE__ [#reference_optional_get] -[: `T const& optional::operator*() const ;`] -[: `T& optional::operator*();`] [: `T const& optional::get() const ;`] [: `T& optional::get() ;`] @@ -808,6 +809,32 @@ __SPACE__ * [*Returns:] A reference to the contained value * [*Throws:] Nothing. * [*Notes:] The requirement is asserted via `BOOST_ASSERT()`. + +__SPACE__ + +[: `T const& optional::get() const ;`] +[: `T& optional::get() ;`] + +[: `inline T const& get ( optional const& ) ;`] +[: `inline T& get ( optional &) ;`] + +* [*Requires: ] `*this` is initialized +* [*Returns:] [_The] reference contained. +* [*Throws:] Nothing. +* [*Notes:] The requirement is asserted via `BOOST_ASSERT()`. + +__SPACE__ + +[#reference_optional_operator_asterisk] + +[: `T const& optional::operator*() const& ;`] +[: `T& optional::operator*() &;`] +[: `T&& optional::operator*() &&;`] + +* [*Requires:] `*this` is initialized +* [*Returns:] A reference to the contained value +* [*Throws:] Nothing. +* [*Notes:] The requirement is asserted via `BOOST_ASSERT()`. On compilers that do not support ref-qualifiers on member functions these three overloads are replaced with the classical two: a `const` and non-`const` member functions. * [*Example:] `` T v ; @@ -821,14 +848,36 @@ assert ( *opt == w ) ; __SPACE__ +[: `T const& optional::operator*() const& ;`] +[: `T & optional::operator*() & ;`] +[: `T & optional::operator*() && ;`] + +* [*Requires: ] `*this` is initialized +* [*Returns:] [_The] reference contained. +* [*Throws:] Nothing. +* [*Notes:] The requirement is asserted via `BOOST_ASSERT()`. On compilers that do not support ref-qualifiers on member functions these three overloads are replaced with the classical two: a `const` and non-`const` member functions. +* [*Example:] +`` +T v ; +T& vref = v ; +optional opt ( vref ); +T const& vref2 = *opt; +assert ( vref2 == v ) ; +++ v ; +assert ( *opt == v ) ; +`` + +__SPACE__ [#reference_optional_value] -[: `T const& optional::value() const ;`] -[: `T& optional::value();`] +[: `T const& optional::value() const& ;`] +[: `T& optional::value() & ;`] +[: `T&& optional::value() && ;`] * [*Returns:] A reference to the contained value, if `*this` is initialized. * [*Throws:] An instance of `bad_optional_access`, if `*this` is not initialized. +* [*Notes:] On compilers that do not support ref-qualifiers on member functions these three overloads are replaced with the classical two: a `const` and non-`const` member functions. * [*Example:] `` T v ; @@ -848,12 +897,13 @@ __SPACE__ [#reference_optional_value_or] -[: `template T optional::value_or(U && v) const ;`] +[: `template T optional::value_or(U && v) const& ;`] +[: `template T optional::value_or(U && v) && ;`] * [*Requires:] `T` is CopyConstructible. -* [*Returns:] `bool(*this) ? **this : static_cast(forward(v))`. +* [*Returns:] First overload: `bool(*this) ? **this : static_cast(forward(v))`. second overload: `bool(*this) ? std::move(**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&`. +* [*Notes:] On compilers that do not support ref-qualifiers on member functions these three overloads are replaced with the classical two: a `const` and non-`const` member functions. On compilers without rvalue reference support the type of `v` becomes `U const&`. __SPACE__ @@ -881,30 +931,6 @@ assert ( u == v ) ; assert ( u != z ) ; `` -__SPACE__ - -[: `T const& optional::operator*() const ;`] -[: `T & optional::operator*();`] -[: `T const& optional::get() const ;`] -[: `T& optional::get() ;`] - -[: `inline T const& get ( optional const& ) ;`] -[: `inline T& get ( optional &) ;`] - -* [*Requires: ] `*this` is initialized -* [*Returns:] [_The] reference contained. -* [*Throws:] Nothing. -* [*Notes:] The requirement is asserted via `BOOST_ASSERT()`. -* [*Example:] -`` -T v ; -T& vref = v ; -optional opt ( vref ); -T const& vref2 = *opt; -assert ( vref2 == v ) ; -++ v ; -assert ( *opt == v ) ; -`` __SPACE__ diff --git a/doc/Jamfile.v2 b/doc/Jamfile.v2 index 5014bb2..2a8b727 100644 --- a/doc/Jamfile.v2 +++ b/doc/Jamfile.v2 @@ -27,7 +27,8 @@ boostbook standalone boost.root=../../../.. toc.max.depth=2 toc.section.depth=2 - chunk.section.depth=1 + chunk.first.sections=2 + chunk.section.depth=2 pdf:img.src.path=$(images)/ pdf:boost.url.prefix=http://www.boost.org/doc/libs/release/libs/optional/doc/html ; diff --git a/doc/html/boost_optional/a_note_about_optional_bool_.html b/doc/html/boost_optional/a_note_about_optional_bool_.html index 169813c..64f37f6 100644 --- a/doc/html/boost_optional/a_note_about_optional_bool_.html +++ b/doc/html/boost_optional/a_note_about_optional_bool_.html @@ -6,7 +6,7 @@ - + @@ -20,7 +20,7 @@
-PrevUpHomeNext +PrevUpHomeNext

@@ -102,7 +102,7 @@
-PrevUpHomeNext +PrevUpHomeNext
diff --git a/doc/html/boost_optional/acknowledgments.html b/doc/html/boost_optional/acknowledgments.html index 58c4f2d..19d24d9 100644 --- a/doc/html/boost_optional/acknowledgments.html +++ b/doc/html/boost_optional/acknowledgments.html @@ -6,7 +6,7 @@ - + @@ -19,7 +19,7 @@

-PrevUpHome +PrevUpHome

@@ -119,7 +119,7 @@
-PrevUpHome +PrevUpHome
diff --git a/doc/html/boost_optional/dependencies_and_portability.html b/doc/html/boost_optional/dependencies_and_portability.html index 5049104..d9f62c1 100644 --- a/doc/html/boost_optional/dependencies_and_portability.html +++ b/doc/html/boost_optional/dependencies_and_portability.html @@ -6,8 +6,8 @@ - - + + @@ -20,81 +20,19 @@

-PrevUpHomeNext +PrevUpHomeNext
-
Optional +

The implementation uses type_traits/alignment_of.hpp and type_traits/type_with_alignment.hpp

-
- -

- 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. Compilers known to have these deficiencies include - GCC versions 4.2, 4.3, 4.4, 4.5; QCC 4.4.2; MSVC versions 8.0, 9.0, 10.0, - 11.0, 12.0. On these compilers prefer using direct-initialization and copy - assignment of optional references to copy-initialization and assignment from - T&: -

-
const int i = 0;
-optional<const int&> or1;
-optional<const int&> or2 = i;  // not portable
-or1 = i;                       // not portable
-
-optional<const int&> or3(i);   // portable
-or1 = optional<const int&>(i); // portable
-
-

- In order to check if your compiler correctly implements reference binding - use this test program. -

-
#include <cassert>
-
-const int global_i = 0;
-
-struct TestingReferenceBinding
-{
-  TestingReferenceBinding(const int& ii)
-  {
-    assert(&ii == &global_i);
-  }
-
-  void operator=(const int& ii)
-  {
-    assert(&ii == &global_i);
-  }
-
-  void operator=(int&&) // remove this if your compiler doesn't have rvalue refs
-  {
-    assert(false);
-  }
-};
-
-int main()
-{
-  const int& iref = global_i;
-  assert(&iref == &global_i);
-
-  TestingReferenceBinding ttt = global_i;
-  ttt = global_i;
-
-  TestingReferenceBinding ttt2 = iref;
-  ttt2 = iref;
-}
-
-
@@ -106,7 +44,7 @@

-PrevUpHomeNext +PrevUpHomeNext
diff --git a/doc/html/boost_optional/dependencies_and_portability/optional_reference_binding.html b/doc/html/boost_optional/dependencies_and_portability/optional_reference_binding.html new file mode 100644 index 0000000..70316bc --- /dev/null +++ b/doc/html/boost_optional/dependencies_and_portability/optional_reference_binding.html @@ -0,0 +1,100 @@ + + + +Optional Reference Binding + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ 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. Compilers known to have these deficiencies include + GCC versions 4.2, 4.3, 4.4, 4.5; QCC 4.4.2; MSVC versions 8.0, 9.0, 10.0, + 11.0, 12.0. On these compilers prefer using direct-initialization and copy + assignment of optional references to copy-initialization and assignment from + T&: +

+
const int i = 0;
+optional<const int&> or1;
+optional<const int&> or2 = i;  // not portable
+or1 = i;                       // not portable
+
+optional<const int&> or3(i);   // portable
+or1 = optional<const int&>(i); // portable
+
+

+ In order to check if your compiler correctly implements reference binding + use this test program. +

+
#include <cassert>
+
+const int global_i = 0;
+
+struct TestingReferenceBinding
+{
+  TestingReferenceBinding(const int& ii)
+  {
+    assert(&ii == &global_i);
+  }
+
+  void operator=(const int& ii)
+  {
+    assert(&ii == &global_i);
+  }
+
+  void operator=(int&&) // remove this if your compiler doesn't have rvalue refs
+  {
+    assert(false);
+  }
+};
+
+int main()
+{
+  const int& iref = global_i;
+  assert(&iref == &global_i);
+
+  TestingReferenceBinding ttt = global_i;
+  ttt = global_i;
+
+  TestingReferenceBinding ttt2 = iref;
+  ttt2 = iref;
+}
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_optional/detailed_semantics.html b/doc/html/boost_optional/detailed_semantics.html index 8374254..b93515f 100644 --- a/doc/html/boost_optional/detailed_semantics.html +++ b/doc/html/boost_optional/detailed_semantics.html @@ -7,7 +7,7 @@ - + @@ -20,7 +20,7 @@

-PrevUpHomeNext +PrevUpHomeNext

@@ -606,7 +606,7 @@ constructor called by the factory throws.
  • - Notes: See In-Place + Notes: See In-Place Factories
  • @@ -712,7 +712,7 @@
  • Notes: If *this was initialized, it is rebound - to the new object. See here + to the new object. See here for details on this behavior.
  • @@ -872,7 +872,7 @@
  • Notes: If *this was initialized and so is *rhs, *this - is rebound to the new object. See here + is rebound to the new object. See here for details on this behavior.
  • @@ -1147,7 +1147,7 @@ constructor called by the factory throws.
  • - Notes: See In-Place + Notes: See In-Place Factories
  • @@ -1177,20 +1177,12 @@ void optional<T>::reset() noexcept ;

    • - Deprecated: Same as operator=( detail::none_t ); + Deprecated: Same as operator=( none_t );

    space

    - 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 ;

    @@ -1224,6 +1216,76 @@ Notes: The requirement is asserted via BOOST_ASSERT(). +
    +

    + space +

    +

    + T const& optional<T&>::get() const ; +

    +

    + T& + optional<T&>::get() ; +

    +

    + inline T + const& + get ( + optional<T&> const& ) ; +

    +

    + inline T& get ( optional<T&> + &) ; +

    +
      +
    • + Requires: *this is initialized +
    • +
    • + Returns: The + reference contained. +
    • +
    • + Throws: Nothing. +
    • +
    • + Notes: The requirement is asserted via + BOOST_ASSERT(). +
    • +
    +

    + space +

    +

    + T const& optional<T + (not a ref)>::operator*() const& ; +

    +

    + T& + optional<T (not a ref)>::operator*() &; +

    +

    + T&& + optional<T (not a ref)>::operator*() &&; +

    +
      +
    • + Requires: *this is initialized +
    • +
    • + Returns: A reference to the contained + value +
    • +
    • + Throws: Nothing. +
    • +
    • + Notes: The requirement is asserted via + BOOST_ASSERT(). + On compilers that do not support ref-qualifiers on member functions these + three overloads are replaced with the classical two: a const + and non-const member functions. +
    • Example:
      T v ;
      @@ -1236,15 +1298,63 @@
       
    +

    + space +

    +

    + T const& optional<T&>::operator*() const& ; +

    +

    + T & + optional<T&>::operator*() & ; +

    +

    + T & + optional<T&>::operator*() && ; +

    +
      +
    • + Requires: *this is initialized +
    • +
    • + Returns: The + reference contained. +
    • +
    • + Throws: Nothing. +
    • +
    • + Notes: The requirement is asserted via + BOOST_ASSERT(). + On compilers that do not support ref-qualifiers on member functions these + three overloads are replaced with the classical two: a const + and non-const member functions. +
    • +
    • + Example: +
      T v ;
      +T& vref = v ;
      +optional<T&> opt ( vref );
      +T const& vref2 = *opt;
      +assert ( vref2 == v ) ;
      +++ v ;
      +assert ( *opt == v ) ;
      +
      +
    • +

    space

    - T const& optional<T>::value() const ; + T const& optional<T>::value() const& ;

    T& - optional<T>::value(); + optional<T>::value() & ; +

    +

    + T&& + optional<T>::value() && ;

    • @@ -1257,6 +1367,12 @@ if *this is not initialized.
    • +
    • + Notes: On compilers that do not support + ref-qualifiers on member functions these three overloads are replaced with + the classical two: a const + and non-const member functions. +
    • Example:
      T v ;
      @@ -1276,7 +1392,11 @@
       

    template<class U> T optional<T>::value_or(U && - v) const ; + v) const& ; +

    +

    + template<class U> T optional<T>::value_or(U && + v) && ;

    • @@ -1284,17 +1404,22 @@ is CopyConstructible.
    • - Returns: bool(*this) - ? **this : static_cast<T>(forward<U>(v)). + Returns: First overload: bool(*this) ? **this : static_cast<T>(forward<U>(v)). + second overload: bool(*this) ? + std::move(**this) : + static_cast<T>(forward<U>(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&. + Notes: On compilers that do not support + ref-qualifiers on member functions these three overloads are replaced with + the classical two: a const + and non-const member functions. + On compilers without rvalue reference support the type of v becomes U + const&.

    @@ -1348,60 +1473,6 @@

    -

    - 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&> - &) ; -

    -
      -
    • - Requires: *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

    @@ -1898,7 +1969,7 @@
    -PrevUpHomeNext +PrevUpHomeNext
    diff --git a/doc/html/boost_optional/development.html b/doc/html/boost_optional/development.html index 1ff950f..70bc6e4 100644 --- a/doc/html/boost_optional/development.html +++ b/doc/html/boost_optional/development.html @@ -6,7 +6,7 @@ - + @@ -20,7 +20,7 @@
    -PrevUpHomeNext +PrevUpHomeNext

    @@ -406,7 +406,7 @@
    -PrevUpHomeNext +PrevUpHomeNext
    diff --git a/doc/html/boost_optional/discussion.html b/doc/html/boost_optional/discussion.html index 5eb1c93..d17a70e 100644 --- a/doc/html/boost_optional/discussion.html +++ b/doc/html/boost_optional/discussion.html @@ -6,7 +6,7 @@ - + @@ -20,7 +20,7 @@
    -PrevUpHomeNext +PrevUpHomeNext

    @@ -122,7 +122,7 @@
    -PrevUpHomeNext +PrevUpHomeNext
    diff --git a/doc/html/boost_optional/in_place_factories.html b/doc/html/boost_optional/in_place_factories.html index 4bb6fe7..1cc1e05 100644 --- a/doc/html/boost_optional/in_place_factories.html +++ b/doc/html/boost_optional/in_place_factories.html @@ -6,7 +6,7 @@ - + @@ -20,7 +20,7 @@
    -PrevUpHomeNext +PrevUpHomeNext

    @@ -190,7 +190,7 @@
    -PrevUpHomeNext +PrevUpHomeNext
    diff --git a/doc/html/boost_optional/optional_references.html b/doc/html/boost_optional/optional_references.html index 2b36c3e..4da272e 100644 --- a/doc/html/boost_optional/optional_references.html +++ b/doc/html/boost_optional/optional_references.html @@ -6,7 +6,7 @@ - + @@ -20,7 +20,7 @@
    -PrevUpHomeNext +PrevUpHomeNext

    @@ -77,7 +77,7 @@ 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 Dependencies + temporary and bind to it. For more details see Dependencies and Portability section.

    @@ -108,7 +108,7 @@
    -PrevUpHomeNext +PrevUpHomeNext
    diff --git a/doc/html/boost_optional/quick_start.html b/doc/html/boost_optional/quick_start.html new file mode 100644 index 0000000..dbe86fc --- /dev/null +++ b/doc/html/boost_optional/quick_start.html @@ -0,0 +1,261 @@ + + + +Quick Start + + + + + + + + + + + + + + + +
    Boost C++ LibrariesHomeLibrariesPeopleFAQMore
    +
    +
    +PrevUpHomeNext +
    +
    + +

    + + 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/optional.hpp>
    +boost::optionl<int> convert(const std::string& text);
    +
    +

    + All necessary functionality can be included with one header <boost/optional.hpp>. + 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<int> 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<int> 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<int> convert(const std::string& text)
    +{
    +  std::stringstream s(text);
    +  int i;
    +  if ((s >> i) && s.get() == std::char_traits<char>::eof())
    +    return i;
    +  else
    +    return boost::none;
    +}
    +
    +

    + Observe the two return statements. return + i uses the converting constructor + that can create optional<T> 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. +

    +

    + + Optional + automatic variables +

    +

    + We could write function convert + in a slightly different manner, so that it has a single return-statement: +

    +
    boost::optionl<int> convert(const std::string& text)
    +{
    +  boost::optionl<int> ans;
    +  std::stringstream s(text);
    +  int i;
    +  if ((s >> i) && s.get() == std::char_traits<char>::eof())
    +    ans = i;
    +
    +  return ans;
    +}
    +
    +

    + The default constructor of optional + creates an unitialized optional object. Unlike with ints + you cannot have an optional<int> + in an indeterminate state. Its state is always well defined. Instruction ans = i + initializes the optional object. It uses the assignment from int. In general, for optional<T>, + when an assignment from T is + invoked, it can do two things. If the optional object is not initialized our + case here), it initializes it with T's + copy constructor. If the optional object is already initialized, it assigns + the new value to it using T's + copy assignment. +

    +

    + + 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> 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 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]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 In-Place + Factories. +

    +

    + + 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<Date, Date> 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 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<Date> begin, end;
    +boost::tie(begin, end) = getPeriod();
    +
    +

    + It works because inside boost::tie a move-assignment + from T is invoked on optional<T>, which + internally calls a move-constructor of T. +

    +
    + + + +
    +
    +
    +PrevUpHomeNext +
    + + 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 new file mode 100644 index 0000000..33ac25d --- /dev/null +++ b/doc/html/boost_optional/quick_start/bypassing_unnecessary_default_construction.html @@ -0,0 +1,75 @@ + + + +Bypassing unnecessary default construction + + + + + + + + + + + + + + + +
    Boost C++ LibrariesHomeLibrariesPeopleFAQMore
    +
    +
    +PrevUpHomeNext +
    +
    + +

    + 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<Date, Date> 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 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<Date> begin, end;
    +boost::tie(begin, end) = getPeriod();
    +
    +

    + It works because inside boost::tie a + move-assignment from T is + invoked on optional<T>, + which internally calls a move-constructor of T. +

    +
    + + + +
    +
    +
    +PrevUpHomeNext +
    + + diff --git a/doc/html/boost_optional/quick_start/optional_automatic_variables.html b/doc/html/boost_optional/quick_start/optional_automatic_variables.html new file mode 100644 index 0000000..34c9ac7 --- /dev/null +++ b/doc/html/boost_optional/quick_start/optional_automatic_variables.html @@ -0,0 +1,75 @@ + + + +Optional automatic variables + + + + + + + + + + + + + + + +
    Boost C++ LibrariesHomeLibrariesPeopleFAQMore
    +
    +
    +PrevUpHomeNext +
    +
    + +

    + We could write function convert + in a slightly different manner, so that it has a single return-statement: +

    +
    boost::optionl<int> convert(const std::string& text)
    +{
    +  boost::optionl<int> ans;
    +  std::stringstream s(text);
    +  int i;
    +  if ((s >> i) && s.get() == std::char_traits<char>::eof())
    +    ans = i;
    +
    +  return ans;
    +}
    +
    +

    + The default constructor of optional + creates an unitialized optional object. Unlike with ints + you cannot have an optional<int> + in an indeterminate state. Its state is always well defined. Instruction + ans = + i initializes the optional object. + It uses the assignment from int. + In general, for optional<T>, + when an assignment from T + is invoked, it can do two things. If the optional object is not initialized + our case here), it initializes it with T's + copy constructor. If the optional object is already initialized, it assigns + the new value to it using T's + copy assignment. +

    +
    + + + +
    +
    +
    +PrevUpHomeNext +
    + + diff --git a/doc/html/boost_optional/quick_start/optional_data_members.html b/doc/html/boost_optional/quick_start/optional_data_members.html new file mode 100644 index 0000000..00f5457 --- /dev/null +++ b/doc/html/boost_optional/quick_start/optional_data_members.html @@ -0,0 +1,92 @@ + + + +Optional data members + + + + + + + + + + + + + + + +
    Boost C++ LibrariesHomeLibrariesPeopleFAQMore
    +
    +
    +PrevUpHomeNext +
    +
    + +

    + 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> 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 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]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 In-Place + Factories. +

    +
    + + + +
    +
    +
    +PrevUpHomeNext +
    + + diff --git a/doc/html/boost_optional/quick_start/optional_return_values.html b/doc/html/boost_optional/quick_start/optional_return_values.html new file mode 100644 index 0000000..9ad85ef --- /dev/null +++ b/doc/html/boost_optional/quick_start/optional_return_values.html @@ -0,0 +1,135 @@ + + + +Optional return values + + + + + + + + + + + + + + + +
    Boost C++ LibrariesHomeLibrariesPeopleFAQMore
    +
    +
    +PrevUpHomeNext +
    +
    + +

    + 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/optional.hpp>
    +boost::optionl<int> convert(const std::string& text);
    +
    +

    + All necessary functionality can be included with one header <boost/optional.hpp>. + 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<int> 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<int> 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<int> convert(const std::string& text)
    +{
    +  std::stringstream s(text);
    +  int i;
    +  if ((s >> i) && s.get() == std::char_traits<char>::eof())
    +    return i;
    +  else
    +    return boost::none;
    +}
    +
    +

    + Observe the two return statements. return + i uses the converting constructor + that can create optional<T> + 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. +

    +
    + + + +
    +
    +
    +PrevUpHomeNext +
    + + diff --git a/doc/html/boost_optional/reference/detailed_semantics.html b/doc/html/boost_optional/reference/detailed_semantics.html new file mode 100644 index 0000000..c5e5d9e --- /dev/null +++ b/doc/html/boost_optional/reference/detailed_semantics.html @@ -0,0 +1,1963 @@ + + + +Detailed Semantics + + + + + + + + + + + + + + + +
    Boost C++ LibrariesHomeLibrariesPeopleFAQMore
    +
    +
    +PrevUpHomeNext +
    +
    + +

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

    +
    + + optional + class member functions +
    +

    + space +

    +

    + optional<T>::optional() + noexcept; +

    +
      +
    • + Effect: Default-Constructs an optional. +
    • +
    • + Postconditions: *this is uninitialized. +
    • +
    • + Notes: T's default constructor is not called. +
    • +
    • + Example: +
      optional<T> def ;
      +assert ( !def ) ;
      +
      +
    • +
    +

    + space +

    +

    + optional<T>::optional( none_t ) noexcept; +

    +
      +
    • + Effect: Constructs an optional uninitialized. +
    • +
    • + Postconditions: *this is uninitialized. +
    • +
    • + 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 +

    +

    + optional<T (not a ref)>::optional( T const& v ) +

    +
      +
    • + Requires: is_copy_constructible<T>::value + is true. +
    • +
    • + 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 +

    +

    + optional<T (not a ref)>::optional( T&& + v ) +

    +
      +
    • + Requires: is_move_constructible<T>::value + is true. +
    • +
    • + Effect: Directly-Move-Constructs an + optional. +
    • +
    • + Postconditions: *this is initialized + and its value is move-constructed from v. +
    • +
    • + Throws: Whatever T::T( T&& ) + throws. +
    • +
    • + Notes: T::T( T&& ) + is called. +
    • +
    • + Exception Safety: Exceptions can only + be thrown during T::T( T&& + ); in that case, the state of + v is determined by exception + safety guarantees for T::T(T&&). +
    • +
    • + Example: +
      T v1, v2;
      +optional<T> opt(std::move(v1));
      +assert ( *opt == v2 ) ;
      +
      +
    • +
    +

    + space +

    +

    + optional<T&>::optional( T&& + ref ) + = delete +

    +
    • + Notes: This constructor is deleted +
    +

    + space +

    +

    + 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 +

    +

    + optional<T (not a ref)>::optional( optional + const& + rhs ); +

    +
      +
    • + Requires: is_copy_constructible<T>::value + is true. +
    • +
    • + 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 +

    +

    + optional<T (not a ref)>::optional( optional&& rhs + ) noexcept(see below); +

    +
      +
    • + Requires: is_move_constructible<T>::value + is true. +
    • +
    • + Effect: Move-constructs an optional. +
    • +
    • + Postconditions: If rhs + is initialized, *this + is initialized and its value is move constructed from rhs; + else *this + is uninitialized. +
    • +
    • + Throws: Whatever T::T( T&& ) + throws. +
    • +
    • + Notes: If rhs + is initialized, T::T( T && + ) is called. The expression inside + noexcept is equivalent to + is_nothrow_move_constructible<T>::value. +
    • +
    • + Exception Safety: Exceptions can only + be thrown during T::T( T&& + ); in that case, rhs remains initialized and the value + of *rhs + is determined by exception safety of T::T(T&&). +
    • +
    • + Example: +
      optional<std::unique_ptr<T>> uninit ;
      +assert (!uninit);
      +
      +optional<std::unique_ptr<T>> uinit2 ( std::move(uninit) ) ;
      +assert ( uninit2 == uninit );
      +
      +optional<std::unique_ptr<T>> init( std::uniqye_ptr<T>(new T(2)) );
      +assert ( **init == T(2) ) ;
      +
      +optional<std::unique_ptr<T>> init2 ( std::move(init) ) ;
      +assert ( init );
      +assert ( *init == nullptr );
      +assert ( init2 );
      +assert ( **init2 == T(2) ) ;
      +
      +
    • +
    +

    + space +

    +

    + optional<T&>::optional( optional && + rhs ); +

    +
      +
    • + Effect: Move-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<std::unique_ptr<T>&> uninit ;
      +assert (!uninit);
      +
      +optional<std::unique_ptr<T>&> uinit2 ( std::move(uninit) ) ;
      +assert ( uninit2 == uninit );
      +
      +std::unique_ptr<T> v(new T(2)) ;
      +optional<std::unique_ptr<T>&> init(v);
      +assert ( *init == v ) ;
      +
      +optional<std::unique_ptr<T>&> init2 ( std::move(init) ) ;
      +assert ( *init2 == v ) ;
      +
      +*v = 3 ;
      +
      +assert ( **init  == 3 ) ;
      +assert ( **init2 == 3 ) ;
      +
      +
    • +
    +

    + space +

    +

    + 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 +

    +

    + template<U> explicit optional<T + (not a ref)>::optional( optional<U>&& + rhs ); +

    +
      +
    • + Effect: Move-constructs an optional. +
    • +
    • + Postconditions: If rhs + is initialized, *this + is initialized and its value is move constructed from *rhs; else *this is uninitialized. +
    • +
    • + Throws: Whatever T::T( U&& ) + throws. +
    • +
    • + Notes: T::T( U&& ) + 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&& + ); in that case, rhs remains initialized and the value + of *rhs + is determined by exception safety guarantee of T::T( U&& ). +
    • +
    • + Example: +
      optional<double> x(123.4);
      +assert ( *x == 123.4 ) ;
      +
      +optional<int> y(std::move(x)) ;
      +assert( *y == 123 ) ;
      +
      +
    • +
    +

    + space +

    +

    + 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 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 +

    +

    + optional& + optional<T>::operator= ( none_t ) noexcept; +

    +
      +
    • + Effect: If *this is initialized destroys its contained + value. +
    • +
    • + Postconditions: *this is uninitialized. +
    • +
    +

    + space +

    +

    + optional& + optional<T (not a ref)>::operator= ( T + const& + rhs ) + ; +

    +
      +
    • + Effect: Assigns the value rhs to an optional. +
    • +
    • + Postconditions: *this is initialized and its value is a + copy of rhs. +
    • +
    • + Throws: Whatever T::operator=( T const& ) or T::T(T const&) + throws. +
    • +
    • + Notes: If *this was initialized, T's + assignment operator is used, otherwise, its copy-constructor is used. +
    • +
    • + Exception Safety: In the event of an + exception, the initialization state of *this is unchanged and its value unspecified + as far as optional is + concerned (it is up to T's + operator=()). + If *this + is initially uninitialized and T's + copy constructor fails, *this is left properly uninitialized. +
    • +
    • + Example: +
      T x;
      +optional<T> def ;
      +optional<T> opt(x) ;
      +
      +T y;
      +def = y ;
      +assert ( *def == y ) ;
      +opt = y ;
      +assert ( *opt == y ) ;
      +
      +
    • +
    +

    + space +

    +

    + optional<T&>& + optional<T&>::operator= ( T& + rhs ) + ; +

    +
      +
    • + Effect: (Re)binds the wrapped reference. +
    • +
    • + Postconditions: *this is initialized and it references + the same object referenced by rhs. +
    • +
    • + Notes: If *this was initialized, it is rebound + to the new object. See 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 +

    +

    + optional& + optional<T (not a ref)>::operator= ( T&& rhs + ) ; +

    +
      +
    • + Effect: Moves the value rhs to an optional. +
    • +
    • + Postconditions: *this is initialized and its value is moved + from rhs. +
    • +
    • + Throws: Whatever T::operator=( T&& ) + or T::T(T &&) + throws. +
    • +
    • + Notes: If *this was initialized, T's + move-assignment operator is used, otherwise, its move-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 + move constructor fails, *this is left properly uninitialized. +
    • +
    • + Example: +
      T x;
      +optional<T> def ;
      +optional<T> opt(x) ;
      +
      +T y1, y2, yR;
      +def = std::move(y1) ;
      +assert ( *def == yR ) ;
      +opt = std::move(y2) ;
      +assert ( *opt == yR ) ;
      +
      +
    • +
    +

    + space +

    +

    + optional<T&>& + optional<T&>::operator= ( T&& + rhs ) + = delete; +

    +
    • + Notes: This assignment operator is deleted. +
    +

    + space +

    +

    + 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 rebound to the new object. See 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 +

    +

    + optional& + optional<T (not a ref)>::operator= ( optional&& rhs + ) noexcept(see below); +

    +
      +
    • + Effect: Move-assigns another optional to an optional. +
    • +
    • + Postconditions: If rhs + is initialized, *this + is initialized and its value is moved from *rhs, rhs + remains initialized; else *this is uninitialized. +
    • +
    • + Throws: Whatever T::operator( T&& ) + or T::T( T && + ) throws. +
    • +
    • + Notes: If both *this and rhs + are initially initialized, T's + move 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 + move constructor is called. The expression inside + noexcept is equivalent to + is_nothrow_move_constructible<T>::value + && is_nothrow_move_assignable<T>::value. +
    • +
    • + 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 + move constructor fails, *this is left properly uninitialized. +
    • +
    • + Example: +
      optional<T> opt(T(2)) ;
      +optional<T> def ;
      +
      +opt = def ;
      +assert ( def ) ;
      +assert ( opt ) ;
      +assert ( *opt == T(2) ) ;
      +
      +
    • +
    +

    + space +

    +

    + optional<T&> + & optional<T&>::operator= ( optional<T&>&& rhs + ) ; +

    +
    • + Effect: Same as optional<T&>::operator= ( optional<T&> const& rhs + ). +
    +

    + space +

    +

    + 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 +

    +

    + template<U> optional& + optional<T (not a ref)>::operator= ( optional<U>&& rhs + ) ; +

    +
      +
    • + Effect: Move-assigns another convertible + optional to an optional. +
    • +
    • + Postconditions: If rhs + is initialized, *this + is initialized and its value is moved from the value of rhs; else *this is uninitialized. +
    • +
    • + Throws: Whatever T::operator=( U&& ) + or T::T( U&& + ) 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 = std::move(opt0) ;
      +assert ( *opt1 == static_cast<U>(v) ) ;
      +
      +
    • +
    +

    + space +

    +

    + template<class... Args> void optional<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. +
    • +
    +

    + space +

    +

    + template<InPlaceFactory> + optional<T>& + optional<T (not a ref)>::operator=( InPlaceFactory + const& + f ); +

    +

    + template<TypedInPlaceFactory> + optional<T>& + optional<T (not a ref)>::operator=( TypedInPlaceFactory + const& + f ); +

    +
      +
    • + Effect: Assigns an optional + with a value of T obtained + from the factory. +
    • +
    • + Postconditions: *this is initialized + and its value is directly given from the factory + f (i.e., the value is not copied). +
    • +
    • + Throws: Whatever the T + constructor called by the factory throws. +
    • +
    • + Notes: See In-Place + Factories +
    • +
    • + Exception Safety: Exceptions can only + be thrown during the call to the T + constructor used by the factory; in that case, the optional + object will be reset to be uninitialized. +
    • +
    +

    + space +

    +

    + void optional<T + (not a ref)>::reset( T const& v ) ; +

    +
    • + Deprecated: same as operator= ( T + const& + v) + ; +
    +

    + space +

    +

    + void optional<T>::reset() noexcept ; +

    +
    • + Deprecated: Same as operator=( none_t + ); +
    +

    + space +

    +

    + 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)> + &) ; +

    +
      +
    • + Requires: *this is initialized +
    • +
    • + Returns: A reference to the contained + value +
    • +
    • + Throws: Nothing. +
    • +
    • + Notes: The requirement is asserted via + BOOST_ASSERT(). +
    • +
    +

    + space +

    +

    + T const& optional<T&>::get() const ; +

    +

    + T& + optional<T&>::get() ; +

    +

    + inline T + const& + get ( + optional<T&> + const& + ) ; +

    +

    + inline T& get ( optional<T&> &) + ; +

    +
      +
    • + Requires: *this is initialized +
    • +
    • + Returns: The + reference contained. +
    • +
    • + Throws: Nothing. +
    • +
    • + Notes: The requirement is asserted via + BOOST_ASSERT(). +
    • +
    +

    + space +

    +

    + T const& optional<T + (not a ref)>::operator*() const& ; +

    +

    + T& + optional<T (not a ref)>::operator*() &; +

    +

    + T&& + optional<T (not a ref)>::operator*() &&; +

    +
      +
    • + Requires: *this is initialized +
    • +
    • + Returns: A reference to the contained + value +
    • +
    • + Throws: Nothing. +
    • +
    • + Notes: The requirement is asserted via + BOOST_ASSERT(). + On compilers that do not support ref-qualifiers on member functions these + three overloads are replaced with the classical two: a const and non-const + member functions. +
    • +
    • + Example: +
      T v ;
      +optional<T> opt ( v );
      +T const& u = *opt;
      +assert ( u == v ) ;
      +T w ;
      +*opt = w ;
      +assert ( *opt == w ) ;
      +
      +
    • +
    +

    + space +

    +

    + T const& optional<T&>::operator*() const& ; +

    +

    + T & + optional<T&>::operator*() & ; +

    +

    + T & + optional<T&>::operator*() && ; +

    +
      +
    • + Requires: *this is initialized +
    • +
    • + Returns: The + reference contained. +
    • +
    • + Throws: Nothing. +
    • +
    • + Notes: The requirement is asserted via + BOOST_ASSERT(). + On compilers that do not support ref-qualifiers on member functions these + three overloads are replaced with the classical two: a const and non-const + member functions. +
    • +
    • + Example: +
      T v ;
      +T& vref = v ;
      +optional<T&> opt ( vref );
      +T const& vref2 = *opt;
      +assert ( vref2 == v ) ;
      +++ v ;
      +assert ( *opt == v ) ;
      +
      +
    • +
    +

    + space +

    +

    + T const& optional<T>::value() const& ; +

    +

    + T& + optional<T>::value() & ; +

    +

    + T&& + optional<T>::value() && ; +

    +
      +
    • + Returns: A reference to the contained + value, if *this + is initialized. +
    • +
    • + Throws: An instance of bad_optional_access, if *this + is not initialized. +
    • +
    • + Notes: On compilers that do not support + ref-qualifiers on member functions these three overloads are replaced + with the classical two: a const + and non-const member functions. +
    • +
    • + Example: +
      T v ;
      +optional<T> o0, o1 ( v );
      +assert ( o1.value() == v );
      +
      +try {
      +  o0.value(); // throws
      +  assert ( false );
      +}
      +catch(bad_optional_access&) {
      +  assert ( true );
      +}
      +
      + space +
    • +
    +

    + template<class U> T optional<T>::value_or(U && + v) + const& + ; +

    +

    + template<class U> T optional<T>::value_or(U && + v) + && ; +

    +
      +
    • + Requires: T + is CopyConstructible. +
    • +
    • + Returns: First overload: bool(*this) ? **this + : static_cast<T>(forward<U>(v)). second overload: bool(*this) ? std::move(**this) : static_cast<T>(forward<U>(v)). +
    • +
    • + Throws: Any exception thrown by the + selected constructor of T. +
    • +
    • + Notes: On compilers that do not support + ref-qualifiers on member functions these three overloads are replaced + with the classical two: a const + and non-const member functions. + On compilers without rvalue reference support the type of v becomes U + const&. +
    • +
    +

    + space +

    +

    + 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 ) + ; +

    +
      +
    • + Deprecated: Use value_or() instead. +
    • +
    • + 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 + (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 +

    +

    + T const* optional<T + (not a ref)>::operator ->() + const ; +

    +

    + T* + optional<T (not a ref)>::operator + ->() ; +

    +
      +
    • + Requires: *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 +

    +

    + explicit optional<T>::operator + bool() + const ; +

    +
      +
    • + Returns: get_ptr() != 0. +
    • +
    • + Throws: Nothing. +
    • +
    • + Notes: On compilers that do not support + explicit conversion operators this falls back to safe-bool idiom. +
    • +
    • + Example: +
      optional<T> def ;
      +assert ( def == 0 );
      +optional<T> opt ( v ) ;
      +assert ( opt );
      +assert ( opt != 0 );
      +
      +
    • +
    +

    + space +

    +

    + bool optional<T>::operator!() noexcept ; +

    +
      +
    • + Returns: If *this is uninitialized, true; + else false. +
    • +
    • + 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 +

    +

    + bool optional<T>::is_initialized() const ; +

    +
    • + Deprecated: Same as explicit + operator bool + () ; +
    +

    + space +

    +
    + + Free + functions +
    +

    + space +

    +

    + 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 +

    +

    + 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 +

    +

    + bool operator + == ( optional<T> const& x, optional<T> const& y ); +

    +
      +
    • + Requires: T + shall meet requirements of EqualityComparable. +
    • +
    • + 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 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 +

    +

    + bool operator + < ( + optional<T> const& x, optional<T> const& y ); +

    +
      +
    • + Requires: T + shall meet requirements of LessThanComparable. +
    • +
    • + 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 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 +

    +

    + bool operator + != ( optional<T> const& x, optional<T> const& y ); +

    +
      +
    • + Returns: !( + x == + y ); +
    • +
    • + Throws: Nothing. +
    • +
    +

    + space +

    +

    + bool operator + > ( + optional<T> const& x, optional<T> const& y ); +

    +
      +
    • + Returns: ( + y < + x ); +
    • +
    • + Throws: Nothing. +
    • +
    +

    + space +

    +

    + bool operator + <= ( + optional<T> const& x, optional<T> const& y ); +

    +
      +
    • + Returns: !( + y < + x ); +
    • +
    • + Throws: Nothing. +
    • +
    +

    + space +

    +

    + bool operator + >= ( + optional<T> const& x, optional<T> const& y ); +

    +
      +
    • + Returns: !( + x<y ); +
    • +
    • + Throws: Nothing. +
    • +
    +

    + bool operator + == ( optional<T> const& x, none_t + ) noexcept; +

    +
      +
    • + Returns: !x. +
    • +
    • + Notes: T + need not meet requirements of EqualityComparable. +
    • +
    +

    + space +

    +

    + bool operator + != ( optional<T> const& x, none_t + ) noexcept; +

    +
    • + Returns: !( + x == + y ); +
    +

    + space +

    +

    + 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&& ) + 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&& ) + 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>::operator= ( T&& ). +
    • +
    • + 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 );
      +
      +
    • +
    +
    + + + +
    +
    +
    +PrevUpHomeNext +
    + + diff --git a/doc/html/boost_optional/reference/synopsis.html b/doc/html/boost_optional/reference/synopsis.html new file mode 100644 index 0000000..99adcfd --- /dev/null +++ b/doc/html/boost_optional/reference/synopsis.html @@ -0,0 +1,174 @@ + + + +Synopsis + + + + + + + + + + + + + + + +
    Boost C++ LibrariesHomeLibrariesPeopleFAQMore
    +
    +
    +PrevUpHomeNext +
    +
    + +
    // In Header: <boost/optional/optional.hpp>
    +
    +namespace boost {
    +
    +template<class T>
    +class optional
    +{
    +    public :
    +
    +    // (If T is of reference type, the parameters and results by reference are by value)
    +
    +    optional () noexcept ; R
    +
    +    optional ( none_t ) noexcept ; R
    +
    +    optional ( T const& v ) ; R
    +
    +    optional ( T&& v ) ; R
    +
    +    // [new in 1.34]
    +    optional ( bool condition, T const& v ) ; R
    +
    +    optional ( optional const& rhs ) ; R
    +
    +    optional ( optional&& rhs ) noexcept(see below) ; R
    +
    +    template<class U> explicit optional ( optional<U> const& rhs ) ; R
    +
    +    template<class U> explicit optional ( optional<U>&& rhs ) ; R
    +
    +    template<class InPlaceFactory> explicit optional ( InPlaceFactory const& f ) ; R
    +
    +    template<class TypedInPlaceFactory> explicit optional ( TypedInPlaceFactory const& f ) ; R
    +
    +    optional& operator = ( none_t ) noexcept ; R
    +
    +    optional& operator = ( T const& v ) ; R
    +
    +    optional& operator = ( T&& v ) ; R
    +
    +    optional& operator = ( optional const& rhs ) ; R
    +
    +    optional& operator = ( optional&& rhs ) noexcept(see below) ; R
    +
    +    template<class U> optional& operator = ( optional<U> const& rhs ) ; R
    +
    +    template<class U> optional& operator = ( optional<U>&& rhs ) ; R
    +
    +    template<class... Args> void emplace ( Args...&& args ) ; R
    +
    +    template<class InPlaceFactory> optional& operator = ( InPlaceFactory const& f ) ; R
    +
    +    template<class TypedInPlaceFactory> optional& operator = ( TypedInPlaceFactory const& f ) ; R
    +
    +    T const& get() const ; R
    +    T&       get() ; R
    +
    +    T const* operator ->() const ; R
    +    T*       operator ->() ; R
    +
    +    T const& operator *() const& ; R
    +    T&       operator *() &; R
    +    T&&      operator *() &&; R
    +
    +    T const& value() const& ; R
    +    T&       value() & ; R
    +    T&&      value() && ; R
    +
    +    template<class U> T value_or( U && v ) const& ; R
    +    template<class U> T value_or( U && v ) && ; R
    +
    +    T const* get_ptr() const ; R
    +    T*       get_ptr() ; R
    +
    +    explicit operator bool() const ; R
    +
    +    bool operator!() const noexcept ; R
    +
    +    // deprecated methods
    +
    +    // (deprecated)
    +    void reset() noexcept ; R
    +
    +    // (deprecated)
    +    void reset ( T const& ) ; R
    +
    +    // (deprecated)
    +    bool is_initialized() const ; R
    +
    +    // (deprecated)
    +    T const& get_value_or( T const& default ) const ; R
    +};
    +
    +template<class T> inline bool operator == ( optional<T> const& x, optional<T> const& y ) ; R
    +
    +template<class T> inline bool operator != ( optional<T> const& x, optional<T> const& y ) ; R
    +
    +template<class T> inline bool operator <  ( optional<T> const& x, optional<T> const& y ) ; R
    +
    +template<class T> inline bool operator >  ( optional<T> const& x, optional<T> const& y ) ; R
    +
    +template<class T> inline bool operator <= ( optional<T> const& x, optional<T> const& y ) ; R
    +
    +template<class T> inline bool operator >= ( optional<T> const& x, optional<T> const& y ) ; R
    +
    +template<class T> inline bool operator == ( optional<T> const& x, none_t ) noexcept ; R
    +
    +template<class T> inline bool operator != ( optional<T> const& x, none_t ) noexcept ; R
    +
    +template<class T> inline optional<T> make_optional ( T const& v ) ; R
    +
    +template<class T> inline optional<T> make_optional ( bool condition, T const& v ) ; R
    +
    +template<class T> inline T const& get_optional_value_or ( optional<T> const& opt, T const& default ) ; R
    +
    +template<class T> inline T const& get ( optional<T> const& opt ) ; R
    +
    +template<class T> inline T& get ( optional<T> & opt ) ; R
    +
    +template<class T> inline T const* get ( optional<T> const* opt ) ; R
    +
    +template<class T> inline T* get ( optional<T>* opt ) ; R
    +
    +template<class T> inline T const* get_pointer ( optional<T> const& opt ) ; R
    +
    +template<class T> inline T* get_pointer ( optional<T> & opt ) ; R
    +
    +template<class T> inline void swap( optional<T>& x, optional<T>& y ) ; R
    +
    +} // namespace boost
    +
    +
    + + + +
    +
    +
    +PrevUpHomeNext +
    + + diff --git a/doc/html/boost_optional/synopsis.html b/doc/html/boost_optional/synopsis.html index b350ded..0de90e7 100644 --- a/doc/html/boost_optional/synopsis.html +++ b/doc/html/boost_optional/synopsis.html @@ -6,7 +6,7 @@ - + @@ -20,7 +20,7 @@
    -PrevUpHomeNext +PrevUpHomeNext

    @@ -86,13 +86,16 @@ T const* operator ->() const ; R T* operator ->() ; R - T const& operator *() const ; R - T& operator *() ; R + T const& operator *() const& ; R + T& operator *() &; R + T&& operator *() &&; R - T const& value() const ; R - T& value() ; R + T const& value() const& ; R + T& value() & ; R + T&& value() && ; R - template<class U> T value_or( U && v ) const ; R + template<class U> T value_or( U && v ) const& ; R + template<class U> T value_or( U && v ) && ; R T const* get_ptr() const ; R T* get_ptr() ; R @@ -165,7 +168,7 @@
    -PrevUpHomeNext +PrevUpHomeNext
    diff --git a/doc/html/boost_optional/tutorial.html b/doc/html/boost_optional/tutorial.html index c1b6173..8f033e8 100644 --- a/doc/html/boost_optional/tutorial.html +++ b/doc/html/boost_optional/tutorial.html @@ -6,8 +6,8 @@ - - + + @@ -20,207 +20,491 @@

    -PrevUpHomeNext +PrevUpHomeNext

    - 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: + Consider these functions which should return a value but which might not + have a value to return:

    -
    #include <boost/optional.hpp>
    -boost::optionl<int> convert(const std::string& text);
    +
      +
    • + (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();
     

    - All necessary functionality can be included with one header <boost/optional.hpp>. - 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: + These functions use a consistent interface for dealing with possibly nonexistent + results:

    -
    const std::string& text = /*... */;
    -boost::optionl<int> oi = convert(text); // move-construct
    -if (oi)                                 // contextual conversion to bool
    -  int i = *oi;                          // operator*
    +
    std::pair<point,bool> p = poly.get_any_point_effectively_inside();
    +if ( p.second )
    +    flood_fill(p.first);
     

    - 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: + 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.

    -
    if (boost::optionl<int> 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<int> convert(const std::string& text)
    -{
    -  std::stringstream s(text);
    -  int i;
    -  if ((s >> i) && s.get() == std::char_traits<char>::eof())
    -    return i;
    -  else
    -    return boost::none;
    -}
    -
    -

    - Observe the two return statements. return - i uses the converting constructor - that can create optional<T> - 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. + Clearly, we need a better idiom.

    + +
    +

    - 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> resource_;
    -
    -public:
    -  Widget() {}
    -
    -  Resource& getResource() // not thread-safe
    -  {
    -    if (resource_ == boost::none)
    -        resource_.emplace("resource", "arguments");
    -
    -    return *resource_;
    -  }
    -};
    -
    + In C++, we can declare an object (a variable) of type + T, and we can give this + 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 (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 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. +

    - 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 even have to be MoveConstructible. -

    -
    + 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—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 Haskell + Maybe built-in type constructor. Thus, + a discriminated union T+nil_t + serves as a conceptual foundation. +

    +

    + A variant<T,nil_t> follows naturally from the traditional + idiom of extending the range of possible values adding an additional sentinel + value with the special meaning of Nothing. However, + this additional Nothing value is largely irrelevant + for our purpose since our goal is to formalize the notion of uninitialized + objects and, while a special extended value can be used to convey that + meaning, it is not strictly necessary in order to do so. +

    +

    + The observation made in the last paragraph about the irrelevant nature + of the additional nil_t + with respect to purpose of optional<T> + suggests an alternative model: a container that either + has a value of T or nothing. +

    +

    + As of this writing I don't know of any precedent for a variable-size fixed-capacity + (of 1) stack-based container model for optional values, yet I believe this + is the consequence of the lack of practical implementations of such a container + rather than an inherent shortcoming of the container model. +

    +

    + In any event, both the discriminated-union or the single-element container + models serve as a conceptual ground for a class representing optional—i.e. + possibly uninitialized—objects. For instance, these models show the + exact semantics required for a wrapper of optional + values: +

    +

    + Discriminated-union: +

    +
      +
    • + deep-copy semantics: copies of the + variant implies copies of the value. +
    • +
    • + deep-relational semantics: comparisons + between variants matches both current types and values +
    • +
    • + If the variant's current type is T, + it is modeling an initialized optional. +
    • +
    • + If the variant's current type is not T, + it is modeling an uninitialized optional. +
    • +
    • + Testing if the variant's current type is T + models testing if the optional is initialized +
    • +
    • + Trying to extract a T + from a variant when its current type is not T, + models the undefined behavior of trying to access the value of an uninitialized + optional +
    • +
    +

    + Single-element container: +

    +
      +
    • + deep-copy semantics: copies of the + container implies copies of the value. +
    • +
    • + deep-relational semantics: comparisons + between containers compare container size and if match, contained value +
    • +
    • + If the container is not empty (contains an object of type T), it is modeling an initialized + optional. +
    • +
    • + If the container is empty, it is modeling an uninitialized + optional. +
    • +
    • + Testing if the container is empty models testing if the optional is + initialized +
    • +
    • + Trying to extract a T + from an empty container models the undefined behavior of trying to + access the value of an uninitialized optional +
    • +
    + +
    + +

    + 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. +

    +
    +
    + +

    + 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. +

    +
    + + Lexically-hinted + Value Access in the presence of possibly untitialized optional objects: + The operators * and -> +
    +

    + A relevant feature of a pointer is that it can have a null + pointer value. This is a special value + which is used to indicate that the pointer is not referring to any object + at all. In other words, null pointer values convey the notion of nonexistent + objects. +

    +

    + This meaning of the null pointer value allowed pointers to became a de + facto standard for handling optional objects because all you + have to do to refer to a value which you don't really have is to use a + null pointer value of the appropriate type. Pointers have been used for + decades—from the days of C APIs to modern C++ libraries—to refer + to optional (that is, possibly nonexistent) objects; particularly as optional + arguments to a function, but also quite often as optional data members. +

    +

    + The possible presence of a null pointer value makes the operations that + access the pointee's value possibly undefined, therefore, expressions which + use dereference and access operators, such as: ( + *p + = 2 ) and ( + p->foo() ), implicitly convey the notion of optionality, + and this information is tied to the syntax of the + expressions. That is, the presence of operators * + and -> tell by themselves + —without any additional context— that the expression will be undefined + unless the implied pointee actually exist. +

    +

    + Such a de facto idiom for referring to optional objects + can be formalized in the form of a concept: the OptionalPointee + concept. This concept captures the syntactic usage of operators *, -> + and 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 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 + OptionalPointee + concept incarnated by pointers. +

    +
    + + 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. +

    +
    - - + + + However, it is particularly important to note that optional<> objects are not pointers. optional<> is not, and does not model, a + pointer. +

    [Note]Note[Warning]Warning

    - 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 In-Place - Factories. -

    +

    + 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 equal_pointees() + and less_pointees() + instead. +

    -
    - -

    - 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<Date, Date> 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<Date> begin, end;
    -boost::tie(begin, end) = getPeriod();
    -
    -

    - It works because inside boost::tie a - move-assignment from T is - invoked on optional<T>, - which internally calls a move-constructor of T. -

    @@ -233,7 +517,7 @@

    -PrevUpHomeNext +PrevUpHomeNext
    diff --git a/doc/html/boost_optional/tutorial/a_note_about_optional_bool_.html b/doc/html/boost_optional/tutorial/a_note_about_optional_bool_.html new file mode 100644 index 0000000..706bf49 --- /dev/null +++ b/doc/html/boost_optional/tutorial/a_note_about_optional_bool_.html @@ -0,0 +1,108 @@ + + + +A note about optional<bool> + + + + + + + + + + + + + + + +
    Boost C++ LibrariesHomeLibrariesPeopleFAQMore
    +
    +
    +PrevUpHomeNext +
    +
    + +

    + 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, although optional<> provides a contextual conversion + to bool in C++11, this falls + back to an implicit conversion on older compilers. 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). +

    +

    + Third, mixed comparisons with bool + work differently than similar mixed comparisons between pointers and bool, so the results might surprise you: +

    +
    optional<bool> oEmpty(none), oTrue(true), oFalse(false);
    +
    +if (oEmpty == none);  // renders true
    +if (oEmpty == false); // renders false!
    +if (oEmpty == true);  // renders false!
    +
    +if (oFalse == none);  // renders false
    +if (oFalse == false); // renders true!
    +if (oFalse == true);  // renders false
    +
    +if (oTrue == none);   // renders false
    +if (oTrue == false);  // renders false
    +if (oTrue == true);   // renders true
    +
    +

    + In other words, for optional<>, the following assertion does not + hold: +

    +
    assert((opt == false) == (!opt));
    +
    +
    + + + +
    +
    +
    +PrevUpHomeNext +
    + + diff --git a/doc/html/boost_optional/tutorial/design_overview.html b/doc/html/boost_optional/tutorial/design_overview.html new file mode 100644 index 0000000..d2493ce --- /dev/null +++ b/doc/html/boost_optional/tutorial/design_overview.html @@ -0,0 +1,423 @@ + + + +Design Overview + + + + + + + + + + + + + + + +
    Boost C++ LibrariesHomeLibrariesPeopleFAQMore
    +
    +
    +PrevUpHomeNext +
    +
    + + +
    + +

    + In C++, we can declare an object (a variable) of type + T, and we can give this + 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 (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 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—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 Haskell + Maybe built-in type constructor. Thus, + a discriminated union T+nil_t + serves as a conceptual foundation. +

    +

    + A variant<T,nil_t> follows naturally from the traditional + idiom of extending the range of possible values adding an additional sentinel + value with the special meaning of Nothing. However, + this additional Nothing value is largely irrelevant + for our purpose since our goal is to formalize the notion of uninitialized + objects and, while a special extended value can be used to convey that + meaning, it is not strictly necessary in order to do so. +

    +

    + The observation made in the last paragraph about the irrelevant nature + of the additional nil_t + with respect to purpose of optional<T> + suggests an alternative model: a container that either + has a value of T or nothing. +

    +

    + As of this writing I don't know of any precedent for a variable-size fixed-capacity + (of 1) stack-based container model for optional values, yet I believe this + is the consequence of the lack of practical implementations of such a container + rather than an inherent shortcoming of the container model. +

    +

    + In any event, both the discriminated-union or the single-element container + models serve as a conceptual ground for a class representing optional—i.e. + possibly uninitialized—objects. For instance, these models show the + exact semantics required for a wrapper of optional + values: +

    +

    + Discriminated-union: +

    +
      +
    • + deep-copy semantics: copies of the + variant implies copies of the value. +
    • +
    • + deep-relational semantics: comparisons + between variants matches both current types and values +
    • +
    • + If the variant's current type is T, + it is modeling an initialized optional. +
    • +
    • + If the variant's current type is not T, + it is modeling an uninitialized optional. +
    • +
    • + Testing if the variant's current type is T + models testing if the optional is initialized +
    • +
    • + Trying to extract a T + from a variant when its current type is not T, + models the undefined behavior of trying to access the value of an uninitialized + optional +
    • +
    +

    + Single-element container: +

    +
      +
    • + deep-copy semantics: copies of the + container implies copies of the value. +
    • +
    • + deep-relational semantics: comparisons + between containers compare container size and if match, contained value +
    • +
    • + If the container is not empty (contains an object of type T), it is modeling an initialized + optional. +
    • +
    • + If the container is empty, it is modeling an uninitialized + optional. +
    • +
    • + Testing if the container is empty models testing if the optional is + initialized +
    • +
    • + Trying to extract a T + from an empty container models the undefined behavior of trying to + access the value of an uninitialized optional +
    • +
    +
    +
    + +

    + 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. +

    +
    +
    + +

    + 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. +

    +
    + + Lexically-hinted + Value Access in the presence of possibly untitialized optional objects: + The operators * and -> +
    +

    + A relevant feature of a pointer is that it can have a null + pointer value. This is a special value + which is used to indicate that the pointer is not referring to any object + at all. In other words, null pointer values convey the notion of nonexistent + objects. +

    +

    + This meaning of the null pointer value allowed pointers to became a de + facto standard for handling optional objects because all you + have to do to refer to a value which you don't really have is to use a + null pointer value of the appropriate type. Pointers have been used for + decades—from the days of C APIs to modern C++ libraries—to refer + to optional (that is, possibly nonexistent) objects; particularly as optional + arguments to a function, but also quite often as optional data members. +

    +

    + The possible presence of a null pointer value makes the operations that + access the pointee's value possibly undefined, therefore, expressions which + use dereference and access operators, such as: ( + *p + = 2 ) and ( + p->foo() ), implicitly convey the notion of optionality, + and this information is tied to the syntax of the + expressions. That is, the presence of operators * + and -> tell by themselves + —without any additional context— that the expression will be undefined + unless the implied pointee actually exist. +

    +

    + Such a de facto idiom for referring to optional objects + can be formalized in the form of a concept: the OptionalPointee + concept. This concept captures the syntactic usage of operators *, -> + and 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 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 + OptionalPointee + concept incarnated by pointers. +

    +
    + + 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]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 equal_pointees() + and less_pointees() + instead. +

    +
    +
    + + + +
    +
    +
    +PrevUpHomeNext +
    + + diff --git a/doc/html/boost_optional/tutorial/exception_safety_guarantees.html b/doc/html/boost_optional/tutorial/exception_safety_guarantees.html new file mode 100644 index 0000000..ede593d --- /dev/null +++ b/doc/html/boost_optional/tutorial/exception_safety_guarantees.html @@ -0,0 +1,175 @@ + + + +Exception Safety Guarantees + + + + + + + + + + + + + + + +
    Boost C++ LibrariesHomeLibrariesPeopleFAQMore
    +
    +
    +PrevUpHomeNext +
    +
    + +

    + This library assumes that T's + destructor does not throw exceptions. If it does, the behaviour of many operations + on optional<T> is + undefined. +

    +

    + The following mutating operations never throw exceptions: +

    +
      +
    • + optional<T>::operator= ( none_t + ) noexcept +
    • +
    • + optional<T>::reset() noexcept +
    • +
    +

    + In addition, the following constructors and the destructor never throw exceptions: +

    +
      +
    • + optional<T>::optional() + noexcept +
    • +
    • + optional<T>::optional( + none_t ) + noexcept +
    • +
    +

    + Regarding the following assignment functions: +

    +
      +
    • + 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& ) +
    • +
    +

    + They forward calls to the corresponding T's + constructors or assignments (depending on whether the optional object is + initialized or not); so if both T's + constructor and the assignment provide strong exception safety guarantee, + optional<T>'s + assignment also provides strong exception safety guarantee; otherwise we + only get the basic guarantee. Additionally, if both involved T's constructor and the assignment never + throw, optional<T>'s + assignment also never throws. +

    +

    + Unless T's constructor or + assignment 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: +

    +
    optional<T> opt1(val1);
    +optional<T> opt2(val2);
    +assert(opt1);
    +assert(opt2);
    +
    +try
    +{
    +  opt1 = opt2; // throws
    +}
    +catch(...)
    +{
    +  assert(opt1);
    +  assert(opt2);
    +}
    +
    +

    + 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. +

    +
    + + 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<T> never + throws. similarly, if both T's + swap and move constructor + offer strong guarantee, swap + on optional<T> also + offers a strong guarantee. +

    +

    + In case swap on optional + is customized, the call to T's + move constructor are replaced with the calls to T's + default constructor followed by swap. + (This is more useful on older compilers that do not support move semantics, + when one wants to acheive stronger exception safety guarantees.) In this + case the exception safety guarantees for swap + are reliant on the guarantees of T's + swap and default constructor +

    +
    + + + +
    +
    +
    +PrevUpHomeNext +
    + + diff --git a/doc/html/boost_optional/tutorial/in_place_factories.html b/doc/html/boost_optional/tutorial/in_place_factories.html new file mode 100644 index 0000000..3d7500a --- /dev/null +++ b/doc/html/boost_optional/tutorial/in_place_factories.html @@ -0,0 +1,197 @@ + + + +In-Place Factories + + + + + + + + + + + + + + + +
    Boost C++ LibrariesHomeLibrariesPeopleFAQMore
    +
    +
    +PrevUpHomeNext +
    +
    + +

    + 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 +

    +
    + + + +
    +
    +
    +PrevUpHomeNext +
    + + diff --git a/doc/html/boost_optional/tutorial/motivation.html b/doc/html/boost_optional/tutorial/motivation.html new file mode 100644 index 0000000..3b9f43c --- /dev/null +++ b/doc/html/boost_optional/tutorial/motivation.html @@ -0,0 +1,129 @@ + + + +Motivation + + + + + + + + + + + + + + + +
    Boost C++ LibrariesHomeLibrariesPeopleFAQMore
    +
    +
    +PrevUpHomeNext +
    +
    + +

    + Consider these functions which should return a value but which might not + have a value to return: +

    +
      +
    • + (A) double sqrt(double n ); +
    • +
    • + (B) char get_async_input(); +
    • +
    • + (C) point polygon::get_any_point_effectively_inside(); +
    • +
    +

    + There are different approaches to the issue of not having a value to return. +

    +

    + A typical approach is to consider the existence of a valid return value as + a postcondition, so that if the function cannot compute the value to return, + it has either undefined behavior (and can use assert in a debug build) or + uses a runtime check and throws an exception if the postcondition is violated. + This is a reasonable choice for example, for function (A), because the lack + of a proper return value is directly related to an invalid parameter (out + of domain argument), so it is appropriate to require the callee to supply + only parameters in a valid domain for execution to continue normally. +

    +

    + However, function (B), because of its asynchronous nature, does not fail + just because it can't find a value to return; so it is incorrect to consider + such a situation an error and assert or throw an exception. This function + must return, and somehow, must tell the callee that it is not returning a + meaningful value. +

    +

    + A similar situation occurs with function (C): it is conceptually an error + to ask a null-area polygon to return a point inside + itself, but in many applications, it is just impractical for performance + reasons to treat this as an error (because detecting that the polygon has + no area might be too expensive to be required to be tested previously), and + either an arbitrary point (typically at infinity) is returned, or some efficient + way to tell the callee that there is no such point is used. +

    +

    + There are various mechanisms to let functions communicate that the returned + value is not valid. One such mechanism, which is quite common since it has + zero or negligible overhead, is to use a special value which is reserved + to communicate this. Classical examples of such special values are EOF, string::npos, + points at infinity, etc... +

    +

    + When those values exist, i.e. the return type can hold all meaningful values + plus the signal value, this mechanism + is quite appropriate and well known. Unfortunately, there are cases when + such values do not exist. In these cases, the usual alternative is either + to use a wider type, such as int + in place of char; or a compound + type, such as std::pair<point,bool>. +

    +

    + Returning a std::pair<T,bool>, thus attaching a boolean flag to the + result which indicates if the result is meaningful, has the advantage that + can be turned into a consistent idiom since the first element of the pair + can be whatever the function would conceptually return. For example, the + last two functions could have the following interface: +

    +
    std::pair<char,bool> get_async_input();
    +std::pair<point,bool> polygon::get_any_point_effectively_inside();
    +
    +

    + These functions use a consistent interface for dealing with possibly nonexistent + results: +

    +
    std::pair<point,bool> p = poly.get_any_point_effectively_inside();
    +if ( p.second )
    +    flood_fill(p.first);
    +
    +

    + However, not only is this quite a burden syntactically, it is also error + prone since the user can easily use the function result (first element of + the pair) without ever checking if it has a valid value. +

    +

    + Clearly, we need a better idiom. +

    +
    + + + +
    +
    +
    +PrevUpHomeNext +
    + + diff --git a/doc/html/boost_optional/tutorial/optional_references.html b/doc/html/boost_optional/tutorial/optional_references.html new file mode 100644 index 0000000..77d73f5 --- /dev/null +++ b/doc/html/boost_optional/tutorial/optional_references.html @@ -0,0 +1,115 @@ + + + +Optional references + + + + + + + + + + + + + + + +
    Boost C++ LibrariesHomeLibrariesPeopleFAQMore
    +
    +
    +PrevUpHomeNext +
    +
    + +

    + 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 refer + to the same object. +
    • +
    • + Value-access will actually provide access to the referenced object rather + than the reference itself. +
    • +
    +
    + + + + + +
    [Warning]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 Dependencies + and Portability section. +

    +
    + + 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<const int&> oi = 1; // illegal
    +
    +
    + + + +
    +
    +
    +PrevUpHomeNext +
    + + diff --git a/doc/html/boost_optional/tutorial/rebinding_semantics_for_assignment_of_optional_references.html b/doc/html/boost_optional/tutorial/rebinding_semantics_for_assignment_of_optional_references.html new file mode 100644 index 0000000..b2bd32d --- /dev/null +++ b/doc/html/boost_optional/tutorial/rebinding_semantics_for_assignment_of_optional_references.html @@ -0,0 +1,149 @@ + + + +Rebinding semantics for assignment of optional references + + + + + + + + + + + + + + + +
    Boost C++ LibrariesHomeLibrariesPeopleFAQMore
    +
    +
    +PrevUpHomeNext +
    +
    + +

    + If you assign to an uninitialized optional<T&> + the effect is to bind (for the first time) to the object. Clearly, there + is no other choice. +

    +
    int x = 1 ;
    +int& rx = x ;
    +optional<int&> ora ;
    +optional<int&> orb(x) ;
    +ora = orb ; // now 'ora' is bound to 'x' through 'rx'
    +*ora = 2 ; // Changes value of 'x' through 'ora'
    +assert(x==2);
    +
    +

    + If you assign to a bare C++ reference, the assignment is forwarded to the + referenced object; its value changes but the reference is never rebound. +

    +
    int a = 1 ;
    +int& ra = a ;
    +int b = 2 ;
    +int& rb = b ;
    +ra = rb ; // Changes the value of 'a' to 'b'
    +assert(a==b);
    +b = 3 ;
    +assert(ra!=b); // 'ra' is not rebound to 'b'
    +
    +

    + Now, if you assign to an initialized optional<T&>, + the effect is to rebind to the new object + instead of assigning the referee. This is unlike bare C++ references. +

    +
    int a = 1 ;
    +int b = 2 ;
    +int& ra = a ;
    +int& rb = b ;
    +optional<int&> ora(ra) ;
    +optional<int&> orb(rb) ;
    +ora = orb ; // 'ora' is rebound to 'b'
    +*ora = 3 ; // Changes value of 'b' (not 'a')
    +assert(a==1);
    +assert(b==3);
    +
    +
    + + Rationale +
    +

    + Rebinding semantics for the assignment of initialized + optional references has been + chosen to provide consistency among initialization + states even at the expense of lack of consistency with the semantics + of bare C++ references. It is true that optional<U> + strives to behave as much as possible as U + does whenever it is initialized; but in the case when U + is T&, + doing so would result in inconsistent behavior w.r.t to the lvalue initialization + state. +

    +

    + Imagine optional<T&> + forwarding assignment to the referenced object (thus changing the referenced + object value but not rebinding), and consider the following code: +

    +
    optional<int&> a = get();
    +int x = 1 ;
    +int& rx = x ;
    +optional<int&> b(rx);
    +a = b ;
    +
    +

    + What does the assignment do? +

    +

    + If a is uninitialized, + the answer is clear: it binds to x + (we now have another reference to x). + But what if a is already + initialized? it would change the value of the referenced + object (whatever that is); which is inconsistent with the other possible + case. +

    +

    + If optional<T&> + would assign just like T& does, you would never be able to use + Optional's assignment without explicitly handling the previous initialization + state unless your code is capable of functioning whether after the assignment, + a aliases the same object + as b or not. +

    +

    + That is, you would have to discriminate in order to be consistent. +

    +

    + If in your code rebinding to another object is not an option, then it is + very likely that binding for the first time isn't either. In such case, assignment + to an uninitialized optional<T&> + shall be prohibited. It is quite possible that in such a scenario it is a + precondition that the lvalue must be already initialized. If it isn't, then + binding for the first time is OK while rebinding is not which is IMO very + unlikely. In such a scenario, you can assign the value itself directly, as + in: +

    +
    assert(!!opt);
    +*opt=value;
    +
    +
    + + + +
    +
    +
    +PrevUpHomeNext +
    + + diff --git a/doc/html/boost_optional/tutorial/type_requirements.html b/doc/html/boost_optional/tutorial/type_requirements.html new file mode 100644 index 0000000..84959d2 --- /dev/null +++ b/doc/html/boost_optional/tutorial/type_requirements.html @@ -0,0 +1,61 @@ + + + +Type requirements + + + + + + + + + + + + + + + +
    Boost C++ LibrariesHomeLibrariesPeopleFAQMore
    +
    +
    +PrevUpHomeNext +
    +
    + +

    + At the very minimum for optional<T> + 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<T> + 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<T> is + also Copyable and can be + easily initialized from an lvalue of type T. +

    +

    + T is + not required to be Default + Constructible. +

    +
    + + + +
    +
    +
    +PrevUpHomeNext +
    + + diff --git a/doc/html/boost_optional/type_requirements.html b/doc/html/boost_optional/type_requirements.html index 8ffd2ea..e1ee777 100644 --- a/doc/html/boost_optional/type_requirements.html +++ b/doc/html/boost_optional/type_requirements.html @@ -34,7 +34,7 @@ Additionally, if T is Moveable, optional<T> is also Moveable and can be easily initialized from an rvalue of type T - and be passed by value. Additionally if T + and be passed by value. Additionally, if T is Copyable, optional<T> is also Copyable and can be easily initialized from an lvalue of type T. diff --git a/doc/html/index.html b/doc/html/index.html index 4f602c2..3508307 100644 --- a/doc/html/index.html +++ b/doc/html/index.html @@ -5,7 +5,7 @@ - + @@ -17,7 +17,7 @@
    More

    -
    Next
    +
    Next

    @@ -37,94 +37,67 @@ -
    - - +

    + + Introduction +

    - 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. -

    -
    - + 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. +

    +

    + + 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. -

    -
    -
    - + 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. +

    +

    + + Solution +

    - This is how you solve it with boost::optional: -

    + This is how you solve it with boost::optional: +

    #include <boost/optional.hpp>
     
     boost::optional<int> getConfigParam(std::string name);  // return either an int or a `not-an-int`
    @@ -138,13 +111,11 @@
     }
     
    -
    -

    - +

    Last revised: June 03, 2014 at 14:35:30 GMT

    Last revised: June 04, 2014 at 16:06:37 GMT


    -
    Next
    +
    Next
    diff --git a/doc/html/optional/introduction.html b/doc/html/optional/introduction.html new file mode 100644 index 0000000..8f63804 --- /dev/null +++ b/doc/html/optional/introduction.html @@ -0,0 +1,82 @@ + + + +Introduction + + + + + + + + + + + + + + + +
    Boost C++ LibrariesHomeLibrariesPeopleFAQMore
    +
    +
    +PrevUpHomeNext +
    +
    + +

    + 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. +

    +

    + + 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. +

    +

    + + Solution +

    +

    + This is how you solve it with boost::optional: +

    +
    #include <boost/optional.hpp>
    +
    +boost::optional<int> getConfigParam(std::string name);  // return either an int or a `not-an-int`
    +
    +int main()
    +{
    +  if (boost::optional<int> oi = getConfigParam("MaxValue")) // did I get a real int?
    +    runWithMax(*oi);                                        // use my int
    +  else
    +    runWithNoMax();
    +}
    +
    +
    + + + +
    +
    +
    +PrevUpHomeNext +
    + + diff --git a/doc/html/optional/introduction/problem.html b/doc/html/optional/introduction/problem.html new file mode 100644 index 0000000..126a786 --- /dev/null +++ b/doc/html/optional/introduction/problem.html @@ -0,0 +1,54 @@ + + + +Problem + + + + + + + + + + + + + + + +
    Boost C++ LibrariesHomeLibrariesPeopleFAQMore
    +
    +
    +PrevUpHomeNext +
    +
    + +

    + 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. +

    +
    + + + +
    +
    +
    +PrevUpHomeNext +
    + + diff --git a/doc/html/optional/introduction/solution.html b/doc/html/optional/introduction/solution.html new file mode 100644 index 0000000..01b95ba --- /dev/null +++ b/doc/html/optional/introduction/solution.html @@ -0,0 +1,58 @@ + + + +Solution + + + + + + + + + + + + + + + +
    Boost C++ LibrariesHomeLibrariesPeopleFAQMore
    +
    +
    +PrevUpHomeNext +
    +
    + +

    + This is how you solve it with boost::optional: +

    +
    #include <boost/optional.hpp>
    +
    +boost::optional<int> getConfigParam(std::string name);  // return either an int or a `not-an-int`
    +
    +int main()
    +{
    +  if (boost::optional<int> oi = getConfigParam("MaxValue")) // did I get a real int?
    +    runWithMax(*oi);                                        // use my int
    +  else
    +    runWithNoMax();
    +}
    +
    +
    + + + +
    +
    +
    +PrevUpHomeNext +
    + + diff --git a/doc/html/optional/reference.html b/doc/html/optional/reference.html new file mode 100644 index 0000000..57d96f2 --- /dev/null +++ b/doc/html/optional/reference.html @@ -0,0 +1,48 @@ + + + +Reference + + + + + + + + + + + + + + + +
    Boost C++ LibrariesHomeLibrariesPeopleFAQMore
    +
    +
    +PrevUpHomeNext +
    + + + + +
    +
    +
    +PrevUpHomeNext +
    + + diff --git a/doc/html/optional/tutorial.html b/doc/html/optional/tutorial.html new file mode 100644 index 0000000..35fd387 --- /dev/null +++ b/doc/html/optional/tutorial.html @@ -0,0 +1,58 @@ + + + +Tutorial + + + + + + + + + + + + + + + +
    Boost C++ LibrariesHomeLibrariesPeopleFAQMore
    +
    +
    +PrevUpHomeNext +
    + + + + +
    +
    +
    +PrevUpHomeNext +
    + + diff --git a/include/boost/optional/optional.hpp b/include/boost/optional/optional.hpp index b3319b0..6e3b160 100644 --- a/include/boost/optional/optional.hpp +++ b/include/boost/optional/optional.hpp @@ -151,6 +151,7 @@ struct types_when_isnt_ref typedef T & reference_type ; #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES typedef T && rval_reference_type ; + typedef T && reference_type_of_temporary_wrapper; #ifdef BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES // GCC 4.4 has support for an early draft of rvalue references. The conforming version below // causes warnings about returning references to a temporary. @@ -173,6 +174,7 @@ struct types_when_is_ref typedef raw_type& reference_type ; #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES typedef BOOST_DEDUCED_TYPENAME remove_const::type&& rval_reference_type ; + typedef raw_type& reference_type_of_temporary_wrapper; static reference_type move(reference_type r) { return r; } #endif typedef raw_type* pointer_const_type ; @@ -227,6 +229,7 @@ class optional_base : public optional_tag typedef BOOST_DEDUCED_TYPENAME types::reference_const_type reference_const_type ; #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES typedef BOOST_DEDUCED_TYPENAME types::rval_reference_type rval_reference_type ; + typedef BOOST_DEDUCED_TYPENAME types::reference_type_of_temporary_wrapper reference_type_of_temporary_wrapper ; #endif typedef BOOST_DEDUCED_TYPENAME types::pointer_type pointer_type ; typedef BOOST_DEDUCED_TYPENAME types::pointer_const_type pointer_const_type ; @@ -725,6 +728,7 @@ class optional : public optional_detail::optional_base typedef BOOST_DEDUCED_TYPENAME base::reference_const_type reference_const_type ; #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES typedef BOOST_DEDUCED_TYPENAME base::rval_reference_type rval_reference_type ; + typedef BOOST_DEDUCED_TYPENAME base::reference_type_of_temporary_wrapper reference_type_of_temporary_wrapper ; #endif typedef BOOST_DEDUCED_TYPENAME base::pointer_type pointer_type ; typedef BOOST_DEDUCED_TYPENAME base::pointer_const_type pointer_const_type ; @@ -961,7 +965,7 @@ class optional : public optional_detail::optional_base #ifndef BOOST_NO_CXX11_REF_QUALIFIERS reference_const_type operator *() const& { return this->get() ; } reference_type operator *() & { return this->get() ; } - rval_reference_type operator *() && { return boost::move(this->get()) ; } + reference_type_of_temporary_wrapper operator *() && { return boost::move(this->get()) ; } #else reference_const_type operator *() const { return this->get() ; } reference_type operator *() { return this->get() ; } @@ -984,7 +988,7 @@ class optional : public optional_detail::optional_base throw_exception(bad_optional_access("Attempted to access the value of an uninitialized optional object.")); } - rval_reference_type value() && + reference_type_of_temporary_wrapper value() && { if (this->is_initialized()) return boost::move(this->get()) ;