Commit b641f833 by Ville Voutilainen Committed by Ville Voutilainen

re PR libstdc++/77288 (Std::experimental::optional::operator= implementation is broken in gcc 6.1)

	PR libstdc++/77288
	* include/std/optional (__is_optional_impl, __is_optional): Remove.
	(__converts_from_optional, __assigns_from_optional): New.
	(optional(_Up&&)): Use is_same instead of __is_optional.
	(optional(const optional<_Up>&)): Constrain with
	__converts_from_optional.
	(optional(optional<_Up>&&)): Likewise.
	(operator=(_Up&&)): Use is_same instead of __is_optional, check
	is_same and is_scalar.
	(operator=(const optional<_Up>&)): Constrain with
	__converts_from_optional and __assigns_from_optional.
	(operator=(optional<_Up>&&)): Likewise.
	* testsuite/20_util/optional/77288.cc: New.
	* testsuite/20_util/optional/cons/value.cc: Adjust.

From-SVN: r240324
parent 55786785
2016-09-21 Ville Voutilainen <ville.voutilainen@gmail.com>
PR libstdc++/77288
* include/std/optional (__is_optional_impl, __is_optional): Remove.
(__converts_from_optional, __assigns_from_optional): New.
(optional(_Up&&)): Use is_same instead of __is_optional.
(optional(const optional<_Up>&)): Constrain with
__converts_from_optional.
(optional(optional<_Up>&&)): Likewise.
(operator=(_Up&&)): Use is_same instead of __is_optional, check
is_same and is_scalar.
(operator=(const optional<_Up>&)): Constrain with
__converts_from_optional and __assigns_from_optional.
(operator=(optional<_Up>&&)): Likewise.
* testsuite/20_util/optional/77288.cc: New.
* testsuite/20_util/optional/cons/value.cc: Adjust.
2016-09-21 Ville Voutilainen <ville.voutilainen@gmail.com>
Implement LWG 2729 for tuple.
* include/std/tuple (_Tuple_impl(_Tuple_impl&&)):
Suppress conditionally.
......
......@@ -423,19 +423,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Tp>
class optional;
template<typename>
struct __is_optional_impl : false_type
{ };
template<typename _Tp>
struct __is_optional_impl<optional<_Tp>> : true_type
{ };
template<typename _Tp>
struct __is_optional
: public __is_optional_impl<std::remove_cv_t<std::remove_reference_t<_Tp>>>
{ };
template<typename _Tp, typename _Up>
using __converts_from_optional =
__or_<is_constructible<_Tp, const optional<_Up>&>,
is_constructible<_Tp, optional<_Up>&>,
is_constructible<_Tp, const optional<_Up>&&>,
is_constructible<_Tp, optional<_Up>&&>,
is_convertible<const optional<_Up>&, _Tp>,
is_convertible<optional<_Up>&, _Tp>,
is_convertible<const optional<_Up>&&, _Tp>,
is_convertible<optional<_Up>&&, _Tp>>;
template<typename _Tp, typename _Up>
using __assigns_from_optional =
__or_<is_assignable<_Tp&, const optional<_Up>&>,
is_assignable<_Tp&, optional<_Up>&>,
is_assignable<_Tp&, const optional<_Up>&&>,
is_assignable<_Tp&, optional<_Up>&&>>;
/**
* @brief Class template for optional values.
......@@ -474,7 +478,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// Converting constructors for engaged optionals.
template <typename _Up = _Tp,
enable_if_t<__and_<
__not_<__is_optional<decay_t<_Up>>>,
__not_<is_same<optional<_Tp>, decay_t<_Up>>>,
is_constructible<_Tp, _Up&&>,
is_convertible<_Up&&, _Tp>
>::value, bool> = true>
......@@ -483,7 +487,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template <typename _Up = _Tp,
enable_if_t<__and_<
__not_<__is_optional<decay_t<_Up>>>,
__not_<is_same<optional<_Tp>, decay_t<_Up>>>,
is_constructible<_Tp, _Up&&>,
__not_<is_convertible<_Up&&, _Tp>>
>::value, bool> = false>
......@@ -494,7 +498,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
enable_if_t<__and_<
__not_<is_same<_Tp, _Up>>,
is_constructible<_Tp, const _Up&>,
is_convertible<const _Up&, _Tp>
is_convertible<const _Up&, _Tp>,
__not_<__converts_from_optional<_Tp, _Up>>
>::value, bool> = true>
constexpr optional(const optional<_Up>& __t)
: _Base(__t ? _Base(std::in_place, *__t) : _Base()) { }
......@@ -503,7 +508,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
enable_if_t<__and_<
__not_<is_same<_Tp, _Up>>,
is_constructible<_Tp, const _Up&>,
__not_<is_convertible<const _Up&, _Tp>>
__not_<is_convertible<const _Up&, _Tp>>,
__not_<__converts_from_optional<_Tp, _Up>>
>::value, bool> = false>
explicit constexpr optional(const optional<_Up>& __t)
: _Base(__t ? _Base(std::in_place, *__t) : _Base()) { }
......@@ -512,7 +518,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
enable_if_t<__and_<
__not_<is_same<_Tp, _Up>>,
is_constructible<_Tp, _Up&&>,
is_convertible<_Up&&, _Tp>
is_convertible<_Up&&, _Tp>,
__not_<__converts_from_optional<_Tp, _Up>>
>::value, bool> = true>
constexpr optional(optional<_Up>&& __t)
: _Base(__t ? _Base(std::in_place, std::move(*__t)) : _Base()) { }
......@@ -521,7 +528,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
enable_if_t<__and_<
__not_<is_same<_Tp, _Up>>,
is_constructible<_Tp, _Up&&>,
__not_<is_convertible<_Up&&, _Tp>>
__not_<is_convertible<_Up&&, _Tp>>,
__not_<__converts_from_optional<_Tp, _Up>>
>::value, bool> = false>
explicit constexpr optional(optional<_Up>&& __t)
: _Base(__t ? _Base(std::in_place, std::move(*__t)) : _Base()) { }
......@@ -550,8 +558,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Up = _Tp,
enable_if_t<__and_<
__not_<__is_optional<decay_t<_Up>>>,
__not_<is_same<optional<_Tp>, decay_t<_Up>>>,
is_constructible<_Tp, _Up>,
__not_<__and_<is_scalar<_Tp>,
is_same<_Tp, decay_t<_Up>>>>,
is_assignable<_Tp&, _Up>>::value,
bool> = true>
optional&
......@@ -568,8 +578,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Up,
enable_if_t<__and_<
__not_<is_same<_Tp, _Up>>,
is_constructible<_Tp, _Up>,
is_assignable<_Tp&, _Up>>::value,
is_constructible<_Tp, const _Up&>,
is_assignable<_Tp&, _Up>,
__not_<__converts_from_optional<_Tp, _Up>>,
__not_<__assigns_from_optional<_Tp, _Up>>
>::value,
bool> = true>
optional&
operator=(const optional<_Up>& __u)
......@@ -592,7 +605,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
enable_if_t<__and_<
__not_<is_same<_Tp, _Up>>,
is_constructible<_Tp, _Up>,
is_assignable<_Tp&, _Up>>::value,
is_assignable<_Tp&, _Up>,
__not_<__converts_from_optional<_Tp, _Up>>,
__not_<__assigns_from_optional<_Tp, _Up>>
>::value,
bool> = true>
optional&
operator=(optional<_Up>&& __u)
......
......@@ -256,17 +256,21 @@ int main()
ox4 = oi;
}
{
std::optional<int> oi = std::optional<short>();
VERIFY(!bool(oi));
std::optional<std::string> os = std::optional<const char*>();
VERIFY(!bool(os));
std::optional<std::optional<int>> ooi = std::optional<int>();
VERIFY(!bool(ooi));
VERIFY(bool(ooi));
ooi = std::optional<int>();
VERIFY(!bool(ooi));
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));
VERIFY(bool(ooi2));
ooi2 = std::optional<short>();
VERIFY(!bool(ooi2));
VERIFY(bool(ooi2));
ooi2 = std::optional<short>(6);
VERIFY(bool(ooi2));
VERIFY(bool(*ooi2));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment