diff --git a/doc/00_optional.qbk b/doc/00_optional.qbk index d1a2275..14f4d4a 100644 --- a/doc/00_optional.qbk +++ b/doc/00_optional.qbk @@ -2,7 +2,7 @@ [quickbook 1.4] [authors [Cacciola Carballal, Fernando Luis]] [copyright 2003-2007 Fernando Luis Cacciola Carballal] - [copyright 2014-2015 Andrzej Krzemieński] + [copyright 2014-2016 Andrzej Krzemieński] [category miscellaneous] [id optional] [dirname optional] diff --git a/doc/11_development.qbk b/doc/11_development.qbk index 9e3ef44..de5d00d 100644 --- a/doc/11_development.qbk +++ b/doc/11_development.qbk @@ -228,7 +228,7 @@ 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 +[caution However, it is particularly important to note that `optional<>` objects are not pointers. [_`optional<>` is not, and does not model, a pointer]. ] diff --git a/doc/15_optional_references.qbk b/doc/15_optional_references.qbk index 2f8b3c6..acb1226 100644 --- a/doc/15_optional_references.qbk +++ b/doc/15_optional_references.qbk @@ -1,6 +1,8 @@  [section Optional references] +[section Overview] + This library allows the template parameter `T` to be of reference type: `T&`, and to some extent, `T const&`. @@ -21,7 +23,7 @@ will nonetheless refer to the same object. * Value-access will actually provide access to the referenced object rather than the reference itself. -[warning On compilers that do not conform to Standard C++ rules of reference binding, operations on optional references might give adverse results: rather than binding a reference to a designated object they may create an unexpected temporary and bind to it. For more details see [link boost_optional.dependencies_and_portability.optional_reference_binding Dependencies and Portability section].] +[caution On compilers that do not conform to Standard C++ rules of reference binding, some operations on optional references are disabled in order to prevent subtle bugs. For more details see [link boost_optional.dependencies_and_portability.optional_reference_binding Dependencies and Portability section].] [heading Rvalue references] @@ -118,3 +120,4 @@ In such a scenario, you can assign the value itself directly, as in: *opt=value; [endsect] +[endsect] diff --git a/doc/27_ref_optional_synopsis.qbk b/doc/27_ref_optional_synopsis.qbk index 042dd3d..6a4f853 100644 --- a/doc/27_ref_optional_synopsis.qbk +++ b/doc/27_ref_optional_synopsis.qbk @@ -9,21 +9,79 @@ ] -[#ref_header_optional_optional_hpp][section:header_optional_optional Synopsis] +[#ref_header_optional_optional_hpp] [section:header_optional_optional Synopsis] ```// In Header: <`[@boost:/boost/optional/optional.hpp boost/optional/optional.hpp]'''>'''`` namespace boost { + template + class optional ; ``[link reference_operator_template __GO_TO__]`` + + template + class optional ; ``[link reference_operator_template_spec __GO_TO__]`` + + template inline bool operator == ( optional const& x, optional const& y ) ; ``[link reference_operator_compare_equal_optional_optional __GO_TO__]`` + + template inline bool operator != ( optional const& x, optional const& y ) ; ``[link reference_operator_compare_not_equal_optional_optional __GO_TO__]`` + + template inline bool operator < ( optional const& x, optional const& y ) ; ``[link reference_operator_compare_less_optional_optional __GO_TO__]`` + + template inline bool operator > ( optional const& x, optional const& y ) ; ``[link reference_operator_compare_greater_optional_optional __GO_TO__]`` + + template inline bool operator <= ( optional const& x, optional const& y ) ; ``[link reference_operator_compare_less_or_equal_optional_optional __GO_TO__]`` + + template inline bool operator >= ( optional const& x, optional const& y ) ; ``[link reference_operator_compare_greater_or_equal_optional_optional __GO_TO__]`` + + template inline bool operator == ( optional const& x, none_t ) noexcept ; ``[link reference_operator_compare_equal_optional_none __GO_TO__]`` + + template inline bool operator != ( optional const& x, none_t ) noexcept ; ``[link reference_operator_compare_not_equal_optional_none __GO_TO__]`` + + template inline optional make_optional ( T const& v ) ; ``[link reference_make_optional_value __GO_TO__]`` + + template inline optional make_optional ( bool condition, T const& v ) ; ``[link reference_make_optional_bool_value __GO_TO__]`` + + template inline auto get_optional_value_or ( optional const& opt, typename optional::reference_const_type def ) -> typename optional::reference_const_type; ``[link reference_free_get_value_or __GO_TO__]`` + + template inline auto get_optional_value_or ( optional const& opt, typename optional::reference_type def ) -> typename optional::reference_type ; ``[link reference_free_get_value_or __GO_TO__]`` + + template inline T const& get ( optional const& opt ) ; ``[link reference_optional_get __GO_TO__]`` + + template inline T& get ( optional & opt ) ; ``[link reference_optional_get __GO_TO__]`` + + template inline T const* get ( optional const* opt ) ; ``[link reference_optional_get __GO_TO__]`` + + template inline T* get ( optional* opt ) ; ``[link reference_optional_get __GO_TO__]`` + + template inline auto get_pointer ( optional const& opt ) -> ``['see below]``; ``[link reference_free_get_pointer __GO_TO__]`` + + template inline auto get_pointer ( optional & opt ) -> ``['see below]``; ``[link reference_free_get_pointer __GO_TO__]`` + + template inline void swap( optional& x, optional& y ) ; ``[link reference_swap_optional_optional __GO_TO__]`` + + template inline void swap( optional& x, optional& y ) ; ``[link reference_swap_optional_reference __GO_TO__]`` + + } // namespace boost + + +[endsect] + + +[section:header_optional_optional_values Optional Values] + +[#reference_operator_template] + template class optional { public : - typedef T value_type; + typedef T value_type ; + typedef T & reference_type ; + typedef T const& reference_const_type ; + typedef T * pointer_type ; + typedef T const* pointer_const_type ; - // (If T is of reference type, the parameters and results by reference are by value) - optional () noexcept ; ``[link reference_optional_constructor __GO_TO__]`` optional ( none_t ) noexcept ; ``[link reference_optional_constructor_none_t __GO_TO__]`` @@ -109,43 +167,79 @@ T const& get_value_or( T const& default ) const ; ``[link reference_optional_get_value_or_value __GO_TO__]`` }; - template inline bool operator == ( optional const& x, optional const& y ) ; ``[link reference_operator_compare_equal_optional_optional __GO_TO__]`` - - template inline bool operator != ( optional const& x, optional const& y ) ; ``[link reference_operator_compare_not_equal_optional_optional __GO_TO__]`` - - template inline bool operator < ( optional const& x, optional const& y ) ; ``[link reference_operator_compare_less_optional_optional __GO_TO__]`` - - template inline bool operator > ( optional const& x, optional const& y ) ; ``[link reference_operator_compare_greater_optional_optional __GO_TO__]`` - - template inline bool operator <= ( optional const& x, optional const& y ) ; ``[link reference_operator_compare_less_or_equal_optional_optional __GO_TO__]`` - - template inline bool operator >= ( optional const& x, optional const& y ) ; ``[link reference_operator_compare_greater_or_equal_optional_optional __GO_TO__]`` - - template inline bool operator == ( optional const& x, none_t ) noexcept ; ``[link reference_operator_compare_equal_optional_none __GO_TO__]`` - - template inline bool operator != ( optional const& x, none_t ) noexcept ; ``[link reference_operator_compare_not_equal_optional_none __GO_TO__]`` - - template inline optional make_optional ( T const& v ) ; ``[link reference_make_optional_value __GO_TO__]`` - - template inline optional make_optional ( bool condition, T const& v ) ; ``[link reference_make_optional_bool_value __GO_TO__]`` - - template inline T const& get_optional_value_or ( optional const& opt, T const& default ) ; ``[link reference_optional_get_value_or_value __GO_TO__]`` - - template inline T const& get ( optional const& opt ) ; ``[link reference_optional_get __GO_TO__]`` - - template inline T& get ( optional & opt ) ; ``[link reference_optional_get __GO_TO__]`` - - template inline T const* get ( optional const* opt ) ; ``[link reference_optional_get __GO_TO__]`` - - template inline T* get ( optional* opt ) ; ``[link reference_optional_get __GO_TO__]`` - - template inline T const* get_pointer ( optional const& opt ) ; ``[link reference_optional_get_ptr __GO_TO__]`` - - template inline T* get_pointer ( optional & opt ) ; ``[link reference_optional_get_ptr __GO_TO__]`` - - template inline void swap( optional& x, optional& y ) ; ``[link reference_swap_optional_optional __GO_TO__]`` - - } // namespace boost - [endsect] + + +[section:header_optional_optional_refs Optional References] + +[#reference_operator_template_spec] + template + class optional // specilization for lvalue references + { + public : + + typedef T& value_type; + typedef T& reference_type; + typedef T& reference_const_type; // no const propagation + typedef T* pointer_type; + typedef T* pointer_const_type; // no const propagation + + optional () noexcept ; ``[link reference_optional_ref_default_ctor __GO_TO__]`` + + optional ( none_t ) noexcept ; ``[link reference_optional_ref_default_ctor __GO_TO__]`` + + template optional(R&& r) noexcept ; ``[link reference_optional_ref_value_ctor __GO_TO__]`` + + template optional(bool cond, R&& r) noexcept ; ``[link reference_optional_ref_cond_value_ctor __GO_TO__]`` + + optional ( optional const& rhs ) noexcept ; ``[link reference_optional_ref_copy_ctor __GO_TO__]`` + + template explicit optional ( optional const& rhs ) noexcept ; ``[link reference_optional_ref_ctor_from_opt_U __GO_TO__]`` + + optional& operator = ( none_t ) noexcept ; ``[link reference_optional_ref_assign_none_t __GO_TO__]`` + + + optional& operator = ( optional const& rhs ) noexcept; ``[link reference_optional_ref_copy_assign __GO_TO__]`` + + template optional& operator = ( optional const& rhs ) noexcept ; ``[link reference_optional_ref_assign_optional_U __GO_TO__]`` + + template optional& operator = (R&& r) noexcept ; ``[link reference_optional_ref_assign_R __GO_TO__]`` + + template void emplace ( R&& r ) noexcept ; ``[link reference_optional_ref_emplace_R __GO_TO__]`` + + T& get() const ; ``[link reference_optional_ref_get __GO_TO__]`` + T& operator *() const ; ``[link reference_optional_ref_get __GO_TO__]`` + + T* operator ->() const ; ``[link reference_optional_ref_arrow __GO_TO__]`` + + T& value() const& ; ``[link reference_optional_ref_value __GO_TO__]`` + + template T& value_or( R && r ) const noexcept ; ``[link reference_optional_ref_value_or __GO_TO__]`` + + template T& value_or_eval( F f ) const ; ``[link reference_optional_ref_value_or_eval __GO_TO__]`` + + T* get_ptr() const noexcept ; ``[link reference_optional_ref_get_ptr __GO_TO__]`` + + explicit operator bool() const noexcept ; ``[link reference_optional_ref_operator_bool __GO_TO__]`` + + bool operator!() const noexcept ; ``[link reference_optional_ref_operator_not __GO_TO__]`` + + // deprecated methods + + // (deprecated) + void reset() noexcept ; ``[link reference_optional_ref_reset __GO_TO__]`` + + // (deprecated) + template void reset ( R && r ) noexcept ; ``[link reference_optional_ref_reset_value __GO_TO__]`` + + // (deprecated) + bool is_initialized() const noexcept ; ``[link reference_optional_ref_is_initialized __GO_TO__]`` + + // (deprecated) + template T& get_value_or( R && r ) constnoexcept; ``[link reference_optional_ref_get_value_or_value __GO_TO__]`` + + private: + T* ref; // exposition only + }; +[endsect] diff --git a/doc/28_ref_optional_semantics.qbk b/doc/28_ref_optional_semantics.qbk index 791eb99..31dc178 100644 --- a/doc/28_ref_optional_semantics.qbk +++ b/doc/28_ref_optional_semantics.qbk @@ -9,18 +9,7 @@ ] -[section Detailed Semantics] - -Because `T` might be of reference type, in the sequel, those entries whose -semantic depends on `T` being of reference type or not will be distinguished -using the following convention: - -* If the entry reads: `optional`, the description -corresponds only to the case where `T` is not of reference type. -* If the entry reads: `optional`, the description corresponds only to -the case where `T` is of reference type. -* If the entry reads: `optional`, the description is the same for both -cases. +[section Detailed Semantics - Optional Values] [note The following section contains various `assert()` which are used only to show @@ -29,9 +18,6 @@ support each particular expression but that if the expression is supported, the implied condition holds. ] -__SPACE__ - -[heading optional class member functions] __SPACE__ @@ -70,7 +56,7 @@ __SPACE__ [#reference_optional_constructor_value] -[: `optional::optional( T const& v )`] +[: `optional::optional( T const& v )`] * [*Requires:] `is_copy_constructible::value` is `true`. * [*Effect:] Directly-Constructs an `optional`. @@ -87,29 +73,12 @@ optional opt(v); assert ( *opt == v ) ; `` -__SPACE__ - -[: `optional::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 opt(vref); -assert ( *opt == v ) ; -++ v ; // mutate referee -assert (*opt == v); -`` __SPACE__ [#reference_optional_constructor_move_value] -[: `optional::optional( T&& v )`] +[: `optional::optional( T&& v )`] * [*Requires:] `is_move_constructible::value` is `true`. * [*Effect:] Directly-Move-Constructs an `optional`. @@ -125,35 +94,27 @@ optional opt(std::move(v1)); assert ( *opt == v2 ) ; `` -__SPACE__ - -[: `optional::optional( T&& ref ) = delete`] - -* [*Notes:] This constructor is deleted - __SPACE__ [#reference_optional_constructor_bool_value] -[: `optional::optional( bool condition, T const& v ) ;` ] -[: `optional ::optional( bool condition, T& v ) ;` ] +[: `optional::optional( bool condition, T const& v ) ;` ] * If condition is true, same as: -[: `optional::optional( T const& v )`] -[: `optional ::optional( T& v )`] +[: `optional::optional( T const& v )`] * otherwise, same as: -[: `optional::optional()`] -[: `optional ::optional()`] +[: `optional::optional()`] + __SPACE__ [#reference_optional_constructor_optional] -[: `optional::optional( optional const& rhs );`] +[: `optional::optional( optional const& rhs );`] * [*Requires:] `is_copy_constructible::value` is `true`. * [*Effect:] Copy-Constructs an `optional`. @@ -178,43 +139,12 @@ optional init2 ( init ) ; assert ( init2 == init ) ; `` -__SPACE__ - -[: `optional::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 refer to the -same object (they alias). -* [*Example:] -`` -optional uninit ; -assert (!uninit); - -optional uinit2 ( uninit ) ; -assert ( uninit2 == uninit ); - -T v = 2 ; T& ref = v ; -optional init(ref); -assert ( *init == v ) ; - -optional init2 ( init ) ; -assert ( *init2 == v ) ; - -v = 3 ; - -assert ( *init == 3 ) ; -assert ( *init2 == 3 ) ; -`` __SPACE__ [#reference_optional_move_constructor_optional] -[: `optional::optional( optional&& rhs ) noexcept(`['see below]`);`] +[: `optional::optional( optional&& rhs ) noexcept(`['see below]`);`] * [*Requires:] `is_move_constructible::value` is `true`. * [*Effect:] Move-constructs an `optional`. @@ -243,43 +173,12 @@ assert ( init2 ); assert ( **init2 == T(2) ) ; `` -__SPACE__ - -[: `optional::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 refer to the -same object (they alias). -* [*Example:] -`` -optional&> uninit ; -assert (!uninit); - -optional&> uinit2 ( std::move(uninit) ) ; -assert ( uninit2 == uninit ); - -std::unique_ptr v(new T(2)) ; -optional&> init(v); -assert ( *init == v ) ; - -optional&> init2 ( std::move(init) ) ; -assert ( *init2 == v ) ; - -*v = 3 ; - -assert ( **init == 3 ) ; -assert ( **init2 == 3 ) ; -`` __SPACE__ [#reference_optional_constructor_other_optional] -[: `template explicit optional::optional( optional const& rhs );`] +[: `template explicit optional::optional( optional const& rhs );`] * [*Effect:] Copy-Constructs an `optional`. * [*Postconditions:] If `rhs` is initialized, `*this` is initialized and its @@ -303,7 +202,7 @@ __SPACE__ [#reference_optional_move_constructor_other_optional] -[: `template explicit optional::optional( optional&& rhs );`] +[: `template explicit optional::optional( optional&& rhs );`] * [*Effect:] Move-constructs an `optional`. * [*Postconditions:] If `rhs` is initialized, `*this` is initialized and its @@ -327,8 +226,8 @@ __SPACE__ [#reference_optional_constructor_factory] -[: `template explicit optional::optional( InPlaceFactory const& f );`] -[: `template explicit optional::optional( TypedInPlaceFactory const& f );`] +[: `template explicit optional::optional( InPlaceFactory const& f );`] +[: `template explicit optional::optional( TypedInPlaceFactory const& f );`] * [*Effect:] Constructs an `optional` with a value of `T` obtained from the factory. @@ -365,7 +264,7 @@ __SPACE__ [#reference_optional_operator_equal_value] -[: `optional& optional::operator= ( T const& rhs ) ;`] +[: `optional& optional::operator= ( T const& rhs ) ;`] * [*Effect:] Assigns the value `rhs` to an `optional`. * [*Postconditions: ] `*this` is initialized and its value is a ['copy] of `rhs`. @@ -390,40 +289,12 @@ opt = y ; assert ( *opt == y ) ; `` -__SPACE__ - -[: `optional& optional::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 [link boost_optional.tutorial.rebinding_semantics_for_assignment_of_optional_references here] for details on this behavior. -* [*Example:] -`` -int a = 1 ; -int b = 2 ; -T& ra = a ; -T& rb = b ; -optional def ; -optional opt(ra) ; - -def = rb ; // binds 'def' to 'b' through 'rb' -assert ( *def == b ) ; -*def = a ; // changes the value of 'b' to a copy of the value of 'a' -assert ( b == a ) ; -int c = 3; -int& rc = c ; -opt = rc ; // REBINDS to 'c' through 'rc' -c = 4 ; -assert ( *opt == 4 ) ; -`` __SPACE__ [#reference_optional_operator_move_equal_value] -[: `optional& optional::operator= ( T&& rhs ) ;`] +[: `optional& optional::operator= ( T&& rhs ) ;`] * [*Effect:] Moves the value `rhs` to an `optional`. * [*Postconditions: ] `*this` is initialized and its value is moved from `rhs`. @@ -448,18 +319,12 @@ opt = std::move(y2) ; assert ( *opt == yR ) ; `` -__SPACE__ - -[: `optional& optional::operator= ( T&& rhs ) = delete;`] - -* [*Notes:] This assignment operator is deleted. - __SPACE__ [#reference_optional_operator_equal_optional] -[: `optional& optional::operator= ( optional const& rhs ) ;`] +[: `optional& optional::operator= ( optional const& rhs ) ;`] * [*Requires:] `T` is __COPY_CONSTRUCTIBLE__ and `CopyAssignable`. * [*Effects:] @@ -485,43 +350,12 @@ assert ( !def ) ; // previous value (copy of 'v') destroyed from within 'opt'. `` -__SPACE__ - -[: `optional & optional::operator= ( optional 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 [link boost_optional.tutorial.rebinding_semantics_for_assignment_of_optional_references here] for details on this behavior. -* [*Example:] -`` -int a = 1 ; -int b = 2 ; -T& ra = a ; -T& rb = b ; -optional def ; -optional ora(ra) ; -optional 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 orc(rc) ; -ora = orc ; // REBINDS ora to 'c' through 'rc' -c = 4 ; -assert ( *ora == 4 ) ; -`` __SPACE__ [#reference_optional_operator_move_equal_optional] -[: `optional& optional::operator= ( optional&& rhs ) noexcept(`['see below]`);`] +[: `optional& optional::operator= ( optional&& rhs ) noexcept(`['see below]`);`] * [*Requires:] `T` is __MOVE_CONSTRUCTIBLE__ and `MoveAssignable`. * [*Effects:] @@ -548,18 +382,13 @@ assert ( opt ) ; assert ( *opt == T(2) ) ; `` -__SPACE__ - -[: `optional & optional::operator= ( optional&& rhs ) ;`] - -* [*Effect:] Same as `optional::operator= ( optional const& rhs )`. __SPACE__ [#reference_optional_operator_equal_other_optional] -[: `template optional& optional::operator= ( optional const& rhs ) ;`] +[: `template optional& optional::operator= ( optional const& rhs ) ;`] * [*Effect:] [table @@ -587,7 +416,7 @@ __SPACE__ [#reference_optional_operator_move_equal_other_optional] -[: `template optional& optional::operator= ( optional&& rhs ) ;`] +[: `template optional& optional::operator= ( optional&& rhs ) ;`] * [*Effect:] [table @@ -617,7 +446,7 @@ __SPACE__ [#reference_optional_emplace] -[: `template void optional::emplace( Args...&& args );`] +[: `template void optional::emplace( Args...&& args );`] * [*Requires:] The compiler supports rvalue references and variadic templates. * [*Effect:] If `*this` is initialized calls `*this = none`. @@ -642,8 +471,8 @@ __SPACE__ [#reference_optional_operator_equal_factory] -[: `template optional& optional::operator=( InPlaceFactory const& f );`] -[: `template optional& optional::operator=( TypedInPlaceFactory const& f );`] +[: `template optional& optional::operator=( InPlaceFactory const& f );`] +[: `template optional& optional::operator=( TypedInPlaceFactory const& f );`] * [*Effect:] Assigns an `optional` with a value of `T` obtained from the factory. @@ -659,7 +488,7 @@ __SPACE__ [#reference_optional_reset_value] -[: `void optional::reset( T const& v ) ;`] +[: `void optional::reset( T const& v ) ;`] * [*Deprecated:] same as `operator= ( T const& v) ;` __SPACE__ @@ -673,36 +502,24 @@ __SPACE__ [#reference_optional_get] -[: `T const& optional::get() const ;`] -[: `T& optional::get() ;`] +[: `T const& optional::get() const ;`] +[: `T& optional::get() ;`] -[: `inline T const& get ( optional const& ) ;`] -[: `inline T& get ( optional &) ;`] +[: `inline T const& get ( optional const& ) ;`] +[: `inline T& get ( optional &) ;`] * [*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::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 const& optional::operator*() const& ;`] +[: `T& optional::operator*() &;`] * [*Requires:] `*this` is initialized * [*Returns:] A reference to the contained value @@ -723,32 +540,12 @@ __SPACE__ [#reference_optional_operator_asterisk_move] -[: `T&& optional::operator*() &&;`] +[: `T&& optional::operator*() &&;`] * [*Requires:] `*this` contains a value. * [*Effects:] Equivalent to `return std::move(*val);`. * [*Notes:] The requirement is asserted via `BOOST_ASSERT()`. On compilers that do not support ref-qualifiers on member functions this overload is not present. -__SPACE__ - -[: `T & 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__ @@ -845,11 +642,8 @@ __SPACE__ [#reference_optional_get_value_or_value] -[: `T const& optional::get_value_or( T const& default) const ;`] -[: `T& optional::get_value_or( T& default ) ;`] - -[: `inline T const& get_optional_value_or ( optional const& o, T const& default ) ;`] -[: `inline T& get_optional_value_or ( optional& o, T& default ) ;`] +[: `T const& optional::get_value_or( T const& default) const ;`] +[: `T& optional::get_value_or( T& default ) ;`] * [*Deprecated:] Use `value_or()` instead. * [*Returns:] A reference to the contained value, if any, or `default`. @@ -862,7 +656,7 @@ T const& y = def.get_value_or(z); assert ( y == z ) ; optional opt ( v ); -T const& u = get_optional_value_or(opt,z); +T const& u = opt.get_value_or(z); assert ( u == v ) ; assert ( u != z ) ; `` @@ -872,11 +666,8 @@ __SPACE__ [#reference_optional_get_ptr] -[: `T const* optional::get_ptr() const ;`] -[: `T* optional::get_ptr() ;`] - -[: `inline T const* get_pointer ( optional const& ) ;`] -[: `inline T* get_pointer ( optional &) ;`] +[: `T const* optional::get_ptr() const ;`] +[: `T* optional::get_ptr() ;`] * [*Returns:] If `*this` is initialized, a pointer to the contained value; else `0` (['null]). @@ -898,8 +689,8 @@ __SPACE__ [#reference_optional_operator_arrow] -[: `T const* optional::operator ->() const ;`] -[: `T* optional::operator ->() ;`] +[: `T const* optional::operator ->() const ;`] +[: `T* optional::operator ->() ;`] * [*Requires: ] `*this` is initialized. * [*Returns:] A pointer to the contained value. @@ -957,15 +748,300 @@ __SPACE__ * [*Deprecated:] Same as `explicit operator bool () ;` + +[endsect] + +[section Detailed Semantics - Optional References] + __SPACE__ -[heading Free functions] +[#reference_optional_ref_default_ctor] + +[: `optional::optional() noexcept;`] +[: `optional::optional(none_t) noexcept;`] + +* [*Postconditions:] `bool(*this) == false`; `*this` refers to nothing. + + +__SPACE__ + +[#reference_optional_ref_value_ctor] + +[: `template optional::optional(R&& r) noexcept;`] +* [*Postconditions:] `bool(*this) == true`; `addressof(**this) == addressof(r)`. +* [*Remarks:] Unless `R` is an lvalue reference, the program is ill-formed. This constructor does not participate in overload resolution if `decay` is an instance of `boost::optional`. +* [*Example:] +`` +T v; +T& vref = v ; +optional opt(vref); +assert ( *opt == v ) ; +++ v ; // mutate referee +assert (*opt == v); +`` + +__SPACE__ + +[#reference_optional_ref_cond_value_ctor] + +[: `template optional::optional(bool cond, R&& r) noexcept;`] +* [*Effects: ] Initializes `ref` with expression `cond ? addressof(r) : nullptr`. +* [*Postconditions:] `bool(*this) == cond`; If `bool(*this)`, `addressof(**this) == addressof(r)`. +* [*Remarks:] Unless `R` is an lvalue reference, the program is ill-formed. This constructor does not participate in overload resolution if `decay` is an instance of `boost::optional`. + +__SPACE__ + +[#reference_optional_ref_copy_ctor] + +[: `optional::optional ( optional const& rhs ) noexcept ;`] + +* [*Effects: ] Initializes `ref` with expression `rhs.ref`. + +* [*Postconditions:] `bool(*this) == bool(rhs)`. + +* [*Example:] +`` +optional uninit ; +assert (!uninit); + +optional uinit2 ( uninit ) ; +assert ( uninit2 == uninit ); + +T v = 2 ; T& ref = v ; +optional init(ref); +assert ( *init == v ) ; + +optional init2 ( init ) ; +assert ( *init2 == v ) ; + +v = 3 ; + +assert ( *init == 3 ) ; +assert ( *init2 == 3 ) ; +`` + +__SPACE__ + +[#reference_optional_ref_ctor_from_opt_U] + +[: `template explicit optional::optional ( optional const& rhs ) noexcept ;`] + +* [*Requires:] `is_convertible::value` is `true`. + +* [*Effects: ] Initializes `ref` with expression `rhs.ref`. + +* [*Postconditions:] `bool(*this) == bool(rhs)`. + + +__SPACE__ + +[#reference_optional_ref_assign_none_t] + +[: `optional::operator= ( none_t ) noexcept ;`] + +* [*Effects: ] Assigns `ref` with expression `nullptr`. + +* [*returns:] `*this`. + +* [*Postconditions:] `bool(*this) == false`. + + + +[#reference_optional_ref_copy_assign] + +[: `optional& optional::operator= ( optional const& rhs ) noexcept ;`] + +* [*Effects: ] Assigns `ref` with expression `rhs.ref`. + +* [*returns:] `*this`. + +* [*Postconditions:] `bool(*this) == bool(rhs)`. + +* [*Notes:] This behaviour is called ['rebinding semantics]. See [link boost_optional.tutorial.optional_references.rebinding_semantics_for_assignment_of_optional_references here] for details. + +* [*Example:] +`` +int a = 1 ; +int b = 2 ; +T& ra = a ; +T& rb = b ; +optional def ; +optional ora(ra) ; +optional 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 orc(rc) ; +ora = orc ; // REBINDS ora to 'c' through 'rc' +c = 4 ; +assert ( *ora == 4 ) ; +`` + + +[#reference_optional_ref_assign_optional_U] + +[: `template optional& optional::operator= ( optional const& rhs ) noexcept ;`] + +* [*Requires:] `is_convertible::value` is `true`. + +* [*Effects: ] Assigns `ref` with expression `rhs.ref`. + +* [*returns:] `*this`. + +* [*Postconditions:] `bool(*this) == bool(rhs)`. + + +__SPACE__ + +[#reference_optional_ref_assign_R] + +[: `template optional& optional::operator= ( R&& r ) noexcept ;`] + +* [*Effects: ] Assigns `ref` with expression `r`. + +* [*returns:] `*this`. + +* [*Postconditions:] `bool(*this) == true`. + +* [*Remarks:] Unless `R` is an lvalue reference, the program is ill-formed. This function does not participate in overload resolution if `decay` is an instance of `boost::optional`. + +* [*Example:] +`` +int a = 1 ; +int b = 2 ; +T& ra = a ; +T& rb = b ; +optional def ; +optional opt(ra) ; + +def = rb ; // binds 'def' to 'b' through 'rb' +assert ( *def == b ) ; +*def = a ; // changes the value of 'b' to a copy of the value of 'a' +assert ( b == a ) ; +int c = 3; +int& rc = c ; +opt = rc ; // REBINDS to 'c' through 'rc' +c = 4 ; +assert ( *opt == 4 ) ; +`` + +__SPACE__ + +[#reference_optional_ref_emplace_R] + +[: `void optional::emplace( R&& r ) noexcept ;`] +* [*Effects: ] Assigns `ref` with expression `r`. +* [*Postconditions:] `bool(*this) == true`. +* [*Remarks:] Unless `R` is an lvalue reference, the program is ill-formed. This function does not participate in overload resolution if `decay` is an instance of `boost::optional`. + +__SPACE__ + +[#reference_optional_ref_get] +[: `T& optional::get() const ;`] +[: `T& optional::operator *() const ;`] +* [*Requires:] `bool(*this) == true`. +* [*Effects: ] Returns `*ref`. +* [*Throws: ] Nothing. +* [*Example:] +`` +T v ; +T& vref = v ; +optional opt ( vref ); +T const& vref2 = *opt; +assert ( vref2 == v ) ; +++ v ; +assert ( *opt == v ) ; +`` + +__SPACE__ + +[#reference_optional_ref_arrow] +[: `T* optional::operator -> () const ;`] +* [*Requires:] `bool(*this) == true`. +* [*Effects: ] Returns `ref`. +* [*Throws: ] Nothing. + +__SPACE__ + +[#reference_optional_ref_value] +[: `T& optional::value() const ;`] +* [*Effects:] Equivalent to `return bool(*this) ? *val : throw bad_optional_access();`. + +__SPACE__ + +[#reference_optional_ref_value_or] +[: `template T& optional::value_or( R&& r ) const noexcept;`] +* [*Effects:] Equivalent to `if (*this) return **this; else return r;`. +* [*Remarks:] Unless `R` is an lvalue reference, the program is ill-formed. + +__SPACE__ + +[#reference_optional_ref_value_or_eval] +[: `template T& optional::value_or( F f ) const ;`] +* [*Effects:] Equivalent to `if (*this) return **this; else return f();`. +* [*Remarks:] Unless `decltype(f())` is an lvalue reference, the program is ill-formed. + +__SPACE__ + +[#reference_optional_ref_get_ptr] +[: `T* optional::get_ptr () const noexcept;`] +* [*Returns:] `ref`. + +__SPACE__ + +[#reference_optional_ref_operator_bool] +[: `optional::operator bool () const noexcept;`] +* [*Returns:] `bool(ref)`. + +__SPACE__ + +[#reference_optional_ref_operator_not] +[: `optional::operator ! () const noexcept;`] +* [*Returns:] `!bool(ref)`. + +__SPACE__ + +[#reference_optional_ref_reset] +[: `void optional::reset() noexcept;`] +* [*Effects:] Use `*this = none` instead. +* [*Remarks:] This function is depprecated. + +__SPACE__ + +[#reference_optional_ref_reset_value] +[: `template void optional::reset ( R&& r) noexcept;`] +* [*Effects:] Equivalent to `*this = std::forward(r)`. +* [*Remarks:] This function is depprecated. + +__SPACE__ + +[#reference_optional_ref_is_initialized] +[: `bool optional::is_initialized() const noexcept;`] +* [*Effects:] Equivalent to `return bool(*this)`. +* [*Remarks:] This function is depprecated. + +__SPACE__ + +[#reference_optional_ref_get_value_or_value] +[: `template T& optional::get_value_or( R&& r ) const noexcept;`] +* [*Effects:] Equivalent to `return value_or(std::forward(r);`. +* [*Remarks:] This function is depprecated. + +[endsect] + + +[section Detailed Semantics - Free Functions] + __SPACE__ [#reference_make_optional_value] -[: `optional make_optional( T const& v )`] +[: `optional make_optional( T const& v )`] * [*Returns: ] `optional(v)` for the ['deduced] type `T` of `v`. * [*Example:] @@ -979,9 +1055,9 @@ __SPACE__ [#reference_make_optional_bool_value] -[: `optional make_optional( bool condition, T const& v )`] +[: `optional make_optional( bool condition, T const& v )`] -* [*Returns: ] `optional(condition,v)` for the ['deduced] type `T` of `v`. +* [*Returns: ] `optional(condition, v)` for the ['deduced] type `T` of `v`. * [*Example:] `` optional calculate_foo() @@ -1108,6 +1184,25 @@ __SPACE__ * [*Returns: ] `!( x == y );` +__SPACE__ + + +[#reference_free_get_pointer] +[: `auto get_pointer ( optional& o ) -> typename optional::pointer_type ;`] +[: `auto get_pointer ( optional const& o ) -> typename optional::pointer_const_type ;`] +* [*Returns:] `o.get_ptr()`. +* [*Throws:] Nothing. + +__SPACE__ + + +[#reference_free_get_value_or] +[: `auto get_optional_value_or ( optional& o, typename optional::reference_type def ) -> typename optional::reference_type ;`] +[: `auto get_optional_value_or ( optional const& o, typename optional::reference_const_type def ) -> typename optional::reference_const_type ;`] +* [*Returns:] `o.get_value_or(def)`. +* [*Throws:] Nothing. +* [*Remarks:] This function is deprecated. + __SPACE__ [#reference_swap_optional_optional] @@ -1147,4 +1242,30 @@ assert ( *optX == y ); assert ( *optY == x ); `` -[endsect] +__SPACE__ + +[#reference_swap_optional_reference] +[: `void swap ( optional& x, optional& y ) noexcept ;`] + +* [*Postconditions:] `x` refers to what `y` refererred to before the swap (if anything). `y` refers to whatever `x` referred to before the swap. + +* [*Example:] +`` +T x(12); +T y(21); + +optional opt0; +optional optX (x); +optional optY (y); + +boost::swap(optX, optY); +assert (addressof(*optX) == addressof(y)); +assert (addressof(*optY) == addressof(x)); + +boost::swap(opt0, optX); +assert ( opt0 ); +assert ( !optX ); +assert (addressof(*opt0) == addressof(y)); +`` + +[endsect] \ No newline at end of file diff --git a/doc/90_dependencies.qbk b/doc/90_dependencies.qbk index cf678dc..80e1803 100644 --- a/doc/90_dependencies.qbk +++ b/doc/90_dependencies.qbk @@ -30,17 +30,17 @@ The implementation uses the following other Boost modules: [section Optional Reference Binding] -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&`: +A number of compilers incorrectly treat const lvalues of integral type as rvalues, and create an illegal temporary when binding to an lvalue reference to const in some expressions. This could result in creating an optional lvalue reference that is in fact bound to an unexpected temporary rather than to the intended object. In order to prevent hard to find run-time bugs, this library performs compile-time checks to prevent expressions that would otherwise bind an optional reference to an unexpected temporary. As a consequence, on certain compilers certain pieces of functionality in optional references are missing. In order to maintain a portability of your code across diferent compilers, it is recommended that you only stick to the minimum portable interface of optional references: prefer direct-initialization and copy assignment of optional references to copy-initialization and assignment from `T&`: const int i = 0; optional or1; - optional or2 = i; // not portable - or1 = i; // not portable + optional or2 = i; // caution: not portable + or1 = i; // caution: not portable optional or3(i); // portable or1 = optional(i); // portable -In order to check if your compiler correctly implements reference binding use this test program. +Compilers known to have these deficiencies include GCC versions 4.2, 4.3, 4.4, 4.5, 5.1, 5.2; QCC 4.4.2; MSVC versions 8.0, 9.0, 10.0, 11.0, 12.0. In order to check if your compiler correctly implements reference binding use this test program. #include diff --git a/doc/91_relnotes.qbk b/doc/91_relnotes.qbk index 8fecf89..dcf180d 100644 --- a/doc/91_relnotes.qbk +++ b/doc/91_relnotes.qbk @@ -1,7 +1,7 @@ [/ Boost.Optional - Copyright (c) 2015 Andrzej Krzemienski + Copyright (c) 2015, 2016 Andrzej Krzemienski Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at @@ -11,11 +11,25 @@ [section:relnotes Release Notes] + +[heading Boost Release 1.61] + +* Now `boost::optional` is specialized for reference parameters. This addresses a couple of issues: + * the `sizeof` of optional reference is that of a pointer, + * some bugs connected to copying optional references are gone, + * all run-time bugs caused by incorrect reference binding on some compilers are now turned into compile-time errors, + * you can swap optional references: it is like swapping pointers: shalow, underlying objects are not affected, + * optional references to abstract types work. +* Documented nested typedefs ([@https://svn.boost.org/trac/boost/ticket/5193 Trac #5193]). +* Made the perfect-forwarding constructor SFINAE-friendly, which fixes [@https://svn.boost.org/trac/boost/ticket/12002 Trac #12002]. However, this only works in the newer compilers that implement variadic macros and `decltype` correctly. + + [heading Boost Release 1.60] * Changed the implementation of `boost::none` again. Now it is a const object with internal linkage (as any other tag). This fixes [@https://svn.boost.org/trac/boost/ticket/11203 Trac #11203]. -[heading Boost Release 1.59] + +[heading Boost Release 1.59] * For C++03 compilers, added 0-argument overload for member function `emplace()`, and therewith removed the dependency on ``. * Fixed [@https://svn.boost.org/trac/boost/ticket/11241 Trac #11241]. diff --git a/doc/html/boost_optional/acknowledgements.html b/doc/html/boost_optional/acknowledgements.html index d025d50..2cd116c 100644 --- a/doc/html/boost_optional/acknowledgements.html +++ b/doc/html/boost_optional/acknowledgements.html @@ -116,7 +116,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. 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&: + A number of compilers incorrectly treat const lvalues of integral type as + rvalues, and create an illegal temporary when binding to an lvalue reference + to const in some expressions. This could result in creating an optional lvalue + reference that is in fact bound to an unexpected temporary rather than to + the intended object. In order to prevent hard to find run-time bugs, this + library performs compile-time checks to prevent expressions that would otherwise + bind an optional reference to an unexpected temporary. As a consequence, + on certain compilers certain pieces of functionality in optional references + are missing. In order to maintain a portability of your code across diferent + compilers, it is recommended that you only stick to the minimum portable + interface of optional references: prefer 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&> or2 = i;  // caution: not portable
+or1 = i;                       // caution: not portable
 
 optional<const int&> or3(i);   // portable
 or1 = optional<const int&>(i); // portable
 

+ Compilers known to have these deficiencies include GCC versions 4.2, 4.3, + 4.4, 4.5, 5.1, 5.2; QCC 4.4.2; MSVC versions 8.0, 9.0, 10.0, 11.0, 12.0. In order to check if your compiler correctly implements reference binding use this test program.

@@ -86,7 +92,7 @@ -
-
-
-
-
-
-
-

-PrevUpHomeNext +PrevUpHomeNext

@@ -33,7 +33,7 @@

-

-PrevUpHomeNext +PrevUpHomeNext
diff --git a/doc/html/boost_optional/reference/header__boost_optional_optional_fwd_hpp_.html b/doc/html/boost_optional/reference/header__boost_optional_optional_fwd_hpp_.html index d87a473..06b75d0 100644 --- a/doc/html/boost_optional/reference/header__boost_optional_optional_fwd_hpp_.html +++ b/doc/html/boost_optional/reference/header__boost_optional_optional_fwd_hpp_.html @@ -52,7 +52,7 @@
-