From 0a8a798c3a57ab608b6e88fd9f2aa97e4bc3af8a Mon Sep 17 00:00:00 2001 From: Andrzej Krzemienski Date: Mon, 9 Mar 2015 11:50:10 +0100 Subject: [PATCH] Fixed Trac #10839 --- doc/20_reference.qbk | 15 ++-- doc/91_relnotes.qbk | 3 +- .../reference/detailed_semantics.html | 17 +++-- doc/html/boost_optional/relnotes.html | 7 +- doc/html/index.html | 2 +- doc/html/optional/reference.html | 6 +- include/boost/optional/optional.hpp | 8 +-- test/Jamfile.v2 | 1 + ...onal_test_fail_convert_assign_of_enums.cpp | 1 - test/optional_test_ref_move.cpp | 69 +++++++++++++++++++ 10 files changed, 107 insertions(+), 22 deletions(-) create mode 100644 test/optional_test_ref_move.cpp diff --git a/doc/20_reference.qbk b/doc/20_reference.qbk index 8afc43b..8ca21b8 100644 --- a/doc/20_reference.qbk +++ b/doc/20_reference.qbk @@ -15,11 +15,13 @@ namespace boost { - template + template class optional { - public : + public : + typedef T value_type; + // (If T is of reference type, the parameters and results by reference are by value) optional () noexcept ; ``[link reference_optional_constructor __GO_TO__]`` @@ -1137,9 +1139,8 @@ __SPACE__ * [*Requires:] `T` shall meet requirements of __SGI_EQUALITY_COMPARABLE__. * [*Returns:] If both `x` and `y` are initialized, `(*x == *y)`. If only `x` or `y` is initialized, `false`. If both are uninitialized, `true`. -* [*Notes:] Pointers have shallow relational operators while `optional` has -deep relational operators. Do not use `operator==` directly in generic -code which expect to be given either an `optional` or a pointer; use +* [*Notes:] This definition guarantees that `optional` not containing a value is compared unequal to any `optional` containing any value, and equal to any other `optional` not containing a value. +Pointers have shallow relational operators while `optional` has deep relational operators. Do not use `operator==` directly in generic code which expect to be given either an `optional` or a pointer; use __FUNCTION_EQUAL_POINTEES__ instead * [*Example:] `` @@ -1166,8 +1167,8 @@ __SPACE__ * [*Requires:] Expression `*x < *y` shall be well-formed and its result shall be convertible to `bool`. * [*Returns:] `(!y) ? false : (!x) ? true : *x < *y`. -* [*Notes:] Pointers have shallow relational operators while `optional` has -deep relational operators. Do not use `operator<` directly in generic code +* [*Notes:] This definition guarantees that `optional` not containing a value is ordered as less than any `optional` containing any value, and equivalent to any other `optional` not containing a value. +Pointers have shallow relational operators while `optional` has deep relational operators. Do not use `operator<` directly in generic code which expect to be given either an `optional` or a pointer; use __FUNCTION_LESS_POINTEES__ instead. `T` need not be __SGI_LESS_THAN_COMPARABLE__. Only single `operator<` is required. Other relational operations are defined in terms of this one. If `T`'s `operator<` satisfies the axioms of __SGI_LESS_THAN_COMPARABLE__ (transitivity, antisymmetry and irreflexivity), `optinal` is __SGI_LESS_THAN_COMPARABLE__. * [*Example:] `` diff --git a/doc/91_relnotes.qbk b/doc/91_relnotes.qbk index ea400c7..e75fef7 100644 --- a/doc/91_relnotes.qbk +++ b/doc/91_relnotes.qbk @@ -17,7 +17,8 @@ * Improved the trick that prevents streaming out `optional` without header `optional_io.hpp` by using safe-bool idiom. This addresses [@https://svn.boost.org/trac/boost/ticket/10825 Trac #10825] * IOStream operators are now mentioned in documentation. * Added a way to manually disable move semantics: just define macro `BOOST_OPTIONAL_CONFIG_NO_RVALUE_REFERENCES`. This can be used to work around [@https://svn.boost.org/trac/boost/ticket/10399 Trac #10399] -* It is no longer possible to assign `optional` to `optional` when `U` is not assignable or convertible to `T`. +* It is no longer possible to assign `optional` to `optional` when `U` is not assignable or convertible to `T` ([@https://svn.boost.org/trac/boost/ticket/11087 Trac #11087]). +* Value accessors now work correctly on rvalues of `optional` ([@https://svn.boost.org/trac/boost/ticket/10839 Trac #10839]). [heading Boost Release 1.57] diff --git a/doc/html/boost_optional/reference/detailed_semantics.html b/doc/html/boost_optional/reference/detailed_semantics.html index 8bff973..3f4bd8d 100644 --- a/doc/html/boost_optional/reference/detailed_semantics.html +++ b/doc/html/boost_optional/reference/detailed_semantics.html @@ -2028,9 +2028,13 @@ If both are uninitialized, true.
  • - Notes: Pointers have shallow relational - operators while optional - has deep relational operators. Do not use operator== directly in generic code which expect + Notes: This definition guarantees that + optional<T> + not containing a value is compared unequal to any optional<T> containing any value, and equal to + any other optional<T> + not containing a value. Pointers have shallow relational operators while + optional has deep relational + operators. Do not use operator== directly in generic code which expect to be given either an optional<T> or a pointer; use equal_pointees() instead
  • @@ -2070,8 +2074,11 @@ : *x < *y.
  • - Notes: Pointers have shallow relational - operators while optional + Notes: This definition guarantees that + optional<T> + not containing a value is ordered as less than any optional<T> containing any value, and equivalent + to any other optional<T> not containing a value. Pointers + have shallow relational operators while optional has deep relational operators. Do not use operator< directly in generic code which expect to be given either an optional<T> or a pointer; use less_pointees() instead. T need not be diff --git a/doc/html/boost_optional/relnotes.html b/doc/html/boost_optional/relnotes.html index 1d476e3..3fb495b 100644 --- a/doc/html/boost_optional/relnotes.html +++ b/doc/html/boost_optional/relnotes.html @@ -54,7 +54,12 @@
  • It is no longer possible to assign optional<U> to optional<T> when U - is not assignable or convertible to T. + is not assignable or convertible to T + (Trac #11087). +
  • +
  • + Value accessors now work correctly on rvalues of optional<T&> (Trac + #10839).
  • diff --git a/doc/html/index.html b/doc/html/index.html index 0c30992..0e063f2 100644 --- a/doc/html/index.html +++ b/doc/html/index.html @@ -138,7 +138,7 @@ - +

    Last revised: March 06, 2015 at 18:13:34 GMT

    Last revised: March 09, 2015 at 09:53:44 GMT


    diff --git a/doc/html/optional/reference.html b/doc/html/optional/reference.html index 0b6db6c..21e9ebb 100644 --- a/doc/html/optional/reference.html +++ b/doc/html/optional/reference.html @@ -39,10 +39,12 @@ namespace boost { -template<class T> +template <class T> class optional { - public : +public : + + typedef T value_type; // (If T is of reference type, the parameters and results by reference are by value) diff --git a/include/boost/optional/optional.hpp b/include/boost/optional/optional.hpp index 56f5096..126cf02 100644 --- a/include/boost/optional/optional.hpp +++ b/include/boost/optional/optional.hpp @@ -1020,7 +1020,7 @@ class optional : public optional_detail::optional_base #if (!defined BOOST_NO_CXX11_REF_QUALIFIERS) && (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) reference_const_type operator *() const& { return this->get() ; } reference_type operator *() & { return this->get() ; } - reference_type_of_temporary_wrapper operator *() && { return boost::move(this->get()) ; } + reference_type_of_temporary_wrapper operator *() && { return base::types::move(this->get()) ; } #else reference_const_type operator *() const { return this->get() ; } reference_type operator *() { return this->get() ; } @@ -1046,7 +1046,7 @@ class optional : public optional_detail::optional_base reference_type_of_temporary_wrapper value() && { if (this->is_initialized()) - return boost::move(this->get()) ; + return base::types::move(this->get()) ; else throw_exception(bad_optional_access()); } @@ -1084,7 +1084,7 @@ class optional : public optional_detail::optional_base value_type value_or ( U&& v ) && { if (this->is_initialized()) - return boost::move(get()); + return base::types::move(get()); else return boost::forward(v); } @@ -1123,7 +1123,7 @@ class optional : public optional_detail::optional_base value_type value_or_eval ( F f ) && { if (this->is_initialized()) - return boost::move(get()); + return base::types::move(get()); else return f(); } diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 54535b7..d654545 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -28,6 +28,7 @@ import testing ; [ run optional_test_ref_convert_assign_mutable_int.cpp ] [ run optional_test_ref_convert_assign_const_int.cpp ] [ run optional_test_ref_portable_minimum.cpp ] + [ run optional_test_ref_move.cpp ] [ run optional_test_inplace_factory.cpp ] [ run optional_test_io.cpp ] [ run optional_test_move.cpp ] diff --git a/test/optional_test_fail_convert_assign_of_enums.cpp b/test/optional_test_fail_convert_assign_of_enums.cpp index 184e282..5953850 100644 --- a/test/optional_test_fail_convert_assign_of_enums.cpp +++ b/test/optional_test_fail_convert_assign_of_enums.cpp @@ -9,7 +9,6 @@ // You are welcome to contact the author at: // akrzemi1@gmail.com -#include #include "boost/optional.hpp" // THIS TEST SHOULD FAIL TO COMPILE diff --git a/test/optional_test_ref_move.cpp b/test/optional_test_ref_move.cpp new file mode 100644 index 0000000..78b7bf2 --- /dev/null +++ b/test/optional_test_ref_move.cpp @@ -0,0 +1,69 @@ +// 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/optional.hpp" + +#ifdef __BORLANDC__ +#pragma hdrstop +#endif + +#include +#include "boost/core/addressof.hpp" +#include "boost/core/lightweight_test.hpp" + +using boost::optional; + +std::string global("text"); + +optional make_optional_string_ref() +{ + return optional(global); +} + +std::string& return_global() +{ + return global; +} + +int main() +{ + optional opt; + opt = make_optional_string_ref(); + BOOST_TEST(bool(opt)); + BOOST_TEST(*opt == global); + BOOST_TEST(boost::addressof(*opt) == boost::addressof(global)); + + { + std::string& str = *make_optional_string_ref(); + BOOST_TEST(str == global); + BOOST_TEST(boost::addressof(str) == boost::addressof(global)); + } + + { + std::string& str = make_optional_string_ref().value(); + BOOST_TEST(str == global); + BOOST_TEST(boost::addressof(str) == boost::addressof(global)); + } + + { + std::string& str = make_optional_string_ref().value_or(global); + BOOST_TEST(str == global); + BOOST_TEST(boost::addressof(str) == boost::addressof(global)); + } + + { + std::string& str = make_optional_string_ref().value_or_eval(&return_global); + BOOST_TEST(str == global); + BOOST_TEST(boost::addressof(str) == boost::addressof(global)); + } + + return boost::report_errors(); +}