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... Args> |
16 | // pair<iterator, bool> try_emplace(const key_type& k, Args&&... args); // C++17 |
17 | // template <class... Args> |
18 | // pair<iterator, bool> try_emplace(key_type&& k, Args&&... args); // C++17 |
19 | // template <class... Args> |
20 | // iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args); // C++17 |
21 | // template <class... Args> |
22 | // iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args); // C++17 |
23 | |
24 | #include <map> |
25 | #include <cassert> |
26 | #include <iterator> |
27 | #include <tuple> |
28 | |
29 | #include "test_macros.h" |
30 | |
31 | class Moveable { |
32 | Moveable(const Moveable&); |
33 | Moveable& operator=(const Moveable&); |
34 | |
35 | int int_; |
36 | double double_; |
37 | |
38 | public: |
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 | |
60 | int main(int, char**) { |
61 | { // pair<iterator, bool> try_emplace(const key_type& k, Args&&... args); |
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 | Moveable mv1(3, 3.0); |
71 | for (int i = 0; i < 20; i += 2) { |
72 | r = m.try_emplace(k: i, args: std::move(mv1)); |
73 | assert(m.size() == 10); |
74 | assert(!r.second); // was not inserted |
75 | assert(!mv1.moved()); // was not moved from |
76 | assert(r.first->first == i); // key |
77 | } |
78 | |
79 | r = m.try_emplace(k: -1, args: std::move(mv1)); |
80 | assert(m.size() == 11); |
81 | assert(r.second); // was inserted |
82 | assert(mv1.moved()); // was moved from |
83 | assert(r.first->first == -1); // key |
84 | assert(r.first->second.get() == 3); // value |
85 | |
86 | Moveable mv2(5, 3.0); |
87 | r = m.try_emplace(k: 5, args: std::move(mv2)); |
88 | assert(m.size() == 12); |
89 | assert(r.second); // was inserted |
90 | assert(mv2.moved()); // was moved from |
91 | assert(r.first->first == 5); // key |
92 | assert(r.first->second.get() == 5); // value |
93 | |
94 | Moveable mv3(-1, 3.0); |
95 | r = m.try_emplace(k: 117, args: std::move(mv2)); |
96 | assert(m.size() == 13); |
97 | assert(r.second); // was inserted |
98 | assert(mv2.moved()); // was moved from |
99 | assert(r.first->first == 117); // key |
100 | assert(r.first->second.get() == -1); // value |
101 | } |
102 | |
103 | { // pair<iterator, bool> try_emplace(key_type&& k, Args&&... args); |
104 | typedef std::map<Moveable, Moveable> M; |
105 | typedef std::pair<M::iterator, bool> R; |
106 | M m; |
107 | R r; |
108 | for (int i = 0; i < 20; i += 2) |
109 | m.emplace(args: Moveable(i, (double)i), args: Moveable(i + 1, (double)i + 1)); |
110 | assert(m.size() == 10); |
111 | |
112 | Moveable mvkey1(2, 2.0); |
113 | Moveable mv1(4, 4.0); |
114 | r = m.try_emplace(k: std::move(mvkey1), args: std::move(mv1)); |
115 | assert(m.size() == 10); |
116 | assert(!r.second); // was not inserted |
117 | assert(!mv1.moved()); // was not moved from |
118 | assert(!mvkey1.moved()); // was not moved from |
119 | assert(r.first->first == mvkey1); // key |
120 | |
121 | Moveable mvkey2(3, 3.0); |
122 | r = m.try_emplace(k: std::move(mvkey2), args: std::move(mv1)); |
123 | assert(m.size() == 11); |
124 | assert(r.second); // was inserted |
125 | assert(mv1.moved()); // was moved from |
126 | assert(mvkey2.moved()); // was moved from |
127 | assert(r.first->first.get() == 3); // key |
128 | assert(r.first->second.get() == 4); // value |
129 | } |
130 | |
131 | { // iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args); |
132 | typedef std::map<int, Moveable> M; |
133 | M m; |
134 | M::iterator r; |
135 | for (int i = 0; i < 20; i += 2) |
136 | m.try_emplace(k: i, args: Moveable(i, (double)i)); |
137 | assert(m.size() == 10); |
138 | M::const_iterator it = m.find(x: 2); |
139 | |
140 | Moveable mv1(3, 3.0); |
141 | for (int i = 0; i < 20; i += 2) { |
142 | r = m.try_emplace(hint: it, k: i, args: std::move(mv1)); |
143 | assert(m.size() == 10); |
144 | assert(!mv1.moved()); // was not moved from |
145 | assert(r->first == i); // key |
146 | assert(r->second.get() == i); // value |
147 | } |
148 | |
149 | r = m.try_emplace(hint: it, k: 3, args: std::move(mv1)); |
150 | assert(m.size() == 11); |
151 | assert(mv1.moved()); // was moved from |
152 | assert(r->first == 3); // key |
153 | assert(r->second.get() == 3); // value |
154 | } |
155 | |
156 | { // iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args); |
157 | typedef std::map<Moveable, Moveable> M; |
158 | M m; |
159 | M::iterator r; |
160 | for (int i = 0; i < 20; i += 2) |
161 | m.emplace(args: Moveable(i, (double)i), args: Moveable(i + 1, (double)i + 1)); |
162 | assert(m.size() == 10); |
163 | M::const_iterator it = std::next(x: m.cbegin()); |
164 | |
165 | Moveable mvkey1(2, 2.0); |
166 | Moveable mv1(4, 4.0); |
167 | r = m.try_emplace(hint: it, k: std::move(mvkey1), args: std::move(mv1)); |
168 | assert(m.size() == 10); |
169 | assert(!mv1.moved()); // was not moved from |
170 | assert(!mvkey1.moved()); // was not moved from |
171 | assert(r->first == mvkey1); // key |
172 | |
173 | Moveable mvkey2(3, 3.0); |
174 | r = m.try_emplace(hint: it, k: std::move(mvkey2), args: std::move(mv1)); |
175 | assert(m.size() == 11); |
176 | assert(mv1.moved()); // was moved from |
177 | assert(mvkey2.moved()); // was moved from |
178 | assert(r->first.get() == 3); // key |
179 | assert(r->second.get() == 4); // value |
180 | } |
181 | |
182 | return 0; |
183 | } |
184 | |