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, c++11, c++14
10
11// <map>
12
13// class map
14
15// template <class M>
16// pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj); // C++17
17// template <class M>
18// pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj); // C++17
19// template <class M>
20// iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj); // C++17
21// template <class M>
22// iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj); // C++17
23
24#include <map>
25#include <cassert>
26#include <iterator>
27#include <tuple>
28
29#include "test_macros.h"
30
31class Moveable {
32 Moveable(const Moveable&);
33 Moveable& operator=(const Moveable&);
34
35 int int_;
36 double double_;
37
38public:
39 Moveable() : int_(0), double_(0) {}
40 Moveable(int i, double d) : int_(i), double_(d) {}
41 Moveable(Moveable&& x) : int_(x.int_), double_(x.double_) {
42 x.int_ = -1;
43 x.double_ = -1;
44 }
45 Moveable& operator=(Moveable&& x) {
46 int_ = x.int_;
47 x.int_ = -1;
48 double_ = x.double_;
49 x.double_ = -1;
50 return *this;
51 }
52
53 bool operator==(const Moveable& x) const { return int_ == x.int_ && double_ == x.double_; }
54 bool operator<(const Moveable& x) const { return int_ < x.int_ || (int_ == x.int_ && double_ < x.double_); }
55
56 int get() const { return int_; }
57 bool moved() const { return int_ == -1; }
58};
59
60int main(int, char**) {
61 { // pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj);
62 typedef std::map<int, Moveable> M;
63 typedef std::pair<M::iterator, bool> R;
64 M m;
65 R r;
66 for (int i = 0; i < 20; i += 2)
67 m.emplace(args&: i, args: Moveable(i, (double)i));
68 assert(m.size() == 10);
69
70 for (int i = 0; i < 20; i += 2) {
71 Moveable mv(i + 1, i + 1);
72 r = m.insert_or_assign(k: i, obj: std::move(mv));
73 assert(m.size() == 10);
74 assert(!r.second); // was not inserted
75 assert(mv.moved()); // was moved from
76 assert(r.first->first == i); // key
77 assert(r.first->second.get() == i + 1); // value
78 }
79
80 Moveable mv1(5, 5.0);
81 r = m.insert_or_assign(k: -1, obj: std::move(mv1));
82 assert(m.size() == 11);
83 assert(r.second); // was inserted
84 assert(mv1.moved()); // was moved from
85 assert(r.first->first == -1); // key
86 assert(r.first->second.get() == 5); // value
87
88 Moveable mv2(9, 9.0);
89 r = m.insert_or_assign(k: 3, obj: std::move(mv2));
90 assert(m.size() == 12);
91 assert(r.second); // was inserted
92 assert(mv2.moved()); // was moved from
93 assert(r.first->first == 3); // key
94 assert(r.first->second.get() == 9); // value
95
96 Moveable mv3(-1, 5.0);
97 r = m.insert_or_assign(k: 117, obj: std::move(mv3));
98 assert(m.size() == 13);
99 assert(r.second); // was inserted
100 assert(mv3.moved()); // was moved from
101 assert(r.first->first == 117); // key
102 assert(r.first->second.get() == -1); // value
103 }
104 { // pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj);
105 typedef std::map<Moveable, Moveable> M;
106 typedef std::pair<M::iterator, bool> R;
107 M m;
108 R r;
109 for (int i = 0; i < 20; i += 2)
110 m.emplace(args: Moveable(i, (double)i), args: Moveable(i + 1, (double)i + 1));
111 assert(m.size() == 10);
112
113 Moveable mvkey1(2, 2.0);
114 Moveable mv1(4, 4.0);
115 r = m.insert_or_assign(k: std::move(mvkey1), obj: std::move(mv1));
116 assert(m.size() == 10);
117 assert(!r.second); // was not inserted
118 assert(!mvkey1.moved()); // was not moved from
119 assert(mv1.moved()); // was moved from
120 assert(r.first->first == mvkey1); // key
121 assert(r.first->second.get() == 4); // value
122
123 Moveable mvkey2(3, 3.0);
124 Moveable mv2(5, 5.0);
125 r = m.try_emplace(k: std::move(mvkey2), args: std::move(mv2));
126 assert(m.size() == 11);
127 assert(r.second); // was inserted
128 assert(mv2.moved()); // was moved from
129 assert(mvkey2.moved()); // was moved from
130 assert(r.first->first.get() == 3); // key
131 assert(r.first->second.get() == 5); // value
132 }
133 { // iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj);
134 typedef std::map<int, Moveable> M;
135 M m;
136 M::iterator r;
137 for (int i = 0; i < 20; i += 2)
138 m.emplace(args&: i, args: Moveable(i, (double)i));
139 assert(m.size() == 10);
140 M::const_iterator it = m.find(x: 2);
141
142 Moveable mv1(3, 3.0);
143 const int key1 = 2;
144 r = m.insert_or_assign(hint: it, k: key1, obj: std::move(mv1));
145 assert(m.size() == 10);
146 assert(mv1.moved()); // was moved from
147 assert(r->first == 2); // key
148 assert(r->second.get() == 3); // value
149
150 Moveable mv2(5, 5.0);
151 const int key2 = 3;
152 r = m.insert_or_assign(hint: it, k: key2, obj: std::move(mv2));
153 assert(m.size() == 11);
154 assert(mv2.moved()); // was moved from
155 assert(r->first == 3); // key
156 assert(r->second.get() == 5); // value
157
158 // wrong hint: begin()
159 Moveable mv3(7, 7.0);
160 const int key3 = 4;
161 r = m.insert_or_assign(hint: m.begin(), k: key3, obj: std::move(mv3));
162 assert(m.size() == 11);
163 assert(mv3.moved()); // was moved from
164 assert(r->first == 4); // key
165 assert(r->second.get() == 7); // value
166
167 Moveable mv4(9, 9.0);
168 const int key4 = 5;
169 r = m.insert_or_assign(hint: m.begin(), k: key4, obj: std::move(mv4));
170 assert(m.size() == 12);
171 assert(mv4.moved()); // was moved from
172 assert(r->first == 5); // key
173 assert(r->second.get() == 9); // value
174
175 // wrong hint: end()
176 Moveable mv5(11, 11.0);
177 const int key5 = 6;
178 r = m.insert_or_assign(hint: m.end(), k: key5, obj: std::move(mv5));
179 assert(m.size() == 12);
180 assert(mv5.moved()); // was moved from
181 assert(r->first == 6); // key
182 assert(r->second.get() == 11); // value
183
184 Moveable mv6(13, 13.0);
185 const int key6 = 7;
186 r = m.insert_or_assign(hint: m.end(), k: key6, obj: std::move(mv6));
187 assert(m.size() == 13);
188 assert(mv6.moved()); // was moved from
189 assert(r->first == 7); // key
190 assert(r->second.get() == 13); // value
191
192 // wrong hint: third element
193 Moveable mv7(15, 15.0);
194 const int key7 = 8;
195 r = m.insert_or_assign(hint: std::next(x: m.begin(), n: 2), k: key7, obj: std::move(mv7));
196 assert(m.size() == 13);
197 assert(mv7.moved()); // was moved from
198 assert(r->first == 8); // key
199 assert(r->second.get() == 15); // value
200
201 Moveable mv8(17, 17.0);
202 const int key8 = 9;
203 r = m.insert_or_assign(hint: std::next(x: m.begin(), n: 2), k: key8, obj: std::move(mv8));
204 assert(m.size() == 14);
205 assert(mv8.moved()); // was moved from
206 assert(r->first == 9); // key
207 assert(r->second.get() == 17); // value
208 }
209 { // iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj);
210 typedef std::map<Moveable, Moveable> M;
211 M m;
212 M::iterator r;
213 for (int i = 0; i < 20; i += 2)
214 m.emplace(args: Moveable(i, (double)i), args: Moveable(i + 1, (double)i + 1));
215 assert(m.size() == 10);
216 M::const_iterator it = std::next(x: m.cbegin());
217
218 Moveable mvkey1(2, 2.0);
219 Moveable mv1(4, 4.0);
220 r = m.insert_or_assign(hint: it, k: std::move(mvkey1), obj: std::move(mv1));
221 assert(m.size() == 10);
222 assert(mv1.moved()); // was moved from
223 assert(!mvkey1.moved()); // was not moved from
224 assert(r->first == mvkey1); // key
225 assert(r->second.get() == 4); // value
226
227 Moveable mvkey2(3, 3.0);
228 Moveable mv2(5, 5.0);
229 r = m.insert_or_assign(hint: it, k: std::move(mvkey2), obj: std::move(mv2));
230 assert(m.size() == 11);
231 assert(mv2.moved()); // was moved from
232 assert(mvkey2.moved()); // was moved from
233 assert(r->first.get() == 3); // key
234 assert(r->second.get() == 5); // value
235
236 // wrong hint: begin()
237 Moveable mvkey3(6, 6.0);
238 Moveable mv3(8, 8.0);
239 r = m.insert_or_assign(hint: m.begin(), k: std::move(mvkey3), obj: std::move(mv3));
240 assert(m.size() == 11);
241 assert(mv3.moved()); // was moved from
242 assert(!mvkey3.moved()); // was not moved from
243 assert(r->first == mvkey3); // key
244 assert(r->second.get() == 8); // value
245
246 Moveable mvkey4(7, 7.0);
247 Moveable mv4(9, 9.0);
248 r = m.insert_or_assign(hint: m.begin(), k: std::move(mvkey4), obj: std::move(mv4));
249 assert(m.size() == 12);
250 assert(mv4.moved()); // was moved from
251 assert(mvkey4.moved()); // was moved from
252 assert(r->first.get() == 7); // key
253 assert(r->second.get() == 9); // value
254
255 // wrong hint: end()
256 Moveable mvkey5(8, 8.0);
257 Moveable mv5(10, 10.0);
258 r = m.insert_or_assign(hint: m.end(), k: std::move(mvkey5), obj: std::move(mv5));
259 assert(m.size() == 12);
260 assert(mv5.moved()); // was moved from
261 assert(!mvkey5.moved()); // was not moved from
262 assert(r->first == mvkey5); // key
263 assert(r->second.get() == 10); // value
264
265 Moveable mvkey6(9, 9.0);
266 Moveable mv6(11, 11.0);
267 r = m.insert_or_assign(hint: m.end(), k: std::move(mvkey6), obj: std::move(mv6));
268 assert(m.size() == 13);
269 assert(mv6.moved()); // was moved from
270 assert(mvkey6.moved()); // was moved from
271 assert(r->first.get() == 9); // key
272 assert(r->second.get() == 11); // value
273
274 // wrong hint: third element
275 Moveable mvkey7(10, 10.0);
276 Moveable mv7(12, 12.0);
277 r = m.insert_or_assign(hint: std::next(x: m.begin(), n: 2), k: std::move(mvkey7), obj: std::move(mv7));
278 assert(m.size() == 13);
279 assert(mv7.moved()); // was moved from
280 assert(!mvkey7.moved()); // was not moved from
281 assert(r->first == mvkey7); // key
282 assert(r->second.get() == 12); // value
283
284 Moveable mvkey8(11, 11.0);
285 Moveable mv8(13, 13.0);
286 r = m.insert_or_assign(hint: std::next(x: m.begin(), n: 2), k: std::move(mvkey8), obj: std::move(mv8));
287 assert(m.size() == 14);
288 assert(mv8.moved()); // was moved from
289 assert(mvkey8.moved()); // was moved from
290 assert(r->first.get() == 11); // key
291 assert(r->second.get() == 13); // value
292 }
293
294 return 0;
295}
296

source code of libcxx/test/std/containers/associative/map/map.modifiers/insert_or_assign.pass.cpp