aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVille Voutilainen <ville.voutilainen@gmail.com>2016-08-18 23:33:57 +0300
committerVille Voutilainen <ville@gcc.gnu.org>2016-08-18 23:33:57 +0300
commita577f786b60475f827df78fedb98eeb2e83f53e9 (patch)
treeced23a4340f17d7cbce9d65395db42f6d9c381c8
parent197c757cb11681a6ff6df1491ebfde4f5a392627 (diff)
downloadgcc-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/ChangeLog25
-rw-r--r--libstdc++-v3/include/std/optional102
-rw-r--r--libstdc++-v3/testsuite/20_util/optional/assignment/5.cc11
-rw-r--r--libstdc++-v3/testsuite/20_util/optional/cons/value.cc22
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));
+ }
}