1 //===----------------------------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // UNSUPPORTED: c++03, c++11, c++14
13 // class unordered_map
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
24 #include <unordered_map>
29 #include "test_macros.h"
33 Moveable(const Moveable
&);
34 Moveable
& operator=(const Moveable
&);
39 Moveable() : int_(0), double_(0) {}
40 Moveable(int i
, double d
) : int_(i
), double_(d
) {}
41 Moveable(Moveable
&& x
)
42 : int_(x
.int_
), double_(x
.double_
)
43 {x
.int_
= -1; x
.double_
= -1;}
44 Moveable
& operator=(Moveable
&& x
)
45 {int_
= x
.int_
; x
.int_
= -1;
46 double_
= x
.double_
; x
.double_
= -1;
50 bool operator==(const Moveable
& x
) const
51 {return int_
== x
.int_
&& double_
== x
.double_
;}
52 bool operator<(const Moveable
& x
) const
53 {return int_
< x
.int_
|| (int_
== x
.int_
&& double_
< x
.double_
);}
54 std::size_t hash () const { return std::hash
<int>()(int_
) + std::hash
<double>()(double_
); }
56 int get() const {return int_
;}
57 bool moved() const {return int_
== -1;}
61 template <> struct hash
<Moveable
> {
62 std::size_t operator () (const Moveable
&m
) const { return m
.hash(); }
69 { // pair<iterator, bool> try_emplace(const key_type& k, Args&&... args);
70 typedef std::unordered_map
<int, Moveable
> M
;
71 typedef std::pair
<M::iterator
, bool> R
;
74 for (int i
= 0; i
< 20; i
+= 2)
75 m
.emplace (i
, Moveable(i
, (double) i
));
76 assert(m
.size() == 10);
79 for (int i
=0; i
< 20; i
+= 2)
81 r
= m
.try_emplace(i
, std::move(mv1
));
82 assert(m
.size() == 10);
83 assert(!r
.second
); // was not inserted
84 assert(!mv1
.moved()); // was not moved from
85 assert(r
.first
->first
== i
); // key
88 r
= m
.try_emplace(-1, std::move(mv1
));
89 assert(m
.size() == 11);
90 assert(r
.second
); // was inserted
91 assert(mv1
.moved()); // was moved from
92 assert(r
.first
->first
== -1); // key
93 assert(r
.first
->second
.get() == 3); // value
96 r
= m
.try_emplace(5, std::move(mv2
));
97 assert(m
.size() == 12);
98 assert(r
.second
); // was inserted
99 assert(mv2
.moved()); // was moved from
100 assert(r
.first
->first
== 5); // key
101 assert(r
.first
->second
.get() == 5); // value
103 Moveable
mv3(-1, 3.0);
104 r
= m
.try_emplace(117, std::move(mv2
));
105 assert(m
.size() == 13);
106 assert(r
.second
); // was inserted
107 assert(mv2
.moved()); // was moved from
108 assert(r
.first
->first
== 117); // key
109 assert(r
.first
->second
.get() == -1); // value
112 { // pair<iterator, bool> try_emplace(key_type&& k, Args&&... args);
113 typedef std::unordered_map
<Moveable
, Moveable
> M
;
114 typedef std::pair
<M::iterator
, bool> R
;
117 for (int i
= 0; i
< 20; i
+= 2)
118 m
.emplace ( Moveable(i
, (double) i
), Moveable(i
+1, (double) i
+1));
119 assert(m
.size() == 10);
121 Moveable
mvkey1(2, 2.0);
122 Moveable
mv1(4, 4.0);
123 r
= m
.try_emplace(std::move(mvkey1
), std::move(mv1
));
124 assert(m
.size() == 10);
125 assert(!r
.second
); // was not inserted
126 assert(!mv1
.moved()); // was not moved from
127 assert(!mvkey1
.moved()); // was not moved from
128 assert(r
.first
->first
== mvkey1
); // key
130 Moveable
mvkey2(3, 3.0);
131 r
= m
.try_emplace(std::move(mvkey2
), std::move(mv1
));
132 assert(m
.size() == 11);
133 assert(r
.second
); // was inserted
134 assert(mv1
.moved()); // was moved from
135 assert(mvkey2
.moved()); // was moved from
136 assert(r
.first
->first
.get() == 3); // key
137 assert(r
.first
->second
.get() == 4); // value
140 { // iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args);
141 typedef std::unordered_map
<int, Moveable
> M
;
144 for (int i
= 0; i
< 20; i
+= 2)
145 m
.try_emplace ( i
, Moveable(i
, (double) i
));
146 assert(m
.size() == 10);
147 M::const_iterator it
= m
.find(2);
149 Moveable
mv1(3, 3.0);
150 for (int i
=0; i
< 20; i
+= 2)
152 r
= m
.try_emplace(it
, i
, std::move(mv1
));
153 assert(m
.size() == 10);
154 assert(!mv1
.moved()); // was not moved from
155 assert(r
->first
== i
); // key
156 assert(r
->second
.get() == i
); // value
159 r
= m
.try_emplace(it
, 3, std::move(mv1
));
160 assert(m
.size() == 11);
161 assert(mv1
.moved()); // was moved from
162 assert(r
->first
== 3); // key
163 assert(r
->second
.get() == 3); // value
166 { // iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args);
167 typedef std::unordered_map
<Moveable
, Moveable
> M
;
170 for ( int i
= 0; i
< 20; i
+= 2 )
171 m
.emplace ( Moveable(i
, (double) i
), Moveable(i
+1, (double) i
+1));
172 assert(m
.size() == 10);
173 M::const_iterator it
= std::next(m
.cbegin());
175 Moveable
mvkey1(2, 2.0);
176 Moveable
mv1(4, 4.0);
177 r
= m
.try_emplace(it
, std::move(mvkey1
), std::move(mv1
));
178 assert(m
.size() == 10);
179 assert(!mv1
.moved()); // was not moved from
180 assert(!mvkey1
.moved()); // was not moved from
181 assert(r
->first
== mvkey1
); // key
183 Moveable
mvkey2(3, 3.0);
184 r
= m
.try_emplace(it
, std::move(mvkey2
), std::move(mv1
));
185 assert(m
.size() == 11);
186 assert(mv1
.moved()); // was moved from
187 assert(mvkey2
.moved()); // was moved from
188 assert(r
->first
.get() == 3); // key
189 assert(r
->second
.get() == 4); // value