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

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