Skip to content

Commit

Permalink
[libc++][ABI BREAK] Make std::pair trivially copyable if its members are
Browse files Browse the repository at this point in the history
  • Loading branch information
philnik777 committed Apr 22, 2024
1 parent c8e5ad4 commit b06140e
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 6 deletions.
40 changes: 34 additions & 6 deletions libcxx/include/__utility/pair.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
@@ -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);

0 comments on commit b06140e

Please sign in to comment.