From c9f1422560485545e91e1f7efa32775dcb1a7506 Mon Sep 17 00:00:00 2001
From: Andrzej Krzemienski
Date: Tue, 29 Apr 2014 01:06:14 +0200
Subject: [PATCH] Updated documentation; fixed optional::swap
---
.../boost_optional/detailed_semantics.html | 436 +++++++++++++++++-
.../boost_optional/optional_references.html | 16 +
doc/html/boost_optional/synopsis.html | 18 +-
doc/html/index.html | 2 +-
doc/reference.qbk | 265 ++++++++++-
doc/special_cases.qbk | 7 +
include/boost/optional/optional.hpp | 39 +-
include/boost/optional/optional_fwd.hpp | 5 +-
test/optional_test_move.cpp | 31 ++
9 files changed, 767 insertions(+), 52 deletions(-)
diff --git a/doc/html/boost_optional/detailed_semantics.html b/doc/html/boost_optional/detailed_semantics.html
index 4ab1a29..6fc4760 100644
--- a/doc/html/boost_optional/detailed_semantics.html
+++ b/doc/html/boost_optional/detailed_semantics.html
@@ -72,7 +72,7 @@
- optional<T>::optional();
+ optional<T>::optional() noexcept;
-
@@ -82,11 +82,7 @@
Postconditions:
*this
is uninitialized.
-
- Throws: Nothing.
-
--
- Notes: T's default constructor is not
- called.
+ Notes: T's default constructor is not called.
-
Example:
@@ -99,7 +95,7 @@
- optional<T>::optional( none_t );
+ optional<T>::optional( none_t ) noexcept;
-
@@ -109,9 +105,6 @@
-
Postconditions:
*this
is uninitialized.
--
- Throws: Nothing.
-
-
Notes:
T
's
default constructor is not called.
@@ -132,12 +125,16 @@
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 acopy of v
.
+ and its value is a copy of v
.
-
Throws: Whatever
T::T(
@@ -193,6 +190,58 @@
+
+
+
+
+ optional<T
(not a ref)>::optional( T&&
+ v )
+
+
+
+
+
+
+ optional<T&>::optional( T&& ref ) = delete
+
+-
+ Notes: This constructor is deleted
+
@@ -229,6 +278,10 @@
optional<T
(not a ref)>::optional( optional const& rhs );
+-
+ Requires:
is_copy_constructible<T>::value
+ is true
.
+
-
Effect: Copy-Constructs an
optional
.
@@ -320,6 +373,116 @@
+
+
+
+
+ optional<T
(not a ref)>::optional( optional&& rhs
+ ) noexcept(
see below);
+
+
+
+
+
+
+ optional<T&>::optional( optional &&
+ rhs );
+
+
@@ -368,6 +531,52 @@
+
+
+
+
+ template<U> explicit optional<T
+ (not a ref)>::optional( optional<U>&&
+ rhs );
+
+
@@ -511,6 +720,66 @@
+
+
+
+
+ optional&
+ optional<T
(not a ref)>::operator= ( T&& rhs
+ ) ;
+
+
+
+
+
+
+ optional<T&>&
+ optional<T&>::operator= ( T&&
+ rhs )
+ = delete;
+
+-
+ Notes: This assignment operator is deleted.
+
@@ -613,6 +882,75 @@
+
+
+
+
+ optional&
+ optional<T
(not a ref)>::operator= ( optional&& rhs
+ ) noexcept(
see below);
+
+
+
+
+
+
+ optional<T&> & optional<T&>::operator= ( optional<T&>&&
+ rhs )
+ ;
+
+-
+ Effect: Same as
optional<T&>::operator= ( optional<T&> const& rhs )
.
+
@@ -673,6 +1011,59 @@
+
+
+
+
+ template<U> optional&
+ optional<T
(not a ref)>::operator= ( optional<U>&&
+ rhs )
+ ;
+
+
@@ -768,7 +1159,7 @@
-
- Requirements:
*this
is initialized
+ Requires: *this
is initialized
-
Returns: A reference to the contained
@@ -870,7 +1261,7 @@
-
- Requirements:
*this
is initialized
+ Requires: *this
is initialized
-
Returns: The
@@ -956,7 +1347,7 @@
-
- Requirements:
*this
is initialized.
+ Requires: *this
is initialized.
-
Returns: A pointer to the contained value.
@@ -1005,16 +1396,13 @@
- bool optional<T>::operator!() ;
+ bool optional<T>::operator!() noexcept ;
-
Returns: If
*this
is uninitialized, true
;
else false
.
--
- Throws: Nothing.
-
-
Notes: This operator is provided for those
compilers which can't use the unspecified-bool-type operator
@@ -1288,7 +1676,7 @@
void swap
( optional<T>&
- x, optional<T>& y );
+ x, optional<T>& y ) ;
-
@@ -1305,19 +1693,21 @@
-
Throws: If both are initialized, whatever
swap(T&,T&)
- throws. If only one is initialized, whatever T::T ( T const& )
throws.
+ 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 const& )
- is called.
+ 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>::reset( T const& )
.
+ If only one is initialized, it has the same basic guarantee as optional<T>::operator= ( T&&
+ )
.
-
Example:
diff --git a/doc/html/boost_optional/optional_references.html b/doc/html/boost_optional/optional_references.html
index a603c1c..92770cf 100644
--- a/doc/html/boost_optional/optional_references.html
+++ b/doc/html/boost_optional/optional_references.html
@@ -68,6 +68,22 @@
than the reference itself.
+
+
+ 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;
+optional<const int&> oi = 1;
+
|
diff --git a/doc/html/boost_optional/synopsis.html b/doc/html/boost_optional/synopsis.html
index 078dd02..1da981f 100644
--- a/doc/html/boost_optional/synopsis.html
+++ b/doc/html/boost_optional/synopsis.html
@@ -37,19 +37,25 @@
- optional () ;
+ optional () noexcept ;
- optional ( none_t ) ;
+ optional ( none_t ) noexcept ;
optional ( T const& v ) ;
+ optional ( T&& v ) ;
+
optional ( bool condition, T const& v ) ;
optional ( optional const& rhs ) ;
+ optional ( optional&& rhs ) noexcept(see below) ;
+
template<class U> explicit optional ( optional<U> const& rhs ) ;
+ template<class U> explicit optional ( optional<U>&& rhs ) ;
+
template<class InPlaceFactory> explicit optional ( InPlaceFactory const& f ) ;
template<class TypedInPlaceFactory> explicit optional ( TypedInPlaceFactory const& f ) ;
@@ -58,10 +64,16 @@
optional& operator = ( T const& v ) ;
+ optional& operator = ( T&& v ) ;
+
optional& operator = ( optional const& rhs ) ;
+ optional& operator = ( optional&& rhs ) noexcept(see below) ;
+
template<class U> optional& operator = ( optional<U> const& rhs ) ;
+ template<class U> optional& operator = ( optional<U>&& rhs ) ;
+
template<class InPlaceFactory> optional& operator = ( InPlaceFactory const& f ) ;
template<class TypedInPlaceFactory> optional& operator = ( TypedInPlaceFactory const& f ) ;
@@ -83,7 +95,7 @@
operator unspecified-bool-type() const ;
- bool operator!() const ;
+ bool operator!() const noexcept ;
diff --git a/doc/html/index.html b/doc/html/index.html
index 2103f59..e1230c1 100644
--- a/doc/html/index.html
+++ b/doc/html/index.html
@@ -163,7 +163,7 @@
-Last revised: April 11, 2014 at 13:25:26 GMT |
+Last revised: April 28, 2014 at 23:02:29 GMT |
|
diff --git a/doc/reference.qbk b/doc/reference.qbk
index cd0234c..d07c440 100644
--- a/doc/reference.qbk
+++ b/doc/reference.qbk
@@ -22,18 +22,24 @@
// (If T is of reference type, the parameters and results by reference are by value)
- optional () ; ``[link reference_optional_constructor __GO_TO__]``
+ optional () noexcept ; ``[link reference_optional_constructor __GO_TO__]``
- optional ( none_t ) ; ``[link reference_optional_constructor_none_t __GO_TO__]``
+ optional ( none_t ) noexcept ; ``[link reference_optional_constructor_none_t __GO_TO__]``
optional ( T const& v ) ; ``[link reference_optional_constructor_value __GO_TO__]``
+
+ optional ( T&& v ) ; ``[link reference_optional_constructor_move_value __GO_TO__]``
// [new in 1.34]
optional ( bool condition, T const& v ) ; ``[link reference_optional_constructor_bool_value __GO_TO__]``
optional ( optional const& rhs ) ; ``[link reference_optional_constructor_optional __GO_TO__]``
+
+ optional ( optional&& rhs ) noexcept(``['see below]``) ; ``[link reference_optional_move_constructor_optional __GO_TO__]``
template explicit optional ( optional const& rhs ) ; ``[link reference_optional_constructor_other_optional __GO_TO__]``
+
+ template explicit optional ( optional&& rhs ) ; ``[link reference_optional_move_constructor_other_optional __GO_TO__]``
template explicit optional ( InPlaceFactory const& f ) ; ``[link reference_optional_constructor_factory __GO_TO__]``
@@ -42,10 +48,16 @@
optional& operator = ( none_t ) ; ``[/[link reference_optional_operator_equal_none_t __GO_TO__]]``
optional& operator = ( T const& v ) ; ``[link reference_optional_operator_equal_value __GO_TO__]``
+
+ optional& operator = ( T&& v ) ; ``[link reference_optional_operator_move_equal_value __GO_TO__]``
optional& operator = ( optional const& rhs ) ; ``[link reference_optional_operator_equal_optional __GO_TO__]``
+
+ optional& operator = ( optional&& rhs ) noexcept(``['see below]``) ; ``[link reference_optional_operator_move_equal_optional __GO_TO__]``
template optional& operator = ( optional const& rhs ) ; ``[link reference_optional_operator_equal_other_optional __GO_TO__]``
+
+ template optional& operator = ( optional&& rhs ) ; ``[link reference_optional_operator_move_equal_other_optional __GO_TO__]``
template optional& operator = ( InPlaceFactory const& f ) ; ``[link reference_optional_operator_equal_factory __GO_TO__]``
@@ -68,7 +80,7 @@
operator unspecified-bool-type() const ; ``[link reference_optional_operator_bool __GO_TO__]``
- bool operator!() const ; ``[link reference_optional_operator_not __GO_TO__]``
+ bool operator!() const noexcept ; ``[link reference_optional_operator_not __GO_TO__]``
// deprecated methods
@@ -151,12 +163,11 @@ __SPACE__
[#reference_optional_constructor]
-[: `optional::optional();`]
+[: `optional::optional() noexcept;`]
* [*Effect:] Default-Constructs an `optional`.
* [*Postconditions:] `*this` is [_uninitialized].
-* [*Throws:] Nothing.
-* Notes: T's default constructor [_is not] called.
+* [*Notes:] T's default constructor [_is not] called.
* [*Example:]
``
optional def ;
@@ -167,11 +178,10 @@ __SPACE__
[#reference_optional_constructor_none_t]
-[: `optional::optional( none_t );`]
+[: `optional::optional( none_t ) noexcept;`]
* [*Effect:] Constructs an `optional` uninitialized.
* [*Postconditions:] `*this` is [_uninitialized].
-* [*Throws:] Nothing.
* [*Notes:] `T`'s default constructor [_is not] called. The expression
`boost::none` denotes an instance of `boost::none_t` that can be used as
the parameter.
@@ -188,8 +198,9 @@ __SPACE__
[: `optional::optional( T const& v )`]
+* [*Requires:] `is_copy_constructible::value` is `true`.
* [*Effect:] Directly-Constructs an `optional`.
-* [*Postconditions:] `*this` is [_initialized] and its value is a['copy]
+* [*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.
@@ -220,6 +231,33 @@ assert ( *opt == v ) ;
assert (*opt == v);
``
+__SPACE__
+
+[#reference_optional_constructor_move_value]
+
+[: `optional::optional( T&& v )`]
+
+* [*Requires:] `is_move_constructible::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 opt(std::move(v1));
+assert ( *opt == v2 ) ;
+``
+
+__SPACE__
+
+[: `optional::optional( T&& ref ) = delete`]
+
+* [*Notes:] This constructor is deleted
+
+
__SPACE__
[#reference_optional_constructor_bool_value]
@@ -243,6 +281,7 @@ __SPACE__
[: `optional::optional( optional const& rhs );`]
+* [*Requires:] `is_copy_constructible::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.
@@ -299,6 +338,70 @@ assert ( *init2 == 3 ) ;
__SPACE__
+[#reference_optional_move_constructor_optional]
+
+[: `optional::optional( optional&& rhs ) noexcept(`['see below]`);`]
+
+* [*Requires:] `is_move_constructible::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::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> uninit ;
+assert (!uninit);
+
+optional> uinit2 ( std::move(uninit) ) ;
+assert ( uninit2 == uninit );
+
+optional> init( std::uniqye_ptr(new T(2)) );
+assert ( **init == T(2) ) ;
+
+optional> init2 ( std::move(init) ) ;
+assert ( init );
+assert ( *init == nullptr );
+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 reefer 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 );`]
@@ -323,6 +426,30 @@ assert( *y == 123 ) ;
__SPACE__
+[#reference_optional_move_constructor_other_optional]
+
+[: `template explicit optional::optional( optional&& 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 x(123.4);
+assert ( *x == 123.4 ) ;
+
+optional y(std::move(x)) ;
+assert( *y == 123 ) ;
+``
+
+__SPACE__
+
[#reference_optional_constructor_factory]
[: `template explicit optional::optional( InPlaceFactory const& f );`]
@@ -408,6 +535,42 @@ c = 4 ;
assert ( *opt == 4 ) ;
``
+__SPACE__
+
+[#reference_optional_operator_move_equal_value]
+
+[: `optional& optional::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 def ;
+optional opt(x) ;
+
+T y1, y2, yR;
+def = std::move(y1) ;
+assert ( *def == yR ) ;
+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]
@@ -471,6 +634,42 @@ assert ( *ora == 4 ) ;
__SPACE__
+[#reference_optional_operator_move_equal_optional]
+
+[: `optional& optional::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::value && is_nothrow_move_assignable::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 opt(T(2)) ;
+optional def ;
+
+opt = def ;
+assert ( def ) ;
+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 ) ;`]
@@ -502,6 +701,37 @@ assert ( *opt1 == static_cast(v) ) ;
__SPACE__
+[#reference_optional_operator_move_equal_other_optional]
+
+[: `template optional& optional::operator= ( optional&& 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 opt0(v);
+optional opt1;
+
+opt1 = std::move(opt0) ;
+assert ( *opt1 == static_cast(v) ) ;
+``
+
+__SPACE__
+
[#reference_optional_operator_equal_factory]
[: `template optional& optional::operator=( InPlaceFactory const& f );`]
@@ -543,7 +773,7 @@ __SPACE__
[: `inline T const& get ( optional const& ) ;`]
[: `inline T& get ( optional &) ;`]
-* [*Requirements:] `*this` is initialized
+* [*Requires:] `*this` is initialized
* [*Returns:] A reference to the contained value
* [*Throws:] Nothing.
* [*Notes:] The requirement is asserted via `BOOST_ASSERT()`.
@@ -593,7 +823,7 @@ __SPACE__
[: `inline T const& get ( optional const& ) ;`]
[: `inline T& get ( optional &) ;`]
-* [*Requirements: ] `*this` is initialized
+* [*Requires: ] `*this` is initialized
* [*Returns:] [_The] reference contained.
* [*Throws:] Nothing.
* [*Notes:] The requirement is asserted via `BOOST_ASSERT()`.
@@ -641,7 +871,7 @@ __SPACE__
[: `T const* optional::operator ->() const ;`]
[: `T* optional::operator ->() ;`]
-* [*Requirements: ] `*this` is initialized.
+* [*Requires: ] `*this` is initialized.
* [*Returns:] A pointer to the contained value.
* [*Throws:] Nothing.
* [*Notes:] The requirement is asserted via `BOOST_ASSERT()`.
@@ -675,10 +905,9 @@ __SPACE__
[#reference_optional_operator_not]
-[: `bool optional::operator!() ;`]
+[: `bool optional::operator!() noexcept ;`]
* [*Returns:] If `*this` is uninitialized, `true`; else `false`.
-* [*Throws:] Nothing.
* [*Notes:] This operator is provided for those compilers which can't
use the ['unspecified-bool-type operator] in certain boolean contexts.
* [*Example:]
@@ -852,21 +1081,21 @@ __SPACE__
[#reference_swap_optional_optional]
-[: `void swap ( optional& x, optional& y );`]
+[: `void swap ( optional& x, optional& y ) ;`]
* [*Effect:] If both `x` and `y` are initialized, calls `swap(*x,*y)`
using `std::swap`. If only one is initialized, say `x`, calls:
`y.reset(*x); x.reset();` If none is initialized, does nothing.
* [*Postconditions:] The states of `x` and `y` interchanged.
* [*Throws:] If both are initialized, whatever `swap(T&,T&)` throws. If only
-one is initialized, whatever `T::T ( T const& )` throws.
+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 const& )` is called.
+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::reset( T const& )`.
+`optional::operator= ( T&& )`.
* [*Example:]
``
T x(12);
diff --git a/doc/special_cases.qbk b/doc/special_cases.qbk
index 681e517..0f6f22b 100644
--- a/doc/special_cases.qbk
+++ b/doc/special_cases.qbk
@@ -21,6 +21,13 @@ will nonetheless reefer to the same object.
* Value-access will actually provide access to the referenced object
rather than the reference itself.
+[heading Rvalue references]
+
+Rvalue references and lvalue references to const have the ability in C++ to extend the life time of a temporary they bind to. Optional references do not have this capability, therefore to avoid surprising effects it is not possible to initialize an optional references from a temporary. Optional rvalue references are disabled altogether. Also, the initialization and assignment of an optional reference to const from rvalue reference is disabled.
+
+ const int& i = 1; // legal
+ optional oi = 1; // illegal
+
[endsect]
[section Rebinding semantics for assignment of optional references]
diff --git a/include/boost/optional/optional.hpp b/include/boost/optional/optional.hpp
index bbbe3be..d191462 100644
--- a/include/boost/optional/optional.hpp
+++ b/include/boost/optional/optional.hpp
@@ -30,6 +30,8 @@
#include
#include
#include
+#include
+#include
#include
#include
#include
@@ -99,8 +101,7 @@ class in_place_factory_base ;
class typed_in_place_factory_base ;
// This forward is needed to refer to namespace scope swap from the member swap
-template void swap ( optional& x, optional& y )
- BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible::value && ::boost::is_nothrow_move_assignable::value);
+template void swap ( optional& x, optional& y );
namespace optional_detail {
@@ -1242,6 +1243,37 @@ struct swap_selector
}
};
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+template<>
+struct swap_selector
+{
+ template
+ static void optional_swap ( optional& x, optional& y )
+ //BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible::value && BOOST_NOEXCEPT_EXPR(boost::swap(*x, *y)))
+ {
+ if(x)
+ {
+ if (y)
+ {
+ boost::swap(*x, *y);
+ }
+ else
+ {
+ y = boost::move(*x);
+ x = boost::none;
+ }
+ }
+ else
+ {
+ if (y)
+ {
+ x = boost::move(*y);
+ y = boost::none;
+ }
+ }
+ }
+};
+#else
template<>
struct swap_selector
{
@@ -1268,6 +1300,7 @@ struct swap_selector
}
}
};
+#endif // !defined BOOST_NO_CXX11_RVALUE_REFERENCES
} // namespace optional_detail
@@ -1275,7 +1308,7 @@ template
struct optional_swap_should_use_default_constructor : has_nothrow_default_constructor {} ;
template inline void swap ( optional& x, optional& y )
- BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible::value && ::boost::is_nothrow_move_assignable::value)
+ //BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible::value && BOOST_NOEXCEPT_EXPR(boost::swap(*x, *y)))
{
optional_detail::swap_selector::value>::optional_swap(x, y);
}
diff --git a/include/boost/optional/optional_fwd.hpp b/include/boost/optional/optional_fwd.hpp
index ade503d..29cee49 100644
--- a/include/boost/optional/optional_fwd.hpp
+++ b/include/boost/optional/optional_fwd.hpp
@@ -16,16 +16,13 @@
#ifndef BOOST_OPTIONAL_OPTIONAL_FWD_FLC_19NOV2002_HPP
#define BOOST_OPTIONAL_OPTIONAL_FWD_FLC_19NOV2002_HPP
#include
-#include
-#include
namespace boost {
template class optional ;
-template void swap ( optional& , optional& )
- BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible::value && ::boost::is_nothrow_move_assignable::value);
+template void swap ( optional& , optional& );
template struct optional_swap_should_use_default_constructor ;
diff --git a/test/optional_test_move.cpp b/test/optional_test_move.cpp
index a2d20c1..affa07f 100644
--- a/test/optional_test_move.cpp
+++ b/test/optional_test_move.cpp
@@ -314,6 +314,35 @@ void test_move_ctor_from_optional_U()
BOOST_CHECK(b2->val == 4);
}
+void test_swap()
+{
+ optional a((MoveOnly(2)));
+ optional b((MoveOnly(3)));
+ swap(a, b);
+
+ BOOST_CHECK(a->val == 3);
+ BOOST_CHECK(b->val == 2);
+}
+
+void test_optional_ref_to_movables()
+{
+ MoveOnly m(3);
+ optional orm = m;
+ orm->val = 2;
+ BOOST_CHECK(m.val == 2);
+
+ optional orm2 = orm;
+ orm2->val = 1;
+ BOOST_CHECK(m.val == 1);
+ BOOST_CHECK(orm->val == 1);
+
+ optional orm3 = boost::move(orm);
+ orm3->val = 4;
+ BOOST_CHECK(m.val == 4);
+ BOOST_CHECK(orm->val == 4);
+ BOOST_CHECK(orm2->val == 4);
+}
+
// these 4 classes have different noexcept signatures in move operations
struct NothrowBoth {
NothrowBoth(NothrowBoth&&) BOOST_NOEXCEPT_IF(true) {};
@@ -370,6 +399,8 @@ int test_main( int, char* [] )
test_move_assign_from_optional_T();
test_move_assign_from_optional_U();
test_with_move_only();
+ test_optional_ref_to_movables();
+ test_swap();
#endif
}
catch ( ... )