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

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