diff --git a/doc/00_optional.qbk b/doc/00_optional.qbk
index fb5d584..1c8d59b 100644
--- a/doc/00_optional.qbk
+++ b/doc/00_optional.qbk
@@ -26,8 +26,9 @@ Distributed under the Boost Software License, Version 1.0.
[def __BOOST_TUPLE__ [@../../../tuple/index.html Boost.Tuple]]
[def __BOOST_TRIBOOL__ [@../../../../doc/html/tribool.html boost::tribool]]
-[def __OPTIONAL_POINTEE__ [@../../../utility/OptionalPointee.html OptionalPointee]]
-[def __COPY_CONSTRUCTIBLE__ [@../../../utility/CopyConstructible.html Copy Constructible]]
+[def __OPTIONAL_POINTEE__ [@../../../utility/OptionalPointee.html `OptionalPointee`]]
+[def __COPY_CONSTRUCTIBLE__ [@../../../utility/CopyConstructible.html `CopyConstructible`]]
+[def __MOVE_CONSTRUCTIBLE__ `MoveConstructible`]
[def __FUNCTION_EQUAL_POINTEES__ [@../../../utility/OptionalPointee.html#equal `equal_pointees()`]]
[def __FUNCTION_LESS_POINTEES__ [@../../../utility/OptionalPointee.html#less `less_pointees()`]]
diff --git a/doc/18_type_requirements.qbk b/doc/18_type_requirements.qbk
index 6faae48..033a6eb 100644
--- a/doc/18_type_requirements.qbk
+++ b/doc/18_type_requirements.qbk
@@ -13,12 +13,12 @@ But this is practically useless. In order for `optional` to be able to do any
optional o;
o.emplace("T", "ctor", "params");
-If `T` is `MoveConstructible`, `optional` is also `MoveConstructible` and can be easily initialized from an rvalue of type `T` and be passed by value:
+If `T` is __MOVE_CONSTRUCTIBLE__, `optional` is also __MOVE_CONSTRUCTIBLE__ and can be easily initialized from an rvalue of type `T` and be passed by value:
optional o = make_T();
optional p = optional();
-If `T` is `CopyConstructible`, `optional` is also `CopyConstructible` and can be easily initialized from an lvalue of type `T`:
+If `T` is __COPY_CONSTRUCTIBLE__, `optional` is also __COPY_CONSTRUCTIBLE__ and can be easily initialized from an lvalue of type `T`:
T v = make_T();
optional o = v;
@@ -29,9 +29,9 @@ If `T` is not `MoveAssignable`, it is still possible to reset the value of `opti
optional o = make_T();
o.emplace(make_another_T());
-If `T` is `Moveable` (both `MoveConstructible` and `MoveAssignable`) then `optional` is also `Moveable` and additionally can be constructed and assigned from an rvalue of type `T`.
+If `T` is `Moveable` (both __MOVE_CONSTRUCTIBLE__ and `MoveAssignable`) then `optional` is also `Moveable` and additionally can be constructed and assigned from an rvalue of type `T`.
-Similarly, if `T` is `Copyable` (both `CopyConstructible` and `CopyAssignable`) then `optional` is also `Copyable` and additionally can be constructed and assigned from an lvalue of type `T`.
+Similarly, if `T` is `Copyable` (both __COPY_CONSTRUCTIBLE__ and `CopyAssignable`) then `optional` is also `Copyable` and additionally can be constructed and assigned from an lvalue of type `T`.
`T` ['is not] required to be __SGI_DEFAULT_CONSTRUCTIBLE__.
diff --git a/doc/20_reference.qbk b/doc/20_reference.qbk
index 82cd932..3a6330e 100644
--- a/doc/20_reference.qbk
+++ b/doc/20_reference.qbk
@@ -80,12 +80,12 @@
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 ) && ; ``[link reference_optional_value_or __GO_TO__]``
+ template T value_or( U && v ) && ; ``[link reference_optional_value_or_move __GO_TO__]``
T const* get_ptr() const ; ``[link reference_optional_get_ptr __GO_TO__]``
T* get_ptr() ; ``[link reference_optional_get_ptr __GO_TO__]``
- explicit operator bool() const ; ``[link reference_optional_operator_bool __GO_TO__]``
+ explicit operator bool() const noexcept ; ``[link reference_optional_operator_bool __GO_TO__]``
bool operator!() const noexcept ; ``[link reference_optional_operator_not __GO_TO__]``
@@ -761,7 +761,7 @@ __SPACE__
of type `T` with `std::forward(args)...`.
* [*Postconditions: ] `*this` is [_initialized].
* [*Throws:] Whatever the selected `T`'s constructor throws.
-* [*Notes:] `T` need not be `MoveConstructible` or `MoveAssignable`. On compilers that do not support variadic templates, the signature falls back to single-argument: `template void emplace(Arg&& arg)`. On compilers that do not support rvalue references, the signature falls back to two overloads: taking `const` and non-`const` lvalue reference.
+* [*Notes:] `T` need not be __MOVE_CONSTRUCTIBLE__ or `MoveAssignable`. On compilers that do not support variadic templates, the signature falls back to single-argument: `template void emplace(Arg&& arg)`. On compilers that do not support rvalue references, the signature falls back to two overloads: taking `const` and non-`const` lvalue reference.
* [*Exception Safety:] If an exception is thrown during the initialization of `T`, `*this` is ['uninitialized].
* [*Example:]
``
@@ -906,12 +906,22 @@ __SPACE__
[#reference_optional_value_or]
[: `template T optional::value_or(U && v) const& ;`]
+
+* [*Requires:] `T` is __COPY_CONSTRUCTIBLE__ and `U &&` is convertible to `T`.
+* [*Returns:] `bool(*this) ? **this : static_cast(forward(v))`.
+* [*Throws:] Any exception thrown by the selected constructor of `T`.
+* [*Notes:] On compilers that do not support ref-qualifiers on member functions this overload is replaced with the `const`-qualified member function. On compilers without rvalue reference support the type of `v` becomes `U const&`.
+
+__SPACE__
+
+[#reference_optional_value_or_move]
+
[: `template T optional::value_or(U && v) && ;`]
-* [*Requires:] `T` is CopyConstructible.
-* [*Returns:] First overload: `bool(*this) ? **this : static_cast(forward(v))`. second overload: `bool(*this) ? std::move(**this) : static_cast(forward(v))`.
+* [*Requires:] `T` is __MOVE_CONSTRUCTIBLE__ and `U &&` is convertible to `T`.
+* [*Returns:] `bool(*this) ? std::move(**this) : static_cast(forward(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&`.
+* [*Notes:] On compilers that do not support ref-qualifiers on member functions this overload is replaced with the classical non-`const`-qualified member function. On compilers without rvalue reference support the type of `v` becomes `U const&`.
__SPACE__
@@ -989,10 +999,9 @@ __SPACE__
[#reference_optional_operator_bool]
-[: `explicit optional::operator bool() const ;`]
+[: `explicit optional::operator bool() const noexcept ;`]
* [*Returns:] `get_ptr() != 0`.
-* [*Throws:] Nothing.
* [*Notes:] On compilers that do not support explicit conversion operators this falls back to safe-bool idiom.
* [*Example:]
``
diff --git a/doc/html/boost_optional/reference/detailed_semantics.html b/doc/html/boost_optional/reference/detailed_semantics.html
index 5d71e1d..23c6745 100644
--- a/doc/html/boost_optional/reference/detailed_semantics.html
+++ b/doc/html/boost_optional/reference/detailed_semantics.html
@@ -1400,19 +1400,14 @@
const&
;
-
- template<class U> T optional<T>::value_or(U &&
- v)
- && ;
-
-
Requires:
T
- is CopyConstructible.
+ is CopyConstructible
and U &&
+ is convertible to T
.
-
- 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))
.
+ Returns: bool(*this) ? **this : static_cast<T>(forward<U>(v))
.
-
Throws: Any exception thrown by the
@@ -1420,13 +1415,42 @@
-
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.
+ ref-qualifiers on member functions this overload is replaced with the
+ const
-qualified member function.
On compilers without rvalue reference support the type of v
becomes U
const&
.
+
+
+
+
+ template<class U> T optional<T>::value_or(U &&
+ v)
+ && ;
+
+
+-
+ Requires:
T
+ is MoveConstructible
+ and U &&
+ is convertible to T
.
+
+-
+ Returns:
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 this overload is replaced with the
+ classical non-
const
-qualified
+ member function. On compilers without rvalue reference support the type
+ of v
becomes U const&
.
+
+
@@ -1572,15 +1596,13 @@
explicit optional<T>::operator
bool()
- const ;
+ const noexcept
+ ;
-
Returns:
get_ptr() != 0
.
--
- Throws: Nothing.
-
-
Notes: On compilers that do not support
explicit conversion operators this falls back to safe-bool idiom.
diff --git a/doc/html/boost_optional/tutorial/design_overview/the_interface.html b/doc/html/boost_optional/tutorial/design_overview/the_interface.html
index 8fa2707..984ae4b 100644
--- a/doc/html/boost_optional/tutorial/design_overview/the_interface.html
+++ b/doc/html/boost_optional/tutorial/design_overview/the_interface.html
@@ -98,10 +98,11 @@
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.
+ 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
@@ -127,7 +128,7 @@
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
+ OptionalPointee
concept incarnated by pointers.
diff --git a/doc/html/boost_optional/tutorial/in_place_factories.html b/doc/html/boost_optional/tutorial/in_place_factories.html
index 3c26b05..d6907b9 100644
--- a/doc/html/boost_optional/tutorial/in_place_factories.html
+++ b/doc/html/boost_optional/tutorial/in_place_factories.html
@@ -31,9 +31,9 @@
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:
+ to be CopyConstructible
, but also requires
+ the existence of a fully constructed object, often temporary, just to follow
+ the copy from:
struct X
{
diff --git a/doc/html/boost_optional/tutorial/type_requirements.html b/doc/html/boost_optional/tutorial/type_requirements.html
index 775e7bb..38a106d 100644
--- a/doc/html/boost_optional/tutorial/type_requirements.html
+++ b/doc/html/boost_optional/tutorial/type_requirements.html
@@ -60,10 +60,9 @@
optional<T> p = optional<T>();
- If T
is CopyConstructible
,
- optional<T>
is
- also CopyConstructible
and
- can be easily initialized from an lvalue of type T
:
+ If T
is CopyConstructible
, optional<T>
is
+ also CopyConstructible
+ and can be easily initialized from an lvalue of type T
:
T v = make_T();
optional<T> o = v;
@@ -85,10 +84,8 @@
can be constructed and assigned from an rvalue of type T
.
- Similarly, if T
is Copyable
(both CopyConstructible
- and CopyAssignable
) then
- optional<T>
is
- also Copyable
and additionally
+ Similarly, if T
is Copyable
(both CopyConstructible
and CopyAssignable
) then optional<T>
+ is also Copyable
and additionally
can be constructed and assigned from an lvalue of type T
.
diff --git a/doc/html/index.html b/doc/html/index.html
index af4424e..a96a8b8 100644
--- a/doc/html/index.html
+++ b/doc/html/index.html
@@ -133,7 +133,7 @@
-Last revised: June 08, 2014 at 18:14:37 GMT |
+Last revised: June 16, 2014 at 12:04:51 GMT |
|
diff --git a/doc/html/optional/reference.html b/doc/html/optional/reference.html
index a1a6d0e..0ab1183 100644
--- a/doc/html/optional/reference.html
+++ b/doc/html/optional/reference.html
@@ -104,12 +104,12 @@
T&& value() && ;
template<class U> T value_or( U && v ) const& ;
- template<class U> T value_or( U && v ) && ;
+ template<class U> T value_or( U && v ) && ;
T const* get_ptr() const ;
T* get_ptr() ;
- explicit operator bool() const ;
+ explicit operator bool() const noexcept ;
bool operator!() const noexcept ;
diff --git a/include/boost/optional/optional.hpp b/include/boost/optional/optional.hpp
index a9763a5..35e147c 100644
--- a/include/boost/optional/optional.hpp
+++ b/include/boost/optional/optional.hpp
@@ -23,6 +23,7 @@
#include
#include
+#include
#include
#include
#include
@@ -34,6 +35,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -49,7 +51,7 @@
#include
#include
#include
-#include
+
#include
#include
@@ -1059,23 +1061,36 @@ class optional : public optional_detail::optional_base
#ifndef BOOST_NO_CXX11_REF_QUALIFIERS
template
value_type value_or ( U&& v ) const&
- { return this->is_initialized() ? get() : static_cast(boost::forward(v)); }
+ {
+ BOOST_STATIC_ASSERT((is_convertible::value));
+ return this->is_initialized() ? get() : static_cast(boost::forward(v));
+ }
template
value_type value_or ( U&& v ) &&
- { return this->is_initialized() ? boost::move(get()) : static_cast(boost::forward(v)); }
+ {
+ BOOST_STATIC_ASSERT((is_convertible::value));
+ return this->is_initialized() ? boost::move(get()) : static_cast(boost::forward(v));
+ }
#elif !defined BOOST_NO_CXX11_RVALUE_REFERENCES
template
value_type value_or ( U&& v ) const
- { return this->is_initialized() ? get() : static_cast(boost::forward(v)); }
+ {
+ BOOST_STATIC_ASSERT((is_convertible::value));
+ return this->is_initialized() ? get() : static_cast(boost::forward(v));
+ }
#else
template
- value_type value_or ( U const& v ) const { return this->is_initialized() ? get() : static_cast(v); }
+ value_type value_or ( U const& v ) const
+ {
+ BOOST_STATIC_ASSERT((is_convertible::value));
+ return this->is_initialized() ? get() : static_cast(v);
+ }
#endif
bool operator!() const BOOST_NOEXCEPT { return !this->is_initialized() ; }
- BOOST_EXPLICIT_OPERATOR_BOOL()
+ BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()
} ;
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
diff --git a/test/Jamfile.v2 b/test/Jamfile.v2
index 9d5e856..04c6cd4 100644
--- a/test/Jamfile.v2
+++ b/test/Jamfile.v2
@@ -41,5 +41,6 @@ import testing ;
[ compile-fail optional_test_ref_fail_init_from_Urefref.cpp ]
[ compile-fail optional_test_ref_fail_assign_from_Trefref.cpp ]
[ compile-fail optional_test_ref_fail_assign_from_Urefref.cpp ]
+ [ compile-fail optional_test_fail_explicit_convert_in_value_or.cpp ]
;
}
diff --git a/test/optional_test_fail_explicit_convert_in_value_or.cpp b/test/optional_test_fail_explicit_convert_in_value_or.cpp
new file mode 100644
index 0000000..7b6f29c
--- /dev/null
+++ b/test/optional_test_fail_explicit_convert_in_value_or.cpp
@@ -0,0 +1,32 @@
+// Copyright (C) 2014, Andrzej Krzemienski.
+//
+// Use, modification, and distribution is subject to 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)
+//
+// See http://www.boost.org/lib/optional for documentation.
+//
+// You are welcome to contact the author at:
+// akrzemi1@gmail.com
+//
+#include "boost/optional.hpp"
+
+//
+// THIS TEST SHOULD FAIL TO COMPILE
+//
+
+struct U
+{};
+
+struct T
+{
+ explicit T(U const&) {}
+};
+
+
+void test_implicit_conversion_to_bool()
+{
+ boost::optional opt;
+ opt.value_or(U());
+}
+