[libcxx-commits] [libcxx] [libc++][ABI BREAK] Make std::pair trivially copyable if its members are (PR #89652)
via libcxx-commits
libcxx-commits at lists.llvm.org
Mon Apr 22 12:02:46 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-libcxx
Author: Nikolas Klauser (philnik777)
<details>
<summary>Changes</summary>
This makes `std::pair` trivially copyable if its members are and we have a way to do so. We need either C++20 with requires clauses or support for `__attribute__((enable_if))`. Only Clang has support for this attribute, so its effectively clang or C++20.
---
Full diff: https://github.com/llvm/llvm-project/pull/89652.diff
2 Files Affected:
- (modified) libcxx/include/__utility/pair.h (+34-6)
- (added) libcxx/test/libcxx/utilities/utility/pairs/pairs.pair/trivially_copyable.compile.pass.cpp (+32)
``````````diff
diff --git a/libcxx/include/__utility/pair.h b/libcxx/include/__utility/pair.h
index e05250ba05717f..5a9f9f4a3a07f2 100644
--- a/libcxx/include/__utility/pair.h
+++ b/libcxx/include/__utility/pair.h
@@ -141,6 +141,31 @@ struct _LIBCPP_TEMPLATE_VIS pair
_NOEXCEPT_(is_nothrow_copy_constructible<first_type>::value&& is_nothrow_copy_constructible<second_type>::value)
: first(__t1), second(__t2) {}
+ // Make pair trivially copyable if we have a way to do it
+ static const bool __enable_defaulted_assignment_operators =
+ !is_reference<first_type>::value && !is_reference<second_type>::value;
+#if _LIBCPP_STD_VER >= 20
+ static const bool __has_defaulted_members = __enable_defaulted_assignment_operators;
+
+ _LIBCPP_HIDE_FROM_ABI constexpr pair& operator=(const pair&)
+ requires __enable_defaulted_assignment_operators
+ = default;
+
+ _LIBCPP_HIDE_FROM_ABI constexpr pair& operator=(pair&&)
+ requires __enable_defaulted_assignment_operators
+ = default;
+# elif __has_attribute(__enable_if__)
+ static const bool __has_defaulted_members = __enable_defaulted_assignment_operators;
+
+ _LIBCPP_HIDE_FROM_ABI pair& operator=(const pair&)
+ __attribute__((__enable_if__(__enable_defaulted_assignment_operators, ""))) = default;
+
+ _LIBCPP_HIDE_FROM_ABI pair& operator=(pair&&)
+ __attribute__((__enable_if__(__enable_defaulted_assignment_operators, ""))) = default;
+#else
+ static const bool __has_defaulted_members = false;
+# endif // __has_attribute(__enable_if__)
+
template <
# if _LIBCPP_STD_VER >= 23 // http://wg21.link/P1951
class _U1 = _T1,
@@ -221,18 +246,21 @@ struct _LIBCPP_TEMPLATE_VIS pair
typename __make_tuple_indices<sizeof...(_Args2) >::type()) {}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair&
- operator=(__conditional_t< is_copy_assignable<first_type>::value && is_copy_assignable<second_type>::value,
- pair,
- __nat> const& __p)
+ operator=(__conditional_t<
+ !__has_defaulted_members && is_copy_assignable<first_type>::value && is_copy_assignable<second_type>::value,
+ pair,
+ __nat> const& __p)
_NOEXCEPT_(is_nothrow_copy_assignable<first_type>::value&& is_nothrow_copy_assignable<second_type>::value) {
first = __p.first;
second = __p.second;
return *this;
}
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair& operator=(
- __conditional_t< is_move_assignable<first_type>::value && is_move_assignable<second_type>::value, pair, __nat>&&
- __p)
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair&
+ operator=(__conditional_t<
+ !__has_defaulted_members && is_move_assignable<first_type>::value && is_move_assignable<second_type>::value,
+ pair,
+ __nat>&& __p)
_NOEXCEPT_(is_nothrow_move_assignable<first_type>::value&& is_nothrow_move_assignable<second_type>::value) {
first = std::forward<first_type>(__p.first);
second = std::forward<second_type>(__p.second);
diff --git a/libcxx/test/libcxx/utilities/utility/pairs/pairs.pair/trivially_copyable.compile.pass.cpp b/libcxx/test/libcxx/utilities/utility/pairs/pairs.pair/trivially_copyable.compile.pass.cpp
new file mode 100644
index 00000000000000..2f4a77c3112200
--- /dev/null
+++ b/libcxx/test/libcxx/utilities/utility/pairs/pairs.pair/trivially_copyable.compile.pass.cpp
@@ -0,0 +1,32 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: c++20 || clang
+
+#include <type_traits>
+#include <utility>
+
+struct trivially_copyable {
+ int arr[4];
+};
+
+static_assert(std::is_trivially_copyable<std::pair<int, int>>::value, "");
+static_assert(std::is_trivially_copyable<std::pair<int, char>>::value, "");
+static_assert(std::is_trivially_copyable<std::pair<char, int>>::value, "");
+static_assert(std::is_trivially_copyable<std::pair<std::pair<char, char>, int>>::value, "");
+static_assert(std::is_trivially_copyable<std::pair<trivially_copyable, int>>::value, "");
+
+static_assert(!std::is_trivially_copyable<std::pair<int&, int>>::value, "");
+static_assert(!std::is_trivially_copyable<std::pair<int, int&>>::value, "");
+static_assert(!std::is_trivially_copyable<std::pair<int&, int&>>::value, "");
+
+static_assert(std::is_trivially_copy_constructible<std::pair<int, int>>::value);
+static_assert(std::is_trivially_move_constructible<std::pair<int, int>>::value);
+static_assert(std::is_trivially_copy_assignable<std::pair<int, int>>::value);
+static_assert(std::is_trivially_move_assignable<std::pair<int, int>>::value);
+static_assert(std::is_trivially_destructible<std::pair<int, int>>::value);
``````````
</details>
https://github.com/llvm/llvm-project/pull/89652
More information about the libcxx-commits
mailing list