1//===----------------------------------------------------------------------===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8
9// UNSUPPORTED: c++03
10
11// <utility>
12
13// template <class T1, class T2> struct pair
14
15// pair& operator=(pair&& p);
16
17#include <utility>
18#include <memory>
19#include <cassert>
20
21#include "test_macros.h"
22#include "archetypes.h"
23
24struct CountAssign {
25 int copied = 0;
26 int moved = 0;
27 TEST_CONSTEXPR_CXX20 CountAssign() = default;
28 TEST_CONSTEXPR_CXX20 CountAssign& operator=(CountAssign const&) {
29 ++copied;
30 return *this;
31 }
32 TEST_CONSTEXPR_CXX20 CountAssign& operator=(CountAssign&&) {
33 ++moved;
34 return *this;
35 }
36};
37
38struct NotAssignable {
39 NotAssignable& operator=(NotAssignable const&) = delete;
40 NotAssignable& operator=(NotAssignable&&) = delete;
41};
42
43struct MoveAssignable {
44 MoveAssignable& operator=(MoveAssignable const&) = delete;
45 MoveAssignable& operator=(MoveAssignable&&) = default;
46};
47
48struct CopyAssignable {
49 CopyAssignable& operator=(CopyAssignable const&) = default;
50 CopyAssignable& operator=(CopyAssignable&&) = delete;
51};
52
53TEST_CONSTEXPR_CXX20 bool test() {
54 {
55 typedef std::pair<ConstexprTestTypes::MoveOnly, int> P;
56 P p1(3, 4);
57 P p2;
58 p2 = std::move(p1);
59 assert(p2.first.value == 3);
60 assert(p2.second == 4);
61 }
62 {
63 using P = std::pair<int&, int&&>;
64 int x = 42;
65 int y = 101;
66 int x2 = -1;
67 int y2 = 300;
68 P p1(x, std::move(y));
69 P p2(x2, std::move(y2));
70 p1 = std::move(p2);
71 assert(p1.first == x2);
72 assert(p1.second == y2);
73 }
74 {
75 using P = std::pair<int, ConstexprTestTypes::DefaultOnly>;
76 static_assert(!std::is_move_assignable<P>::value, "");
77 }
78 {
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, "");
82 P p;
83 P p2;
84 p = std::move(p2);
85 assert(p.first.moved == 0);
86 assert(p.first.copied == 1);
87 assert(p2.first.moved == 0);
88 assert(p2.first.copied == 0);
89 }
90 {
91 using P = std::pair<CountAssign, ConstexprTestTypes::MoveOnly>;
92 static_assert(std::is_move_assignable<P>::value, "");
93 P p;
94 P p2;
95 p = std::move(p2);
96 assert(p.first.moved == 1);
97 assert(p.first.copied == 0);
98 assert(p2.first.moved == 0);
99 assert(p2.first.copied == 0);
100 }
101 {
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, "");
108 }
109 {
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, "");
114
115 // ... works if it's CopyAssignable
116 using P2 = std::pair<CopyAssignable&, int>;
117 static_assert(std::is_move_assignable<P2>::value, "");
118
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, "");
125
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, "");
132 }
133 return true;
134}
135
136int main(int, char**) {
137 test();
138#if TEST_STD_VER >= 20
139 static_assert(test());
140#endif
141
142 return 0;
143}
144

source code of libcxx/test/std/utilities/utility/pairs/pairs.pair/assign_rv_pair.pass.cpp