From 8fc2901fad2cdece588476ace9a1a335a2582e42 Mon Sep 17 00:00:00 2001 From: Andrzej Krzemienski Date: Sat, 14 Jun 2014 00:46:24 +0200 Subject: [PATCH 1/4] explicit operator bool becomes noexcept --- doc/20_reference.qbk | 5 ++--- doc/html/boost_optional/reference/detailed_semantics.html | 6 ++---- doc/html/index.html | 2 +- doc/html/optional/reference.html | 2 +- include/boost/optional/optional.hpp | 5 +++-- 5 files changed, 9 insertions(+), 11 deletions(-) diff --git a/doc/20_reference.qbk b/doc/20_reference.qbk index 82cd932..691f475 100644 --- a/doc/20_reference.qbk +++ b/doc/20_reference.qbk @@ -85,7 +85,7 @@ 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__]`` @@ -989,10 +989,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..05ad5da 100644 --- a/doc/html/boost_optional/reference/detailed_semantics.html +++ b/doc/html/boost_optional/reference/detailed_semantics.html @@ -1572,15 +1572,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/index.html b/doc/html/index.html index af4424e..74b30e5 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 13, 2014 at 21:36:29 GMT


diff --git a/doc/html/optional/reference.html b/doc/html/optional/reference.html index a1a6d0e..9ec144c 100644 --- a/doc/html/optional/reference.html +++ b/doc/html/optional/reference.html @@ -109,7 +109,7 @@ T const* get_ptr() const ; R T* get_ptr() ; R - explicit operator bool() const ; R + explicit operator bool() const noexcept ; R bool operator!() const noexcept ; R diff --git a/include/boost/optional/optional.hpp b/include/boost/optional/optional.hpp index a9763a5..d5e3394 100644 --- a/include/boost/optional/optional.hpp +++ b/include/boost/optional/optional.hpp @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -49,7 +50,7 @@ #include #include #include -#include + #include #include @@ -1075,7 +1076,7 @@ class optional : public optional_detail::optional_base bool operator!() const BOOST_NOEXCEPT { return !this->is_initialized() ; } - BOOST_EXPLICIT_OPERATOR_BOOL() + BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT() } ; #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES From 31c9119266015c1084dcb7c640bd45c7e5375c80 Mon Sep 17 00:00:00 2001 From: Andrzej Krzemienski Date: Sat, 14 Jun 2014 22:49:37 +0200 Subject: [PATCH 2/4] value_or() requires that U is convertible to T Due to Vladimir Batov. --- doc/00_optional.qbk | 4 +-- doc/20_reference.qbk | 2 +- .../reference/detailed_semantics.html | 3 +- .../design_overview/the_interface.html | 11 ++++--- .../tutorial/in_place_factories.html | 6 ++-- doc/html/index.html | 2 +- include/boost/optional/optional.hpp | 22 ++++++++++--- test/Jamfile.v2 | 1 + ...test_fail_explicit_convert_in_value_or.cpp | 32 +++++++++++++++++++ 9 files changed, 66 insertions(+), 17 deletions(-) create mode 100644 test/optional_test_fail_explicit_convert_in_value_or.cpp diff --git a/doc/00_optional.qbk b/doc/00_optional.qbk index fb5d584..6b41c88 100644 --- a/doc/00_optional.qbk +++ b/doc/00_optional.qbk @@ -26,8 +26,8 @@ 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 __FUNCTION_EQUAL_POINTEES__ [@../../../utility/OptionalPointee.html#equal `equal_pointees()`]] [def __FUNCTION_LESS_POINTEES__ [@../../../utility/OptionalPointee.html#less `less_pointees()`]] diff --git a/doc/20_reference.qbk b/doc/20_reference.qbk index 691f475..bac369a 100644 --- a/doc/20_reference.qbk +++ b/doc/20_reference.qbk @@ -908,7 +908,7 @@ __SPACE__ [: `template T optional::value_or(U && v) const& ;`] [: `template T optional::value_or(U && v) && ;`] -* [*Requires:] `T` is CopyConstructible. +* [*Requires:] `T` is __COPY_CONSTRUCTIBLE__ and `U &&` is convertible to `T`. * [*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 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&`. diff --git a/doc/html/boost_optional/reference/detailed_semantics.html b/doc/html/boost_optional/reference/detailed_semantics.html index 05ad5da..21aebff 100644 --- a/doc/html/boost_optional/reference/detailed_semantics.html +++ b/doc/html/boost_optional/reference/detailed_semantics.html @@ -1408,7 +1408,8 @@
  • Requires: T - is CopyConstructible. + is CopyConstructible and U && + is convertible to T.
  • Returns: First overload: bool(*this) ? **this 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/index.html b/doc/html/index.html
    index 74b30e5..4495d9b 100644
    --- a/doc/html/index.html
    +++ b/doc/html/index.html
    @@ -133,7 +133,7 @@
     
- +

Last revised: June 13, 2014 at 21:36:29 GMT

Last revised: June 14, 2014 at 20:46:55 GMT


diff --git a/include/boost/optional/optional.hpp b/include/boost/optional/optional.hpp index d5e3394..c742570 100644 --- a/include/boost/optional/optional.hpp +++ b/include/boost/optional/optional.hpp @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -1060,18 +1061,31 @@ 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() ; } 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()); +} + From 0a2a8957fa010d08a0fe29d0c6bfb3753a5ed0af Mon Sep 17 00:00:00 2001 From: Andrzej Krzemienski Date: Sun, 15 Jun 2014 21:51:07 +0200 Subject: [PATCH 3/4] bug fix: comma in BOOST_STATIC_ASSERT --- include/boost/optional/optional.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/boost/optional/optional.hpp b/include/boost/optional/optional.hpp index c742570..35e147c 100644 --- a/include/boost/optional/optional.hpp +++ b/include/boost/optional/optional.hpp @@ -1062,28 +1062,28 @@ class optional : public optional_detail::optional_base template value_type value_or ( U&& v ) const& { - BOOST_STATIC_ASSERT(is_convertible::value); + BOOST_STATIC_ASSERT((is_convertible::value)); return this->is_initialized() ? get() : static_cast(boost::forward(v)); } template value_type value_or ( U&& v ) && { - BOOST_STATIC_ASSERT(is_convertible::value); + 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 { - BOOST_STATIC_ASSERT(is_convertible::value); + 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 { - BOOST_STATIC_ASSERT(is_convertible::value); + BOOST_STATIC_ASSERT((is_convertible::value)); return this->is_initialized() ? get() : static_cast(v); } #endif From 9edf2ddac1a0c6f928d021ceb311708c147406f5 Mon Sep 17 00:00:00 2001 From: Andrzej Krzemienski Date: Mon, 16 Jun 2014 14:23:34 +0200 Subject: [PATCH 4/4] docs: fixed requirements in value_or() --- doc/00_optional.qbk | 1 + doc/18_type_requirements.qbk | 8 ++-- doc/20_reference.qbk | 20 ++++++--- .../reference/detailed_semantics.html | 43 ++++++++++++++----- .../tutorial/type_requirements.html | 13 +++--- doc/html/index.html | 2 +- doc/html/optional/reference.html | 2 +- 7 files changed, 60 insertions(+), 29 deletions(-) diff --git a/doc/00_optional.qbk b/doc/00_optional.qbk index 6b41c88..1c8d59b 100644 --- a/doc/00_optional.qbk +++ b/doc/00_optional.qbk @@ -28,6 +28,7 @@ Distributed under the Boost Software License, Version 1.0. [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 bac369a..3a6330e 100644 --- a/doc/20_reference.qbk +++ b/doc/20_reference.qbk @@ -80,7 +80,7 @@ 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__]`` @@ -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& ;`] -[: `template T optional::value_or(U && v) && ;`] * [*Requires:] `T` is __COPY_CONSTRUCTIBLE__ and `U &&` is convertible to `T`. -* [*Returns:] First overload: `bool(*this) ? **this : static_cast(forward(v))`. second overload: `bool(*this) ? std::move(**this) : static_cast(forward(v))`. +* [*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 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 `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 __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 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__ diff --git a/doc/html/boost_optional/reference/detailed_semantics.html b/doc/html/boost_optional/reference/detailed_semantics.html index 21aebff..23c6745 100644 --- a/doc/html/boost_optional/reference/detailed_semantics.html +++ b/doc/html/boost_optional/reference/detailed_semantics.html @@ -1400,11 +1400,6 @@ const& ;

-

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

  • Requires: T @@ -1412,8 +1407,7 @@ 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 @@ -1421,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&.
+

+ space +

+

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

space

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 4495d9b..a96a8b8 100644 --- a/doc/html/index.html +++ b/doc/html/index.html @@ -133,7 +133,7 @@ - +

Last revised: June 14, 2014 at 20:46:55 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 9ec144c..0ab1183 100644 --- a/doc/html/optional/reference.html +++ b/doc/html/optional/reference.html @@ -104,7 +104,7 @@ T&& value() && ; R template<class U> T value_or( U && v ) const& ; R - template<class U> T value_or( U && v ) && ; R + template<class U> T value_or( U && v ) && ; R T const* get_ptr() const ; R T* get_ptr() ; R