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// <unordered_map>
12
13// class unordered_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 <unordered_map>
25#include <cassert>
26#include <iterator>
27#include <tuple>
28
29#include "test_macros.h"
30
31class Moveable
32{
33 Moveable(const Moveable&);
34 Moveable& operator=(const Moveable&);
35
36 int int_;
37 double double_;
38public:
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;
47 return *this;
48 }
49
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_); }
55
56 int get() const {return int_;}
57 bool moved() const {return int_ == -1;}
58};
59
60namespace std {
61 template <> struct hash<Moveable> {
62 std::size_t operator () (const Moveable &m) const { return m.hash(); }
63 };
64}
65
66int main(int, char**)
67{
68
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;
72 M m;
73 R r;
74 for (int i = 0; i < 20; i += 2)
75 m.emplace (args&: i, args: Moveable(i, (double) i));
76 assert(m.size() == 10);
77
78 Moveable mv1(3, 3.0);
79 for (int i=0; i < 20; i += 2)
80 {
81 r = m.try_emplace(k: i, args: 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
86 }
87
88 r = m.try_emplace(k: -1, args: 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
94
95 Moveable mv2(5, 3.0);
96 r = m.try_emplace(k: 5, args: 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
102
103 Moveable mv3(-1, 3.0);
104 r = m.try_emplace(k: 117, args: 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
110 }
111
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;
115 M m;
116 R r;
117 for (int i = 0; i < 20; i += 2)
118 m.emplace ( args: Moveable(i, (double) i), args: Moveable(i+1, (double) i+1));
119 assert(m.size() == 10);
120
121 Moveable mvkey1(2, 2.0);
122 Moveable mv1(4, 4.0);
123 r = m.try_emplace(k: std::move(mvkey1), args: 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
129
130 Moveable mvkey2(3, 3.0);
131 r = m.try_emplace(k: std::move(mvkey2), args: 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
138 }
139
140 { // iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args);
141 typedef std::unordered_map<int, Moveable> M;
142 M m;
143 M::iterator r;
144 for (int i = 0; i < 20; i += 2)
145 m.try_emplace ( k: i, args: Moveable(i, (double) i));
146 assert(m.size() == 10);
147 M::const_iterator it = m.find(x: 2);
148
149 Moveable mv1(3, 3.0);
150 for (int i=0; i < 20; i += 2)
151 {
152 r = m.try_emplace(hint: it, k: i, args: 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
157 }
158
159 r = m.try_emplace(hint: it, k: 3, args: 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
164 }
165
166 { // iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args);
167 typedef std::unordered_map<Moveable, Moveable> M;
168 M m;
169 M::iterator r;
170 for ( int i = 0; i < 20; i += 2 )
171 m.emplace ( args: Moveable(i, (double) i), args: Moveable(i+1, (double) i+1));
172 assert(m.size() == 10);
173 M::const_iterator it = std::next(x: m.cbegin());
174
175 Moveable mvkey1(2, 2.0);
176 Moveable mv1(4, 4.0);
177 r = m.try_emplace(hint: it, k: std::move(mvkey1), args: 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
182
183 Moveable mvkey2(3, 3.0);
184 r = m.try_emplace(hint: it, k: std::move(mvkey2), args: 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
190 }
191
192 return 0;
193}
194

source code of libcxx/test/std/containers/unord/unord.map/unord.map.modifiers/try.emplace.pass.cpp