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:
Moveable()38     Moveable() : int_(0), double_(0) {}
Moveable(int i,double d)39     Moveable(int i, double d) : int_(i), double_(d) {}
Moveable(Moveable && x)40     Moveable(Moveable&& x)
41         : int_(x.int_), double_(x.double_)
42             {x.int_ = -1; x.double_ = -1;}
operator =(Moveable && x)43     Moveable& operator=(Moveable&& x)
44         {int_ = x.int_; x.int_ = -1;
45          double_ = x.double_; x.double_ = -1;
46          return *this;
47         }
48 
operator ==(const Moveable & x) const49     bool operator==(const Moveable& x) const
50         {return int_ == x.int_ && double_ == x.double_;}
operator <(const Moveable & x) const51     bool operator<(const Moveable& x) const
52         {return int_ < x.int_ || (int_ == x.int_ && double_ < x.double_);}
53 
get() const54     int get() const {return int_;}
moved() const55     bool moved() const {return int_ == -1;}
56 };
57 
58 
main(int,char **)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 ( i, 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(i, 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(-1, 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(3, 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(117, 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 ( Moveable(i, (double) i), 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(std::move(mvkey1), 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(std::move(mvkey2), 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 ( i, Moveable(i, (double) i));
140         assert(m.size() == 10);
141         M::const_iterator it = m.find(2);
142 
143         Moveable mv1(3, 3.0);
144         r = m.insert_or_assign(it, 2, 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(it, 3, 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(m.begin(), 4, 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(m.begin(), 5, 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(m.end(), 6, 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(m.end(), 7, 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(std::next(m.begin(), 2), 8, 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(std::next(m.begin(), 2), 9, 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 ( Moveable(i, (double) i), Moveable(i+1, (double) i+1));
208         assert(m.size() == 10);
209         M::const_iterator it = std::next(m.cbegin());
210 
211         Moveable mvkey1(2, 2.0);
212         Moveable mv1(4, 4.0);
213         r = m.insert_or_assign(it, std::move(mvkey1), 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(it, std::move(mvkey2), 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(m.begin(), std::move(mvkey3), 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(m.begin(), std::move(mvkey4), 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(m.end(), std::move(mvkey5), 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(m.end(), std::move(mvkey6), 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(std::next(m.begin(), 2), std::move(mvkey7), 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(std::next(m.begin(), 2), std::move(mvkey8), 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