blob: eabcf2e85db2ee56fa57eb53b0027c6d56b1607f [file] [log] [blame]
Marshall Clow0ce05a92015-07-07 05:45:35 +00001//===----------------------------------------------------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
Eric Fiselierfd9bbf52015-07-19 03:16:47 +000010// UNSUPPORTED: c++98, c++03, c++11, c++14
Marshall Clow0ce05a92015-07-07 05:45:35 +000011
12// <unordered_map>
13
14// class unordered_map
15
16// template <class... Args>
17// pair<iterator, bool> try_emplace(const key_type& k, Args&&... args); // C++17
18// template <class... Args>
19// pair<iterator, bool> try_emplace(key_type&& k, Args&&... args); // C++17
20// template <class... Args>
21// iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args); // C++17
22// template <class... Args>
23// iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args); // C++17
24
Dan Albert1d4a1ed2016-05-25 22:36:09 -070025#include <__config>
Marshall Clow0ce05a92015-07-07 05:45:35 +000026#include <unordered_map>
27#include <cassert>
28#include <tuple>
29
30class Moveable
31{
32 Moveable(const Moveable&);
33 Moveable& operator=(const Moveable&);
34
35 int int_;
36 double double_;
37public:
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 size_t hash () const { return std::hash<int>()(int_) + std::hash<double>()(double_); }
54
55 int get() const {return int_;}
56 bool moved() const {return int_ == -1;}
57};
58
59namespace std {
60 template <> struct hash<Moveable> {
61 size_t operator () (const Moveable &m) const { return m.hash(); }
62 };
63}
64
65int main()
66{
Marshall Clow0ce05a92015-07-07 05:45:35 +000067
68 { // pair<iterator, bool> try_emplace(const key_type& k, Args&&... args);
69 typedef std::unordered_map<int, Moveable> M;
70 typedef std::pair<M::iterator, bool> R;
71 M m;
72 R r;
73 for (int i = 0; i < 20; i += 2)
74 m.emplace (i, Moveable(i, (double) i));
75 assert(m.size() == 10);
76
77 Moveable mv1(3, 3.0);
78 for (int i=0; i < 20; i += 2)
79 {
80 r = m.try_emplace(i, std::move(mv1));
81 assert(m.size() == 10);
82 assert(!r.second); // was not inserted
83 assert(!mv1.moved()); // was not moved from
84 assert(r.first->first == i); // key
85 }
86
87 r = m.try_emplace(-1, std::move(mv1));
88 assert(m.size() == 11);
89 assert(r.second); // was inserted
90 assert(mv1.moved()); // was moved from
91 assert(r.first->first == -1); // key
92 assert(r.first->second.get() == 3); // value
93
94 Moveable mv2(5, 3.0);
95 r = m.try_emplace(5, std::move(mv2));
96 assert(m.size() == 12);
97 assert(r.second); // was inserted
98 assert(mv2.moved()); // was moved from
99 assert(r.first->first == 5); // key
100 assert(r.first->second.get() == 5); // value
101
102 Moveable mv3(-1, 3.0);
103 r = m.try_emplace(117, std::move(mv2));
104 assert(m.size() == 13);
105 assert(r.second); // was inserted
106 assert(mv2.moved()); // was moved from
107 assert(r.first->first == 117); // key
108 assert(r.first->second.get() == -1); // value
109 }
110
Eric Fiselierfd9bbf52015-07-19 03:16:47 +0000111 { // pair<iterator, bool> try_emplace(key_type&& k, Args&&... args);
Marshall Clow0ce05a92015-07-07 05:45:35 +0000112 typedef std::unordered_map<Moveable, Moveable> M;
113 typedef std::pair<M::iterator, bool> R;
114 M m;
115 R r;
116 for (int i = 0; i < 20; i += 2)
117 m.emplace ( Moveable(i, (double) i), Moveable(i+1, (double) i+1));
118 assert(m.size() == 10);
119
120 Moveable mvkey1(2, 2.0);
121 Moveable mv1(4, 4.0);
122 r = m.try_emplace(std::move(mvkey1), std::move(mv1));
123 assert(m.size() == 10);
124 assert(!r.second); // was not inserted
125 assert(!mv1.moved()); // was not moved from
126 assert(!mvkey1.moved()); // was not moved from
127 assert(r.first->first == mvkey1); // key
128
129 Moveable mvkey2(3, 3.0);
130 r = m.try_emplace(std::move(mvkey2), std::move(mv1));
131 assert(m.size() == 11);
132 assert(r.second); // was inserted
133 assert(mv1.moved()); // was moved from
134 assert(mvkey2.moved()); // was moved from
135 assert(r.first->first.get() == 3); // key
136 assert(r.first->second.get() == 4); // value
137 }
138
139 { // iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args);
140 typedef std::unordered_map<int, Moveable> M;
141 M m;
142 M::iterator r;
143 for (int i = 0; i < 20; i += 2)
144 m.try_emplace ( i, Moveable(i, (double) i));
145 assert(m.size() == 10);
146 M::const_iterator it = m.find(2);
Eric Fiselierfd9bbf52015-07-19 03:16:47 +0000147
Marshall Clow0ce05a92015-07-07 05:45:35 +0000148 Moveable mv1(3, 3.0);
149 for (int i=0; i < 20; i += 2)
150 {
151 r = m.try_emplace(it, i, std::move(mv1));
152 assert(m.size() == 10);
153 assert(!mv1.moved()); // was not moved from
154 assert(r->first == i); // key
155 assert(r->second.get() == i); // value
156 }
157
158 r = m.try_emplace(it, 3, std::move(mv1));
159 assert(m.size() == 11);
160 assert(mv1.moved()); // was moved from
161 assert(r->first == 3); // key
162 assert(r->second.get() == 3); // value
163 }
164
165 { // iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args);
166 typedef std::unordered_map<Moveable, Moveable> M;
167 M m;
168 M::iterator r;
169 for ( int i = 0; i < 20; i += 2 )
170 m.emplace ( Moveable(i, (double) i), Moveable(i+1, (double) i+1));
171 assert(m.size() == 10);
172 M::const_iterator it = std::next(m.cbegin());
173
174 Moveable mvkey1(2, 2.0);
175 Moveable mv1(4, 4.0);
176 r = m.try_emplace(it, std::move(mvkey1), std::move(mv1));
177 assert(m.size() == 10);
178 assert(!mv1.moved()); // was not moved from
179 assert(!mvkey1.moved()); // was not moved from
180 assert(r->first == mvkey1); // key
181
182 Moveable mvkey2(3, 3.0);
183 r = m.try_emplace(it, std::move(mvkey2), std::move(mv1));
184 assert(m.size() == 11);
185 assert(mv1.moved()); // was moved from
186 assert(mvkey2.moved()); // was moved from
187 assert(r->first.get() == 3); // key
188 assert(r->second.get() == 4); // value
189 }
Marshall Clow0ce05a92015-07-07 05:45:35 +0000190}