diff options
author | Ville Voutilainen <ville.voutilainen@gmail.com> | 2016-08-18 23:33:57 +0300 |
---|---|---|
committer | Ville Voutilainen <ville@gcc.gnu.org> | 2016-08-18 23:33:57 +0300 |
commit | a577f786b60475f827df78fedb98eeb2e83f53e9 (patch) | |
tree | ced23a4340f17d7cbce9d65395db42f6d9c381c8 | |
parent | 197c757cb11681a6ff6df1491ebfde4f5a392627 (diff) | |
download | gcc-a577f786b60475f827df78fedb98eeb2e83f53e9.zip gcc-a577f786b60475f827df78fedb98eeb2e83f53e9.tar.gz gcc-a577f786b60475f827df78fedb98eeb2e83f53e9.tar.bz2 |
Implement the latest proposed resolution of LWG 2756.
* include/std/optional (Optional_base(const _Tp&))
(Optional_base(_Tp&&), using _Base::_Base): Remove.
(optional(nullopt_t)): New.
(optional(_Up&&)): Invoke base directly with in_place
rather than creating a temporary, add default template
argument, change constraints.
(optional(const optional<_Up>&)): Invoke base directly
with in_place, remove unnecessary constraints.
(optional(optional<_Up>&& __t)): Likewise.
(optional(in_place_t, _Args&&...)): New.
(optional(in_place_t, initializer_list<_Up>, _Args&&...)): Likewise.
(operator=(_Up&&)): Add default template argument, change constraints.
(operator=(const optional<_Up>&)): Put is_same first in the
constraints.
(operator=(optional<_Up>&&)): Likewise.
* testsuite/20_util/optional/assignment/5.cc: Add a test to
verify assignment from something that can't be perfect-forwarded.
* testsuite/20_util/optional/cons/value.cc: Add tests to verify
that a nested optional is disengaged when constructed
from a disengaged element type, and to verify that assignments
from an engaged element type engage the optional.
From-SVN: r239593
-rw-r--r-- | libstdc++-v3/ChangeLog | 25 | ||||
-rw-r--r-- | libstdc++-v3/include/std/optional | 102 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/20_util/optional/assignment/5.cc | 11 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/20_util/optional/cons/value.cc | 22 |
4 files changed, 101 insertions, 59 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index a2fa63e..e8eebd39 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,28 @@ +2016-08-18 Ville Voutilainen <ville.voutilainen@gmail.com> + + Implement the latest proposed resolution of LWG 2756. + * include/std/optional (Optional_base(const _Tp&)) + (Optional_base(_Tp&&), using _Base::_Base): Remove. + (optional(nullopt_t)): New. + (optional(_Up&&)): Invoke base directly with in_place + rather than creating a temporary, add default template + argument, change constraints. + (optional(const optional<_Up>&)): Invoke base directly + with in_place, remove unnecessary constraints. + (optional(optional<_Up>&& __t)): Likewise. + (optional(in_place_t, _Args&&...)): New. + (optional(in_place_t, initializer_list<_Up>, _Args&&...)): Likewise. + (operator=(_Up&&)): Add default template argument, change constraints. + (operator=(const optional<_Up>&)): Put is_same first in the + constraints. + (operator=(optional<_Up>&&)): Likewise. + * testsuite/20_util/optional/assignment/5.cc: Add a test to + verify assignment from something that can't be perfect-forwarded. + * testsuite/20_util/optional/cons/value.cc: Add tests to verify + that a nested optional is disengaged when constructed + from a disengaged element type, and to verify that assignments + from an engaged element type engage the optional. + 2016-08-18 Tim Shen <timshen@google.com> Implement <variant> diff --git a/libstdc++-v3/include/std/optional b/libstdc++-v3/include/std/optional index 4c94dff..2ff75ea 100644 --- a/libstdc++-v3/include/std/optional +++ b/libstdc++-v3/include/std/optional @@ -175,12 +175,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : _Optional_base{} { } // Constructors for engaged optionals. - constexpr _Optional_base(const _Tp& __t) - : _M_payload(__t), _M_engaged(true) { } - - constexpr _Optional_base(_Tp&& __t) - : _M_payload(std::move(__t)), _M_engaged(true) { } - template<typename... _Args> constexpr explicit _Optional_base(in_place_t, _Args&&... __args) : _M_payload(std::forward<_Args>(__args)...), _M_engaged(true) { } @@ -317,12 +311,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION constexpr _Optional_base(nullopt_t) noexcept : _Optional_base{} { } - constexpr _Optional_base(const _Tp& __t) - : _M_payload(__t), _M_engaged(true) { } - - constexpr _Optional_base(_Tp&& __t) - : _M_payload(std::move(__t)), _M_engaged(true) { } - template<typename... _Args> constexpr explicit _Optional_base(in_place_t, _Args&&... __args) : _M_payload(std::forward<_Args>(__args)...), _M_engaged(true) { } @@ -478,80 +466,79 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION public: using value_type = _Tp; - // _Optional_base has the responsibility for construction. - using _Base::_Base; - constexpr optional() = default; + + constexpr optional(nullopt_t) noexcept + : _Base(nullopt) { } + // Converting constructors for engaged optionals. - template <typename _Up, + template <typename _Up = _Tp, enable_if_t<__and_< - __not_<is_same<_Tp, _Up>>, + __not_<__is_optional<decay_t<_Up>>>, is_constructible<_Tp, _Up&&>, is_convertible<_Up&&, _Tp> >::value, bool> = true> constexpr optional(_Up&& __t) - : _Base(_Tp(std::forward<_Up>(__t))) { } + : _Base(std::in_place, std::forward<_Up>(__t)) { } - template <typename _Up, + template <typename _Up = _Tp, enable_if_t<__and_< - __not_<is_same<_Tp, _Up>>, - is_constructible<_Tp, _Up&&>, - __not_<is_convertible<_Up&&, _Tp>> - >::value, bool> = false> + __not_<__is_optional<decay_t<_Up>>>, + is_constructible<_Tp, _Up&&>, + __not_<is_convertible<_Up&&, _Tp>> + >::value, bool> = false> explicit constexpr optional(_Up&& __t) - : _Base(_Tp(std::forward<_Up>(__t))) { } + : _Base(std::in_place, std::forward<_Up>(__t)) { } template <typename _Up, enable_if_t<__and_< __not_<is_same<_Tp, _Up>>, - __not_<is_constructible< - _Tp, const optional<_Up>&>>, - __not_<is_convertible< - const optional<_Up>&, _Tp>>, is_constructible<_Tp, const _Up&>, is_convertible<const _Up&, _Tp> >::value, bool> = true> constexpr optional(const optional<_Up>& __t) - : _Base(__t ? optional<_Tp>(*__t) : optional<_Tp>()) { } + : _Base(__t ? _Base(std::in_place, *__t) : _Base()) { } template <typename _Up, enable_if_t<__and_< __not_<is_same<_Tp, _Up>>, - __not_<is_constructible< - _Tp, const optional<_Up>&>>, - __not_<is_convertible< - const optional<_Up>&, _Tp>>, is_constructible<_Tp, const _Up&>, __not_<is_convertible<const _Up&, _Tp>> >::value, bool> = false> explicit constexpr optional(const optional<_Up>& __t) - : _Base(__t ? optional<_Tp>(*__t) : optional<_Tp>()) { } + : _Base(__t ? _Base(std::in_place, *__t) : _Base()) { } template <typename _Up, enable_if_t<__and_< __not_<is_same<_Tp, _Up>>, - __not_<is_constructible< - _Tp, optional<_Up>&&>>, - __not_<is_convertible< - optional<_Up>&&, _Tp>>, is_constructible<_Tp, _Up&&>, is_convertible<_Up&&, _Tp> >::value, bool> = true> constexpr optional(optional<_Up>&& __t) - : _Base(__t ? optional<_Tp>(std::move(*__t)) : optional<_Tp>()) { } + : _Base(__t ? _Base(std::in_place, std::move(*__t)) : _Base()) { } template <typename _Up, enable_if_t<__and_< __not_<is_same<_Tp, _Up>>, - __not_<is_constructible< - _Tp, optional<_Up>&&>>, - __not_<is_convertible< - optional<_Up>&&, _Tp>>, is_constructible<_Tp, _Up&&>, __not_<is_convertible<_Up&&, _Tp>> >::value, bool> = false> explicit constexpr optional(optional<_Up>&& __t) - : _Base(__t ? optional<_Tp>(std::move(*__t)) : optional<_Tp>()) { } + : _Base(__t ? _Base(std::in_place, std::move(*__t)) : _Base()) { } + + template<typename... _Args> + explicit constexpr optional(in_place_t, _Args&&... __args) + : _Base(std::in_place, std::forward<_Args>(__args)...) { } + + template<typename _Up, typename... _Args, + enable_if_t<is_constructible<_Tp, + initializer_list<_Up>&, + _Args&&...>::value, + int>...> + explicit constexpr optional(in_place_t, + initializer_list<_Up> __il, + _Args&&... __args) + : _Base(std::in_place, __il, std::forward<_Args>(__args)...) { } // Assignment operators. optional& @@ -561,13 +548,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return *this; } - template<typename _Up, + template<typename _Up = _Tp, enable_if_t<__and_< - is_constructible<_Tp, _Up>, - is_assignable<_Tp&, _Up>, - __not_<is_same<_Up, nullopt_t>>, - __not_<__is_optional<_Up>>>::value, - bool> = true> + __not_<__is_optional<decay_t<_Up>>>, + is_constructible<_Tp, _Up>, + is_assignable<_Tp&, _Up>>::value, + bool> = true> optional& operator=(_Up&& __u) { @@ -581,10 +567,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Up, enable_if_t<__and_< - is_constructible<_Tp, _Up>, - is_assignable<_Tp&, _Up>, - __not_<is_same<_Tp, _Up>>>::value, - bool> = true> + __not_<is_same<_Tp, _Up>>, + is_constructible<_Tp, _Up>, + is_assignable<_Tp&, _Up>>::value, + bool> = true> optional& operator=(const optional<_Up>& __u) { @@ -604,10 +590,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Up, enable_if_t<__and_< - is_constructible<_Tp, _Up>, - is_assignable<_Tp&, _Up>, - __not_<is_same<_Tp, _Up>>>::value, - bool> = true> + __not_<is_same<_Tp, _Up>>, + is_constructible<_Tp, _Up>, + is_assignable<_Tp&, _Up>>::value, + bool> = true> optional& operator=(optional<_Up>&& __u) { diff --git a/libstdc++-v3/testsuite/20_util/optional/assignment/5.cc b/libstdc++-v3/testsuite/20_util/optional/assignment/5.cc index e450a46..d1a75b4 100644 --- a/libstdc++-v3/testsuite/20_util/optional/assignment/5.cc +++ b/libstdc++-v3/testsuite/20_util/optional/assignment/5.cc @@ -19,6 +19,7 @@ // <http://www.gnu.org/licenses/>. #include <optional> +#include <vector> #include <testsuite_hooks.h> int counter = 0; @@ -61,6 +62,14 @@ int main() o = {}; VERIFY( !o ); } - + { + std::optional<std::vector<int>> ovi{{1, 2, 3}}; + VERIFY(ovi->size() == 3); + VERIFY((*ovi)[0] == 1 && (*ovi)[1] == 2 && (*ovi)[2] == 3); + ovi = {4, 5, 6, 7}; + VERIFY(ovi->size() == 4); + VERIFY((*ovi)[0] == 4 && (*ovi)[1] == 5 && + (*ovi)[2] == 6 && (*ovi)[3] == 7); + } VERIFY( counter == 0 ); } diff --git a/libstdc++-v3/testsuite/20_util/optional/cons/value.cc b/libstdc++-v3/testsuite/20_util/optional/cons/value.cc index 13a6e9c..6a2d871 100644 --- a/libstdc++-v3/testsuite/20_util/optional/cons/value.cc +++ b/libstdc++-v3/testsuite/20_util/optional/cons/value.cc @@ -255,4 +255,26 @@ int main() std::optional<X> ox4; ox4 = oi; } + { + std::optional<std::optional<int>> ooi = std::optional<int>(); + VERIFY(!bool(ooi)); + ooi = std::optional<int>(); + VERIFY(!bool(ooi)); + ooi = std::optional<int>(42); + VERIFY(bool(ooi)); + VERIFY(bool(*ooi)); + std::optional<std::optional<int>> ooi2 = std::optional<short>(); + VERIFY(!bool(ooi2)); + ooi2 = std::optional<short>(); + VERIFY(!bool(ooi2)); + ooi2 = std::optional<short>(6); + VERIFY(bool(ooi2)); + VERIFY(bool(*ooi2)); + std::optional<std::optional<int>> ooi3 = std::optional<int>(42); + VERIFY(bool(ooi3)); + VERIFY(bool(*ooi3)); + std::optional<std::optional<int>> ooi4 = std::optional<short>(6); + VERIFY(bool(ooi4)); + VERIFY(bool(*ooi4)); + } } |