1 //===----------------------------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
13 // template <class T1, class T2> struct pair
15 // pair& operator=(pair&& p);
21 #include "test_macros.h"
22 #include "archetypes.h"
27 TEST_CONSTEXPR_CXX20
CountAssign() = default;
28 TEST_CONSTEXPR_CXX20 CountAssign
& operator=(CountAssign
const&) {
32 TEST_CONSTEXPR_CXX20 CountAssign
& operator=(CountAssign
&&) {
38 struct NotAssignable
{
39 NotAssignable
& operator=(NotAssignable
const&) = delete;
40 NotAssignable
& operator=(NotAssignable
&&) = delete;
43 struct MoveAssignable
{
44 MoveAssignable
& operator=(MoveAssignable
const&) = delete;
45 MoveAssignable
& operator=(MoveAssignable
&&) = default;
48 struct CopyAssignable
{
49 CopyAssignable
& operator=(CopyAssignable
const&) = default;
50 CopyAssignable
& operator=(CopyAssignable
&&) = delete;
53 TEST_CONSTEXPR_CXX20
bool test() {
55 typedef std::pair
<ConstexprTestTypes::MoveOnly
, int> P
;
59 assert(p2
.first
.value
== 3);
60 assert(p2
.second
== 4);
63 using P
= std::pair
<int&, int&&>;
68 P
p1(x
, std::move(y
));
69 P
p2(x2
, std::move(y2
));
71 assert(p1
.first
== x2
);
72 assert(p1
.second
== y2
);
75 using P
= std::pair
<int, ConstexprTestTypes::DefaultOnly
>;
76 static_assert(!std::is_move_assignable
<P
>::value
, "");
79 // The move decays to the copy constructor
80 using P
= std::pair
<CountAssign
, ConstexprTestTypes::CopyOnly
>;
81 static_assert(std::is_move_assignable
<P
>::value
, "");
85 assert(p
.first
.moved
== 0);
86 assert(p
.first
.copied
== 1);
87 assert(p2
.first
.moved
== 0);
88 assert(p2
.first
.copied
== 0);
91 using P
= std::pair
<CountAssign
, ConstexprTestTypes::MoveOnly
>;
92 static_assert(std::is_move_assignable
<P
>::value
, "");
96 assert(p
.first
.moved
== 1);
97 assert(p
.first
.copied
== 0);
98 assert(p2
.first
.moved
== 0);
99 assert(p2
.first
.copied
== 0);
102 using P1
= std::pair
<int, NotAssignable
>;
103 using P2
= std::pair
<NotAssignable
, int>;
104 using P3
= std::pair
<NotAssignable
, NotAssignable
>;
105 static_assert(!std::is_move_assignable
<P1
>::value
, "");
106 static_assert(!std::is_move_assignable
<P2
>::value
, "");
107 static_assert(!std::is_move_assignable
<P3
>::value
, "");
110 // We assign through the reference and don't move out of the incoming ref,
111 // so this doesn't work (but would if the type were CopyAssignable).
112 using P1
= std::pair
<MoveAssignable
&, int>;
113 static_assert(!std::is_move_assignable
<P1
>::value
, "");
115 // ... works if it's CopyAssignable
116 using P2
= std::pair
<CopyAssignable
&, int>;
117 static_assert(std::is_move_assignable
<P2
>::value
, "");
119 // For rvalue-references, we can move-assign if the type is MoveAssignable
120 // or CopyAssignable (since in the worst case the move will decay into a copy).
121 using P3
= std::pair
<MoveAssignable
&&, int>;
122 using P4
= std::pair
<CopyAssignable
&&, int>;
123 static_assert(std::is_move_assignable
<P3
>::value
, "");
124 static_assert(std::is_move_assignable
<P4
>::value
, "");
126 // In all cases, we can't move-assign if the types are not assignable,
127 // since we assign through the reference.
128 using P5
= std::pair
<NotAssignable
&, int>;
129 using P6
= std::pair
<NotAssignable
&&, int>;
130 static_assert(!std::is_move_assignable
<P5
>::value
, "");
131 static_assert(!std::is_move_assignable
<P6
>::value
, "");
136 int main(int, char**) {
138 #if TEST_STD_VER >= 20
139 static_assert(test());