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