diff --git a/doc/20_reference.qbk b/doc/20_reference.qbk index 069789a..9b14267 100644 --- a/doc/20_reference.qbk +++ b/doc/20_reference.qbk @@ -72,12 +72,14 @@ T* operator ->() ; ``[link reference_optional_operator_arrow __GO_TO__]`` T const& operator *() const& ; ``[link reference_optional_operator_asterisk __GO_TO__]`` - T& operator *() &; ``[link reference_optional_operator_asterisk __GO_TO__]`` - T operator *() &&; ``[link reference_optional_operator_asterisk_move __GO_TO__]`` + T& operator *() & ; ``[link reference_optional_operator_asterisk __GO_TO__]`` + T operator *() && ; ``[link reference_optional_operator_asterisk_move __GO_TO__]`` + T operator *() const&& ; ``[link reference_optional_operator_asterisk_move __GO_TO__]`` T const& value() const& ; ``[link reference_optional_value __GO_TO__]`` T& value() & ; ``[link reference_optional_value __GO_TO__]`` T value() && ; ``[link reference_optional_value_move __GO_TO__]`` + T value() const&& ; ``[link reference_optional_value_move __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_move __GO_TO__]`` @@ -863,22 +865,24 @@ __SPACE__ [#reference_optional_operator_asterisk_move] [: `T optional::operator*() &&;`] +[: `T optional::operator*() const&&;`] -* [*Requires:] `T` is __MOVE_CONSTRUCTIBLE__ and `*this` is initialized. -* [*Returns:] A move-constructed copy the contained value. -* [*Throws:] Whatever the `T`'s constructor selected for the move throws. -* [*Notes:] The requirement is asserted via `BOOST_ASSERT()`. On compilers that do not support ref-qualifiers on member functions this overload is not present. +* [*Requires:] `*this` contains a value. +* [*Effects:] Equivalent to `return std::move(*val);`. +* [*Remarks:] If `T` is not __MOVE_CONSTRUCTIBLE__, the program is ill-formed. +* [*Notes:] The requirement is asserted via `BOOST_ASSERT()`. On GCC compiler the second overload is not present, as this compiler incorrectly implements binding of references to const prvalues. On compilers that do not support ref-qualifiers on member functions both these overloads are not present. __SPACE__ -[: `T const& optional::operator*() const& ;`] -[: `T & optional::operator*() & ;`] -[: `T & optional::operator*() && ;`] +[: `T & optional::operator*() const& ;`] +[: `T & optional::operator*() & ;`] +[: `T & optional::operator*() && ;`] +[: `T & optional::operator*() const&& ;`] * [*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. +* [*Notes:] The requirement is asserted via `BOOST_ASSERT()`. On GCC compiler the fourth overload is not present, as this compiler incorrectly implements binding of references to const prvalues. On compilers that do not support ref-qualifiers on member functions these four overloads are replaced with the classical two: a `const` and non-`const` member functions. * [*Example:] `` T v ; @@ -897,8 +901,7 @@ __SPACE__ [: `T const& optional::value() const& ;`] [: `T& optional::value() & ;`] -* [*Returns:] A reference to the contained value, if `*this` is initialized. -* [*Throws:] An instance of `bad_optional_access`, if `*this` is not initialized. +* [*Effects:] Equivalent to `return bool(*this) ? *val : throw bad_optional_access();`. * [*Notes:] On compilers that do not support ref-qualifiers on member functions these two overloads are replaced with the classical two: a `const` and non-`const` member functions. * [*Example:] `` @@ -919,12 +922,12 @@ __SPACE__ [#reference_optional_value_move] -[: `T optional::value() && ;`] +[: `T optional::value() && ;`] +[: `T optional::value() const&& ;`] -* [*Requires:] `T` is __MOVE_CONSTRUCTIBLE__. -* [*Returns:] A move-constructed copy of the contained value, if `*this` is initialized. -* [*Throws:] An instance of `bad_optional_access`, if `*this` is not initialized. -* [*Notes:] On compilers that do not support ref-qualifiers on member functions this overload is not present. +* [*Effects:] Equivalent to `return bool(*this) ? std::move(*val) : throw bad_optional_access();`. +* [*Remarks:] If `T` is not __MOVE_CONSTRUCTIBLE__, the program is ill-formed. +* [*Notes:] On GCC compiler the second overload is not present, as this compiler incorrectly implements binding of references to const prvalues. On compilers that do not support ref-qualifiers on member functions both these overloads are not present. __SPACE__ @@ -933,8 +936,8 @@ __SPACE__ [: `template T optional::value_or(U && v) const& ;`] -* [*Requires:] `T` is __COPY_CONSTRUCTIBLE__ and `U &&` is convertible to `T`. -* [*Effects:] `if (*this) return **this; else return std::forward(v);`. +* [*Effects:] Equivalent to `if (*this) return **this; else return std::forward(v);`. +* [*Remarks:] If `T` is not __COPY_CONSTRUCTIBLE__ or `U &&` is not convertible to `T`, the program is ill-formed. * [*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__ @@ -943,8 +946,8 @@ __SPACE__ [: `template T optional::value_or(U && v) && ;`] -* [*Requires:] `T` is __MOVE_CONSTRUCTIBLE__ and `U &&` is convertible to `T`. -* [*Effects:] `if (*this) return std::move(**this); else return std::forward(v);`. +* [*Effects:] Equivalent to `if (*this) return std::move(**this); else return std::forward(v);`. +* [*Remarks:] If `T` is not __MOVE_CONSTRUCTIBLE__ or `U &&` is not convertible to `T`, the program is ill-formed. * [*Notes:] On compilers that do not support ref-qualifiers on member functions this overload is not present. __SPACE__ diff --git a/doc/html/boost_optional/reference/detailed_semantics.html b/doc/html/boost_optional/reference/detailed_semantics.html index 8f83d55..e41bb4e 100644 --- a/doc/html/boost_optional/reference/detailed_semantics.html +++ b/doc/html/boost_optional/reference/detailed_semantics.html @@ -1337,33 +1337,37 @@ T optional<T (not a ref)>::operator*() &&;

+

+ T optional<T + (not a ref)>::operator*() const&&; +

  • - Requires: T - is MoveConstructible - and *this - is initialized. + Requires: *this contains a value.
  • - Returns: A move-constructed copy the - contained value. + Effects: Equivalent to return std::move(*val);.
  • - Throws: Whatever the T's - constructor selected for the move throws. + Remarks: If T + is not MoveConstructible, + the program is ill-formed.
  • Notes: The requirement is asserted via BOOST_ASSERT(). - On compilers that do not support ref-qualifiers on member functions this - overload is not present. + On GCC compiler the second overload is not present, as this compiler + incorrectly implements binding of references to const prvalues. On compilers + that do not support ref-qualifiers on member functions both these overloads + are not present.

space

- T const& optional<T&>::operator*() const& ; + T & + optional<T&>::operator*() const& ;

T & @@ -1373,6 +1377,11 @@ T & optional<T&>::operator*() && ;

+

+ T & + optional<T&>::operator*() const&& + ; +

  • Requires: *this is initialized @@ -1387,9 +1396,11 @@
  • 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. + On GCC compiler the fourth overload is not present, as this compiler + incorrectly implements binding of references to const prvalues. On compilers + that do not support ref-qualifiers on member functions these four overloads + are replaced with the classical two: a const + and non-const member functions.
  • Example: @@ -1415,13 +1426,7 @@

  • - Returns: A reference to the contained - value, if *this - is initialized. -
  • -
  • - Throws: An instance of bad_optional_access, if *this - is not initialized. + Effects: Equivalent to return bool(*this) ? *val : throw bad_optional_access();.
  • Notes: On compilers that do not support @@ -1452,22 +1457,24 @@ T optional<T>::value() && ;

+

+ T optional<T>::value() const&& ; +

  • - Requires: T - is MoveConstructible. + Effects: Equivalent to return bool(*this) ? std::move(*val) : throw + bad_optional_access();.
  • - Returns: A move-constructed copy of - the contained value, if *this is initialized. + Remarks: If T + is not MoveConstructible, + the program is ill-formed.
  • - Throws: An instance of bad_optional_access, if *this - is not initialized. -
  • -
  • - Notes: On compilers that do not support - ref-qualifiers on member functions this overload is not present. + Notes: On GCC compiler the second overload + is not present, as this compiler incorrectly implements binding of references + to const prvalues. On compilers that do not support ref-qualifiers on + member functions both these overloads are not present.

@@ -1481,13 +1488,14 @@

  • - Requires: T - is CopyConstructible and U && - is convertible to T. + Effects: Equivalent to if (*this) return **this; else return + std::forward<U>(v);.
  • - Effects: if - (*this) return **this; else return std::forward<U>(v);. + Remarks: If T + is not CopyConstructible or U && + is not convertible to T, + the program is ill-formed.
  • Notes: On compilers that do not support @@ -1507,15 +1515,14 @@

  • - Requires: T - is MoveConstructible - and U && - is convertible to T. + Effects: Equivalent to if (*this) return std::move(**this); else return std::forward<U>(v);.
  • - Effects: if - (*this) return std::move(**this); else return - std::forward<U>(v);. + Remarks: If T + is not MoveConstructible + or U && + is not convertible to T, + the program is ill-formed.
  • Notes: On compilers that do not support diff --git a/doc/html/index.html b/doc/html/index.html index c840a4f..fc616b7 100644 --- a/doc/html/index.html +++ b/doc/html/index.html @@ -133,7 +133,7 @@
- +

Last revised: June 20, 2014 at 20:25:26 GMT

Last revised: June 27, 2014 at 22:17:04 GMT


diff --git a/doc/html/optional/reference.html b/doc/html/optional/reference.html index dc2dd88..3ce1cb9 100644 --- a/doc/html/optional/reference.html +++ b/doc/html/optional/reference.html @@ -96,12 +96,14 @@ T* operator ->() ; R T const& operator *() const& ; R - T& operator *() &; R - T operator *() &&; R + T& operator *() & ; R + T operator *() && ; R + T operator *() const&& ; R T const& value() const& ; R T& value() & ; R T value() && ; R + T value() const&& ; R template<class U> T value_or( U && v ) const& ; R template<class U> T value_or( U && v ) && ; R diff --git a/include/boost/optional/bad_optional_access.hpp b/include/boost/optional/bad_optional_access.hpp index 95abf3a..bf5cae0 100644 --- a/include/boost/optional/bad_optional_access.hpp +++ b/include/boost/optional/bad_optional_access.hpp @@ -19,8 +19,9 @@ namespace boost { class bad_optional_access : public std::logic_error { public: - explicit bad_optional_access(const std::string& what_arg) : std::logic_error(what_arg) {} - explicit bad_optional_access(const char* what_arg) : std::logic_error(what_arg) {} + bad_optional_access() + : std::logic_error("Attempted to access the value of an uninitialized optional object.") + {} }; } // namespace boost diff --git a/include/boost/optional/optional.hpp b/include/boost/optional/optional.hpp index 5d08606..8d6971f 100644 --- a/include/boost/optional/optional.hpp +++ b/include/boost/optional/optional.hpp @@ -1005,13 +1005,16 @@ class optional : public optional_detail::optional_base // the behaviour is UNDEFINED // No-throw #ifndef BOOST_NO_CXX11_REF_QUALIFIERS - reference_const_type operator *() const& { return this->get() ; } - reference_type operator *() & { return this->get() ; } - value_type operator *() && { return boost::move(this->get()) ; } + reference_const_type operator *() const& { return this->get() ; } + reference_type operator *() & { return this->get() ; } + value_type operator *() && { return boost::move(this->get()) ; } +#ifdef BOOST_CLANG + value_type operator *() const&& { return boost::move(this->get()) ; } +#endif #else reference_const_type operator *() const { return this->get() ; } reference_type operator *() { return this->get() ; } -#endif +#endif // !defined BOOST_NO_CXX11_REF_QUALIFIERS #ifndef BOOST_NO_CXX11_REF_QUALIFIERS reference_const_type value() const& @@ -1019,7 +1022,7 @@ class optional : public optional_detail::optional_base if (this->is_initialized()) return this->get() ; else - throw_exception(bad_optional_access("Attempted to access the value of an uninitialized optional object.")); + throw_exception(bad_optional_access()); } reference_type value() & @@ -1027,7 +1030,7 @@ class optional : public optional_detail::optional_base if (this->is_initialized()) return this->get() ; else - throw_exception(bad_optional_access("Attempted to access the value of an uninitialized optional object.")); + throw_exception(bad_optional_access()); } value_type value() && @@ -1035,15 +1038,25 @@ class optional : public optional_detail::optional_base if (this->is_initialized()) return boost::move(this->get()) ; else - throw_exception(bad_optional_access("Attempted to access the value of an uninitialized optional object.")); + throw_exception(bad_optional_access()); } +#ifdef BOOST_CLANG + value_type value() const&& + { + if (this->is_initialized()) + return boost::move(this->get()) ; + else + throw_exception(bad_optional_access()); + } +#endif + #else reference_const_type value() const { if (this->is_initialized()) return this->get() ; else - throw_exception(bad_optional_access("Attempted to access the value of an uninitialized optional object.")); + throw_exception(bad_optional_access()); } reference_type value() @@ -1051,7 +1064,7 @@ class optional : public optional_detail::optional_base if (this->is_initialized()) return this->get() ; else - throw_exception(bad_optional_access("Attempted to access the value of an uninitialized optional object.")); + throw_exception(bad_optional_access()); } #endif diff --git a/test/optional_test.cpp b/test/optional_test.cpp index ba64269..e34ce7e 100644 --- a/test/optional_test.cpp +++ b/test/optional_test.cpp @@ -291,7 +291,7 @@ void test_uninitialized_access( T const* ) { // This should throw because 'def' is uninitialized T const& n = def.get() ; - unused_variable(n); + boost::ignore_unused(n); passed = true ; } catch (...) {} @@ -302,7 +302,7 @@ void test_uninitialized_access( T const* ) { // This should throw because 'def' is uninitialized T const& n = *def ; - unused_variable(n); + boost::ignore_unused(n); passed = true ; } catch (...) {} @@ -312,7 +312,7 @@ void test_uninitialized_access( T const* ) try { T v(5) ; - unused_variable(v); + boost::ignore_unused(v); // This should throw because 'def' is uninitialized *def = v ; passed = true ; @@ -325,7 +325,7 @@ void test_uninitialized_access( T const* ) { // This should throw because 'def' is uninitialized T v = *(def.operator->()) ; - unused_variable(v); + boost::ignore_unused(v); passed = true ; } catch (...) {} diff --git a/test/optional_test_common.cpp b/test/optional_test_common.cpp index ba04a6a..532b74e 100644 --- a/test/optional_test_common.cpp +++ b/test/optional_test_common.cpp @@ -1,4 +1,5 @@ // Copyright (C) 2003, Fernando Luis Cacciola Carballal. +// 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 @@ -9,6 +10,8 @@ // You are welcome to contact the author at: // fernando_cacciola@hotmail.com // +#include + #ifdef ENABLE_TRACE #define TRACE(msg) std::cout << msg << std::endl ; #else @@ -37,7 +40,6 @@ void assertion_failed (char const * expr, char const * func, char const * file, using boost::optional ; -template inline void unused_variable ( const T& ) {} #ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP using boost::swap ; diff --git a/test/optional_test_value_access.cpp b/test/optional_test_value_access.cpp index c83326a..63d65b9 100644 --- a/test/optional_test_value_access.cpp +++ b/test/optional_test_value_access.cpp @@ -85,7 +85,7 @@ void test_function_value_for() { T& v = o0.value(); BOOST_CHECK(false); - unused_variable(v); + boost::ignore_unused(v); } catch(boost::bad_optional_access const&) { @@ -194,6 +194,19 @@ void test_function_value_or_eval() } } +const optional makeConstOptVal() +{ + return std::string("something"); +} + +void test_const_move() +{ + std::string s5 = *makeConstOptVal(); + std::string s6 = makeConstOptVal().value(); + boost::ignore_unused(s5); + boost::ignore_unused(s6); +} + #ifndef BOOST_NO_CXX11_REF_QUALIFIERS struct MoveOnly @@ -223,13 +236,13 @@ void test_move_only_getters() MoveOnly m2 = makeMoveOnly().value(); MoveOnly m3 = makeMoveOnly().value_or(MoveOnly(1)); MoveOnly m4 = makeMoveOnly().value_or_eval(moveOnlyDefault); - unused_variable(m1); - unused_variable(m2); - unused_variable(m3); - unused_variable(m4); + boost::ignore_unused(m1); + boost::ignore_unused(m2); + boost::ignore_unused(m3); + boost::ignore_unused(m4); } -#endif +#endif // !defined BOOST_NO_CXX11_REF_QUALIFIERS int test_main( int, char* [] ) { @@ -238,6 +251,7 @@ int test_main( int, char* [] ) test_function_value(); test_function_value_or(); test_function_value_or_eval(); + test_const_move(); } catch ( ... ) {