From 18b8c4bb18ad18d77233d1020e1430e14cbdceb2 Mon Sep 17 00:00:00 2001
From: Andrzej Krzemienski
Date: Sat, 28 Jun 2014 00:31:36 +0200
Subject: [PATCH] Catching up with N4078
---
doc/20_reference.qbk | 45 ++++-----
.../reference/detailed_semantics.html | 93 ++++++++++---------
doc/html/index.html | 2 +-
doc/html/optional/reference.html | 6 +-
.../boost/optional/bad_optional_access.hpp | 5 +-
include/boost/optional/optional.hpp | 31 +++++--
test/optional_test.cpp | 8 +-
test/optional_test_common.cpp | 4 +-
test/optional_test_value_access.cpp | 26 ++++--
9 files changed, 131 insertions(+), 89 deletions(-)
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.
- 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 ->() ;
T const& operator *() const& ;
- T& operator *() &;
- T operator *() &&;
+ T& operator *() & ;
+ T operator *() && ;
+ T operator *() const&& ;
T const& value() const& ;
T& value() & ;
T value() && ;
+ T value() const&& ;
template<class U> T value_or( U && v ) const& ;
template<class U> T value_or( U && v ) && ;
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 ( ... )
{