[libcxx-commits] [libcxx] [libcxx] makes `expected` trivially assignable when both members are … (PR #74768)
via libcxx-commits
libcxx-commits at lists.llvm.org
Thu Dec 7 13:48:47 PST 2023
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-libcxx
Author: Christopher Di Bella (cjdb)
<details>
<summary>Changes</summary>
…trivially assignable
---
Full diff: https://github.com/llvm/llvm-project/pull/74768.diff
3 Files Affected:
- (modified) libcxx/include/__expected/expected.h (+25)
- (modified) libcxx/test/std/utilities/expected/expected.expected/assign/assign.copy.pass.cpp (+36-1)
- (modified) libcxx/test/std/utilities/expected/expected.expected/assign/assign.move.pass.cpp (+32-1)
``````````diff
diff --git a/libcxx/include/__expected/expected.h b/libcxx/include/__expected/expected.h
index bf16c8f720d26..128369fc1b0a1 100644
--- a/libcxx/include/__expected/expected.h
+++ b/libcxx/include/__expected/expected.h
@@ -38,8 +38,10 @@
#include <__type_traits/is_reference.h>
#include <__type_traits/is_same.h>
#include <__type_traits/is_swappable.h>
+#include <__type_traits/is_trivially_copy_assignable.h>
#include <__type_traits/is_trivially_copy_constructible.h>
#include <__type_traits/is_trivially_destructible.h>
+#include <__type_traits/is_trivially_move_assignable.h>
#include <__type_traits/is_trivially_move_constructible.h>
#include <__type_traits/is_void.h>
#include <__type_traits/lazy.h>
@@ -282,10 +284,27 @@ class expected {
}
}
+ static constexpr bool __is_trivially_move_assignable =
+ is_trivially_move_constructible_v<_Tp> &&
+ is_trivially_move_assignable_v<_Tp> &&
+ is_trivially_move_constructible_v<_Err> &&
+ is_trivially_move_assignable_v<_Err>;
+
+ static constexpr bool __is_trivially_copy_assignable =
+ __is_trivially_move_assignable &&
+ is_trivially_copy_constructible_v<_Tp> &&
+ is_trivially_copy_assignable_v<_Tp> &&
+ is_trivially_copy_constructible_v<_Err> &&
+ is_trivially_copy_assignable_v<_Err>;
+
public:
// [expected.object.assign], assignment
_LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const expected&) = delete;
+ _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const expected& __rhs)
+ requires __is_trivially_copy_assignable
+ = default;
+
_LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const expected& __rhs)
noexcept(is_nothrow_copy_assignable_v<_Tp> &&
is_nothrow_copy_constructible_v<_Tp> &&
@@ -295,6 +314,7 @@ class expected {
is_copy_constructible_v<_Tp> &&
is_copy_assignable_v<_Err> &&
is_copy_constructible_v<_Err> &&
+ !__is_trivially_copy_assignable &&
(is_nothrow_move_constructible_v<_Tp> ||
is_nothrow_move_constructible_v<_Err>))
{
@@ -312,6 +332,10 @@ class expected {
return *this;
}
+ _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(expected&& __rhs)
+ requires __is_trivially_move_assignable
+ = default;
+
_LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(expected&& __rhs)
noexcept(is_nothrow_move_assignable_v<_Tp> &&
is_nothrow_move_constructible_v<_Tp> &&
@@ -321,6 +345,7 @@ class expected {
is_move_assignable_v<_Tp> &&
is_move_constructible_v<_Err> &&
is_move_assignable_v<_Err> &&
+ !__is_trivially_move_assignable &&
(is_nothrow_move_constructible_v<_Tp> ||
is_nothrow_move_constructible_v<_Err>))
{
diff --git a/libcxx/test/std/utilities/expected/expected.expected/assign/assign.copy.pass.cpp b/libcxx/test/std/utilities/expected/expected.expected/assign/assign.copy.pass.cpp
index 03fe888b0a5e7..12ca07a3c1f9a 100644
--- a/libcxx/test/std/utilities/expected/expected.expected/assign/assign.copy.pass.cpp
+++ b/libcxx/test/std/utilities/expected/expected.expected/assign/assign.copy.pass.cpp
@@ -47,6 +47,22 @@ struct NotCopyAssignable {
NotCopyAssignable& operator=(const NotCopyAssignable&) = delete;
};
+struct NotTriviallyCopyConstructible {
+ NotTriviallyCopyConstructible(const NotTriviallyCopyConstructible&);
+ NotTriviallyCopyConstructible(NotTriviallyCopyConstructible&&) = default;
+
+ NotTriviallyCopyConstructible& operator=(const NotTriviallyCopyConstructible&) = default;
+ NotTriviallyCopyConstructible& operator=(NotTriviallyCopyConstructible&&) = default;
+};
+
+struct NotTriviallyCopyAssignable {
+ NotTriviallyCopyAssignable(const NotTriviallyCopyAssignable&) = default;
+ NotTriviallyCopyAssignable(NotTriviallyCopyAssignable&&) = default;
+
+ NotTriviallyCopyAssignable& operator=(const NotTriviallyCopyAssignable&);
+ NotTriviallyCopyAssignable& operator=(NotTriviallyCopyAssignable&&) = default;
+};
+
struct MoveMayThrow {
MoveMayThrow(MoveMayThrow const&) = default;
MoveMayThrow& operator=(const MoveMayThrow&) = default;
@@ -55,7 +71,7 @@ struct MoveMayThrow {
};
// Test constraints
-static_assert(std::is_copy_assignable_v<std::expected<int, int>>);
+static_assert(std::is_trivially_copy_assignable_v<std::expected<int, int>>);
// !is_copy_assignable_v<T>
static_assert(!std::is_copy_assignable_v<std::expected<NotCopyAssignable, int>>);
@@ -78,6 +94,25 @@ static_assert(std::is_copy_assignable_v<std::expected<int, MoveMayThrow>>);
// !is_nothrow_move_constructible_v<T> && !is_nothrow_move_constructible_v<E>
static_assert(!std::is_copy_assignable_v<std::expected<MoveMayThrow, MoveMayThrow>>);
+// !is_trivially_copy_constructible
+static_assert(std::is_copy_assignable_v<std::expected<NotTriviallyCopyConstructible, int>>);
+static_assert(!std::is_trivially_copy_assignable_v<std::expected<NotTriviallyCopyConstructible, int>>);
+static_assert(!std::is_trivially_copy_assignable_v<std::expected<int, NotTriviallyCopyConstructible>>);
+static_assert(
+ !std::is_trivially_copy_assignable_v<std::expected<NotTriviallyCopyConstructible, NotTriviallyCopyConstructible>>);
+
+// !is_trivially_copy_assignable
+static_assert(std::is_copy_assignable_v<std::expected<NotTriviallyCopyAssignable, int>>);
+static_assert(!std::is_trivially_copy_assignable_v<std::expected<NotTriviallyCopyAssignable, int>>);
+static_assert(!std::is_trivially_copy_assignable_v<std::expected<int, NotTriviallyCopyAssignable>>);
+static_assert(
+ !std::is_trivially_copy_assignable_v<std::expected<NotTriviallyCopyAssignable, NotTriviallyCopyAssignable>>);
+
+static_assert(
+ !std::is_trivially_copy_assignable_v<std::expected<NotTriviallyCopyConstructible, NotTriviallyCopyAssignable>>);
+static_assert(
+ !std::is_trivially_copy_assignable_v<std::expected<NotTriviallyCopyAssignable, NotTriviallyCopyConstructible>>);
+
constexpr bool test() {
// If this->has_value() && rhs.has_value() is true, equivalent to val = *rhs.
{
diff --git a/libcxx/test/std/utilities/expected/expected.expected/assign/assign.move.pass.cpp b/libcxx/test/std/utilities/expected/expected.expected/assign/assign.move.pass.cpp
index 8c419afd10729..b08023b9c95ef 100644
--- a/libcxx/test/std/utilities/expected/expected.expected/assign/assign.move.pass.cpp
+++ b/libcxx/test/std/utilities/expected/expected.expected/assign/assign.move.pass.cpp
@@ -50,13 +50,29 @@ struct NotMoveAssignable {
NotMoveAssignable& operator=(NotMoveAssignable&&) = delete;
};
+struct NotTriviallyMoveConstructible {
+ NotTriviallyMoveConstructible(const NotTriviallyMoveConstructible&) = default;
+ NotTriviallyMoveConstructible(NotTriviallyMoveConstructible&&);
+
+ NotTriviallyMoveConstructible& operator=(const NotTriviallyMoveConstructible&) = default;
+ NotTriviallyMoveConstructible& operator=(NotTriviallyMoveConstructible&&) = default;
+};
+
+struct NotTriviallyMoveAssignable {
+ NotTriviallyMoveAssignable(const NotTriviallyMoveAssignable&) = default;
+ NotTriviallyMoveAssignable(NotTriviallyMoveAssignable&&) = default;
+
+ NotTriviallyMoveAssignable& operator=(const NotTriviallyMoveAssignable&) = default;
+ NotTriviallyMoveAssignable& operator=(NotTriviallyMoveAssignable&&);
+};
+
struct MoveCtorMayThrow {
MoveCtorMayThrow(MoveCtorMayThrow&&) noexcept(false) {}
MoveCtorMayThrow& operator=(MoveCtorMayThrow&&) noexcept = default;
};
// Test constraints
-static_assert(std::is_move_assignable_v<std::expected<int, int>>);
+static_assert(std::is_trivially_move_assignable_v<std::expected<int, int>>);
// !is_move_assignable_v<T>
static_assert(!std::is_move_assignable_v<std::expected<NotMoveAssignable, int>>);
@@ -99,6 +115,21 @@ static_assert(!std::is_nothrow_move_assignable_v<std::expected<int, MoveAssignMa
// !is_nothrow_move_constructible_v<E>
static_assert(!std::is_nothrow_move_assignable_v<std::expected<int, MoveCtorMayThrow>>);
+// !is_trivially_move_constructible
+static_assert(std::is_move_assignable_v<std::expected<NotTriviallyMoveConstructible, int>>);
+static_assert(!std::is_trivially_move_assignable_v<std::expected<NotTriviallyMoveConstructible, int>>);
+static_assert(!std::is_trivially_move_assignable_v<std::expected<int, NotTriviallyMoveConstructible>>);
+
+// !is_trivially_move_assignable
+static_assert(std::is_move_assignable_v<std::expected<NotTriviallyMoveAssignable, int>>);
+static_assert(!std::is_trivially_move_assignable_v<std::expected<NotTriviallyMoveAssignable, int>>);
+static_assert(!std::is_trivially_move_assignable_v<std::expected<int, NotTriviallyMoveAssignable>>);
+
+static_assert(
+ !std::is_trivially_move_assignable_v<std::expected<NotTriviallyMoveConstructible, NotTriviallyMoveAssignable>>);
+static_assert(
+ !std::is_trivially_move_assignable_v<std::expected<NotTriviallyMoveAssignable, NotTriviallyMoveConstructible>>);
+
constexpr bool test() {
// If this->has_value() && rhs.has_value() is true, equivalent to val = std::move(*rhs).
{
``````````
</details>
https://github.com/llvm/llvm-project/pull/74768
More information about the libcxx-commits
mailing list