+2018-11-19 Ville Voutilainen <ville.voutilainen@gmail.com>
+
+ PR libstdc++/87855
+ Also implement P0602R4 (variant and optional
+ should propagate copy/move triviality) for std::optional.
+ * include/std/optional (_Optional_payload): Change
+ the main constraints to check constructibility in
+ addition to assignability.
+ (operator=): Make constexpr.
+ (_M_reset): Likewise.
+ (_M_construct): Likewise.
+ (operator->): Likewise.
+ * testsuite/20_util/optional/assignment/8.cc: Adjust.
+ * testsuite/20_util/optional/assignment/9.cc: New.
+
2018-11-19 Jonathan Wakely <jwakely@redhat.com>
PR libstdc++/88084 - Implement LWG 2777
template <typename _Tp,
bool /*_HasTrivialDestructor*/ =
is_trivially_destructible_v<_Tp>,
- bool /*_HasTrivialCopyAssignment*/ =
- is_trivially_copy_assignable_v<_Tp>,
- bool /*_HasTrivialMoveAssignment*/ =
- is_trivially_move_assignable_v<_Tp>>
+ bool /*_HasTrivialCopy */ =
+ is_trivially_copy_assignable_v<_Tp>
+ && is_trivially_copy_constructible_v<_Tp>,
+ bool /*_HasTrivialMove */ =
+ is_trivially_move_assignable_v<_Tp>
+ && is_trivially_move_constructible_v<_Tp>>
struct _Optional_payload
{
constexpr _Optional_payload() noexcept : _M_empty() { }
this->_M_construct(std::move(__other._M_payload));
}
+ constexpr
_Optional_payload&
operator=(const _Optional_payload& __other)
{
return *this;
}
+ constexpr
_Optional_payload&
operator=(_Optional_payload&& __other)
noexcept(__and_v<is_nothrow_move_constructible<_Tp>,
{ return this->_M_payload; }
// _M_reset is a 'safe' operation with no precondition.
+ constexpr
void
_M_reset() noexcept
{
_Optional_payload(const _Optional_payload&) = default;
_Optional_payload(_Optional_payload&&) = default;
+ constexpr
_Optional_payload&
operator=(const _Optional_payload& __other)
{
{ return this->_M_payload; }
// _M_reset is a 'safe' operation with no precondition.
+ constexpr
void
_M_reset() noexcept
{
_Optional_payload&
operator=(const _Optional_payload& __other) = default;
+ constexpr
_Optional_payload&
operator=(_Optional_payload&& __other)
noexcept(__and_v<is_nothrow_move_constructible<_Tp>,
{ return this->_M_payload; }
// _M_reset is a 'safe' operation with no precondition.
+ constexpr
void
_M_reset() noexcept
{
_Optional_payload(const _Optional_payload&) = default;
_Optional_payload(_Optional_payload&&) = default;
+ constexpr
_Optional_payload&
operator=(const _Optional_payload& __other)
{
return *this;
}
+ constexpr
_Optional_payload&
operator=(_Optional_payload&& __other)
noexcept(__and_v<is_nothrow_move_constructible<_Tp>,
bool _M_engaged;
template<typename... _Args>
+ constexpr
void
_M_construct(_Args&&... __args)
noexcept(is_nothrow_constructible_v<_Stored_type, _Args...>)
{ return this->_M_payload; }
// _M_reset is a 'safe' operation with no precondition.
+ constexpr
void
_M_reset() noexcept
{
}
// _M_reset is a 'safe' operation with no precondition.
+ constexpr
void
_M_reset() noexcept
{
operator->() const
{ return std::__addressof(this->_M_get()); }
+ constexpr
_Tp*
operator->()
{ return std::__addressof(this->_M_get()); }
};
static_assert(std::is_trivially_move_assignable_v<S2>);
+struct S3 {
+ S3(const S3&);
+ S3& operator=(const S3&) = default;
+};
+static_assert(std::is_trivially_copy_assignable_v<S3>);
+static_assert(std::is_copy_assignable_v<S3>);
+static_assert(!std::is_trivially_copy_assignable_v<std::optional<S3>>);
+static_assert(std::is_copy_assignable_v<std::optional<S3>>);
+
+struct S4 {
+ S4(S4&&);
+ S4& operator=(S4&&) = default;
+};
+static_assert(std::is_trivially_move_assignable_v<S4>);
+static_assert(std::is_move_assignable_v<S4>);
+static_assert(!std::is_trivially_move_assignable_v<std::optional<S4>>);
+static_assert(std::is_move_assignable_v<std::optional<S4>>);
+
union U2 {
char dummy;
S2 s;
--- /dev/null
+// { dg-options "-std=gnu++17" }
+// { dg-do compile { target c++17 } }
+
+// Copyright (C) 2018 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <optional>
+
+constexpr bool f()
+{
+ std::optional<int> o1{42};
+ std::optional<int> o2;
+ o2 = o1;
+ return (o1 == o2);
+}
+
+constexpr bool f2()
+{
+ std::optional<int> o1{42};
+ std::optional<int> o2;
+ std::optional<int> o3;
+ o2 = o1;
+ o3 = std::move(o2);
+ return (o1 == o3);
+}
+
+void g()
+{
+ constexpr bool b = f();
+ static_assert(b);
+ constexpr bool b2 = f2();
+ static_assert(b2);
+}
+
+struct NonTrivialButConstexpr
+{
+ int dummy;
+ NonTrivialButConstexpr() = default;
+ constexpr NonTrivialButConstexpr(int val) : dummy(val) {}
+ NonTrivialButConstexpr(const NonTrivialButConstexpr&) = default;
+ NonTrivialButConstexpr(NonTrivialButConstexpr&&) = default;
+ constexpr NonTrivialButConstexpr&
+ operator=(const NonTrivialButConstexpr& other)
+ {
+ dummy = other.dummy;
+ return *this;
+ }
+ constexpr NonTrivialButConstexpr&
+ operator=(NonTrivialButConstexpr&& other)
+ {
+ dummy = other.dummy;
+ return *this;
+ }
+};
+
+constexpr bool f3()
+{
+ std::optional<NonTrivialButConstexpr> d1, d2;
+ d1 = d2;
+ std::optional<NonTrivialButConstexpr> o1{42};
+ std::optional<NonTrivialButConstexpr> o2{22};
+ o2 = o1;
+ return ((*o1).dummy == (*o2).dummy && o1->dummy == o2->dummy);
+}
+
+constexpr bool f4()
+{
+ std::optional<NonTrivialButConstexpr> d1, d2;
+ d1 = std::move(d2);
+ std::optional<NonTrivialButConstexpr> o1{42};
+ std::optional<NonTrivialButConstexpr> o2{22};
+ std::optional<NonTrivialButConstexpr> o3{33};
+ o2 = o1;
+ o3 = std::move(o2);
+ return ((*o1).dummy == (*o3).dummy && o1->dummy == o3->dummy);
+}
+
+void g2()
+{
+ constexpr bool b = f3();
+ static_assert(b);
+ constexpr bool b2 = f4();
+ static_assert(b2);
+}