diff --git a/include/boost/optional/optional.hpp b/include/boost/optional/optional.hpp index 4a8dc5e..b3319b0 100644 --- a/include/boost/optional/optional.hpp +++ b/include/boost/optional/optional.hpp @@ -958,9 +958,40 @@ class optional : public optional_detail::optional_base // Returns a reference to the value if this is initialized, otherwise, // 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() ; } + rval_reference_type operator *() && { return boost::move(this->get()) ; } +#else reference_const_type operator *() const { return this->get() ; } reference_type operator *() { return this->get() ; } - +#endif + +#ifndef BOOST_NO_CXX11_REF_QUALIFIERS + 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.")); + } + + reference_type value() & + { + if (this->is_initialized()) + return this->get() ; + else + throw_exception(bad_optional_access("Attempted to access the value of an uninitialized optional object.")); + } + + rval_reference_type value() && + { + 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.")); + } +#else reference_const_type value() const { if (this->is_initialized()) @@ -976,10 +1007,20 @@ class optional : public optional_detail::optional_base else throw_exception(bad_optional_access("Attempted to access the value of an uninitialized optional object.")); } +#endif -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +#ifndef BOOST_NO_CXX11_REF_QUALIFIERS template - value_type value_or ( U&& v ) const { return this->is_initialized() ? get() : static_cast(boost::forward(v)); } + value_type value_or ( U&& v ) const& + { 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)); } +#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)); } #else template value_type value_or ( U const& v ) const { return this->is_initialized() ? get() : static_cast(v); } diff --git a/test/optional_test_common.cpp b/test/optional_test_common.cpp index 385651e..ba04a6a 100644 --- a/test/optional_test_common.cpp +++ b/test/optional_test_common.cpp @@ -37,7 +37,7 @@ void assertion_failed (char const * expr, char const * func, char const * file, using boost::optional ; -template inline void unused_variable ( T ) {} +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 bd3ea9e..506278f 100644 --- a/test/optional_test_value_access.cpp +++ b/test/optional_test_value_access.cpp @@ -128,6 +128,35 @@ void test_function_value_or() BOOST_CHECK(FatToIntConverter::conversions == 1); } +#ifndef BOOST_NO_CXX11_REF_QUALIFIERS +struct MoveOnly +{ + explicit MoveOnly(int){} + MoveOnly(MoveOnly &&){} + void operator=(MoveOnly &&); +private: + MoveOnly(MoveOnly const&); + void operator=(MoveOnly const&); +}; + +optional makeMoveOnly() +{ + return MoveOnly(1); +} + +// compile-time test +void test_move_only_getters() +{ + MoveOnly m1 = *makeMoveOnly(); + MoveOnly m2 = makeMoveOnly().value(); + MoveOnly m3 = makeMoveOnly().value_or(MoveOnly(1)); + unused_variable(m1); + unused_variable(m2); + unused_variable(m3); +} + +#endif + int test_main( int, char* [] ) { try