32
32
#include < __type_traits/is_implicitly_default_constructible.h>
33
33
#include < __type_traits/is_nothrow_assignable.h>
34
34
#include < __type_traits/is_nothrow_constructible.h>
35
+ #include < __type_traits/is_reference.h>
35
36
#include < __type_traits/is_same.h>
36
37
#include < __type_traits/is_swappable.h>
37
38
#include < __type_traits/is_trivially_relocatable.h>
@@ -80,6 +81,38 @@ struct _LIBCPP_TEMPLATE_VIS pair
80
81
_LIBCPP_HIDE_FROM_ABI pair (pair const &) = default;
81
82
_LIBCPP_HIDE_FROM_ABI pair (pair&&) = default;
82
83
84
+ // When we are requested for pair to be trivially copyable by the ABI macro, we use defaulted members
85
+ // if it is both legal to do it (i.e. no references) and we have a way to actually implement it, which requires
86
+ // the __enable_if__ attribute before C++20.
87
+ #ifdef _LIBCPP_ABI_TRIVIALLY_COPYABLE_PAIR
88
+ // FIXME: This should really just be a static constexpr variable. It's in a struct to avoid gdb printing the value
89
+ // when printing a pair
90
+ struct __has_defaulted_members {
91
+ static const bool value = !is_reference<first_type>::value && !is_reference<second_type>::value;
92
+ };
93
+ # if _LIBCPP_STD_VER >= 20
94
+ _LIBCPP_HIDE_FROM_ABI constexpr pair& operator =(const pair&)
95
+ requires __has_defaulted_members::value
96
+ = default ;
97
+
98
+ _LIBCPP_HIDE_FROM_ABI constexpr pair& operator =(pair&&)
99
+ requires __has_defaulted_members::value
100
+ = default ;
101
+ # elif __has_attribute(__enable_if__)
102
+ _LIBCPP_HIDE_FROM_ABI pair& operator =(const pair&)
103
+ __attribute__ ((__enable_if__(__has_defaulted_members::value, " " ))) = default;
104
+
105
+ _LIBCPP_HIDE_FROM_ABI pair& operator =(pair&&)
106
+ __attribute__ ((__enable_if__(__has_defaulted_members::value, " " ))) = default;
107
+ # else
108
+ # error "_LIBCPP_ABI_TRIVIALLY_COPYABLE_PAIR isn't supported with this compiler"
109
+ # endif
110
+ #else
111
+ struct __has_defaulted_members {
112
+ static const bool value = false ;
113
+ };
114
+ #endif // defined(_LIBCPP_ABI_TRIVIALLY_COPYABLE_PAIR) && __has_attribute(__enable_if__)
115
+
83
116
#ifdef _LIBCPP_CXX03_LANG
84
117
_LIBCPP_HIDE_FROM_ABI pair () : first(), second() {}
85
118
@@ -225,7 +258,8 @@ struct _LIBCPP_TEMPLATE_VIS pair
225
258
typename __make_tuple_indices<sizeof...(_Args2) >::type()) {}
226
259
227
260
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair&
228
- operator =(__conditional_t <is_copy_assignable<first_type>::value && is_copy_assignable<second_type>::value,
261
+ operator =(__conditional_t <!__has_defaulted_members::value && is_copy_assignable<first_type>::value &&
262
+ is_copy_assignable<second_type>::value,
229
263
pair,
230
264
__nat> const & __p) noexcept (is_nothrow_copy_assignable<first_type>::value &&
231
265
is_nothrow_copy_assignable<second_type>::value) {
@@ -234,10 +268,12 @@ struct _LIBCPP_TEMPLATE_VIS pair
234
268
return *this ;
235
269
}
236
270
237
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair& operator =(
238
- __conditional_t <is_move_assignable<first_type>::value && is_move_assignable<second_type>::value, pair, __nat>&&
239
- __p) noexcept (is_nothrow_move_assignable<first_type>::value &&
240
- is_nothrow_move_assignable<second_type>::value) {
271
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair&
272
+ operator =(__conditional_t <!__has_defaulted_members::value && is_move_assignable<first_type>::value &&
273
+ is_move_assignable<second_type>::value,
274
+ pair,
275
+ __nat>&& __p) noexcept (is_nothrow_move_assignable<first_type>::value &&
276
+ is_nothrow_move_assignable<second_type>::value) {
241
277
first = std::forward<first_type>(__p.first );
242
278
second = std::forward<second_type>(__p.second );
243
279
return *this ;
0 commit comments