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 <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> 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 | { |
73 | r = m.try_emplace(k: i, args: std::move(mv1)); |
74 | assert(m.size() == 10); |
75 | assert(!r.second); // was not inserted |
76 | assert(!mv1.moved()); // was not moved from |
77 | assert(r.first->first == i); // key |
78 | } |
79 | |
80 | r = m.try_emplace(k: -1, args: std::move(mv1)); |
81 | assert(m.size() == 11); |
82 | assert(r.second); // was inserted |
83 | assert(mv1.moved()); // was moved from |
84 | assert(r.first->first == -1); // key |
85 | assert(r.first->second.get() == 3); // value |
86 | |
87 | Moveable mv2(5, 3.0); |
88 | r = m.try_emplace(k: 5, args: std::move(mv2)); |
89 | assert(m.size() == 12); |
90 | assert(r.second); // was inserted |
91 | assert(mv2.moved()); // was moved from |
92 | assert(r.first->first == 5); // key |
93 | assert(r.first->second.get() == 5); // value |
94 | |
95 | Moveable mv3(-1, 3.0); |
96 | r = m.try_emplace(k: 117, args: std::move(mv2)); |
97 | assert(m.size() == 13); |
98 | assert(r.second); // was inserted |
99 | assert(mv2.moved()); // was moved from |
100 | assert(r.first->first == 117); // key |
101 | assert(r.first->second.get() == -1); // value |
102 | } |
103 | |
104 | { // pair<iterator, bool> try_emplace(key_type&& k, Args&&... args); |
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.try_emplace(k: std::move(mvkey1), args: std::move(mv1)); |
116 | assert(m.size() == 10); |
117 | assert(!r.second); // was not inserted |
118 | assert(!mv1.moved()); // was not moved from |
119 | assert(!mvkey1.moved()); // was not moved from |
120 | assert(r.first->first == mvkey1); // key |
121 | |
122 | Moveable mvkey2(3, 3.0); |
123 | r = m.try_emplace(k: std::move(mvkey2), args: std::move(mv1)); |
124 | assert(m.size() == 11); |
125 | assert(r.second); // was inserted |
126 | assert(mv1.moved()); // was moved from |
127 | assert(mvkey2.moved()); // was moved from |
128 | assert(r.first->first.get() == 3); // key |
129 | assert(r.first->second.get() == 4); // value |
130 | } |
131 | |
132 | { // iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args); |
133 | typedef std::map<int, Moveable> M; |
134 | M m; |
135 | M::iterator r; |
136 | for ( int i = 0; i < 20; i += 2 ) |
137 | m.try_emplace ( k: i, args: Moveable(i, (double) i)); |
138 | assert(m.size() == 10); |
139 | M::const_iterator it = m.find(x: 2); |
140 | |
141 | Moveable mv1(3, 3.0); |
142 | for (int i=0; i < 20; i += 2) |
143 | { |
144 | r = m.try_emplace(hint: it, k: i, args: std::move(mv1)); |
145 | assert(m.size() == 10); |
146 | assert(!mv1.moved()); // was not moved from |
147 | assert(r->first == i); // key |
148 | assert(r->second.get() == i); // value |
149 | } |
150 | |
151 | r = m.try_emplace(hint: it, k: 3, args: std::move(mv1)); |
152 | assert(m.size() == 11); |
153 | assert(mv1.moved()); // was moved from |
154 | assert(r->first == 3); // key |
155 | assert(r->second.get() == 3); // value |
156 | } |
157 | |
158 | { // iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args); |
159 | typedef std::map<Moveable, Moveable> M; |
160 | M m; |
161 | M::iterator r; |
162 | for ( int i = 0; i < 20; i += 2 ) |
163 | m.emplace ( args: Moveable(i, (double) i), args: Moveable(i+1, (double) i+1)); |
164 | assert(m.size() == 10); |
165 | M::const_iterator it = std::next(x: m.cbegin()); |
166 | |
167 | Moveable mvkey1(2, 2.0); |
168 | Moveable mv1(4, 4.0); |
169 | r = m.try_emplace(hint: it, k: std::move(mvkey1), args: std::move(mv1)); |
170 | assert(m.size() == 10); |
171 | assert(!mv1.moved()); // was not moved from |
172 | assert(!mvkey1.moved()); // was not moved from |
173 | assert(r->first == mvkey1); // key |
174 | |
175 | Moveable mvkey2(3, 3.0); |
176 | r = m.try_emplace(hint: it, k: std::move(mvkey2), args: std::move(mv1)); |
177 | assert(m.size() == 11); |
178 | assert(mv1.moved()); // was moved from |
179 | assert(mvkey2.moved()); // was moved from |
180 | assert(r->first.get() == 3); // key |
181 | assert(r->second.get() == 4); // value |
182 | } |
183 | |
184 | return 0; |
185 | } |
186 | |