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, c++17, c++20
10
11// <flat_map>
12
13// template <class... Args>
14// iterator emplace_hint(const_iterator position, Args&&... args);
15
16#include <flat_map>
17#include <cassert>
18#include <deque>
19#include <functional>
20#include <vector>
21
22#include "MinSequenceContainer.h"
23#include "test_macros.h"
24#include "../../../Emplaceable.h"
25#include "DefaultOnly.h"
26#include "min_allocator.h"
27#include "../helpers.h"
28
29#if defined(_LIBCPP_VERSION)
30// spec only specifies `emplace(Args&&...)` is_constructible_v<pair<key_type, mapped_type>, Args...> is true.
31// nothing mentioned for emplace_hint
32template <class M, class... Args>
33concept CanEmplaceHint =
34 requires(M m, typename M::const_iterator i, Args&&... args) { m.emplace_hint(i, std::forward<Args>(args)...); };
35
36using Map = std::flat_map<Emplaceable, Emplaceable>;
37static_assert(CanEmplaceHint<Map>);
38static_assert(CanEmplaceHint<Map, Emplaceable, Emplaceable>);
39static_assert(CanEmplaceHint<Map, std::piecewise_construct_t, std::tuple<int, double>, std::tuple<int, double>>);
40static_assert(!CanEmplaceHint<Map, Emplaceable>);
41static_assert(!CanEmplaceHint<Map, int, double>);
42#endif
43
44template <class KeyContainer, class ValueContainer>
45void test() {
46 using Key = typename KeyContainer::value_type;
47 using Value = typename ValueContainer::value_type;
48 using M = std::flat_map<Key, Value, std::less<Key>, KeyContainer, ValueContainer>;
49 using R = M::iterator;
50 {
51 // was empty
52 M m;
53 std::same_as<R> decltype(auto) r = m.emplace_hint(m.end(), typename M::value_type(2, 3.5));
54 assert(r == m.begin());
55 assert(m.size() == 1);
56 assert(r->first == 2);
57 assert(r->second == 3.5);
58 }
59 {
60 // hints correct at the begin
61 M m = {{3, 3.0}, {4, 4.0}};
62 auto hint = m.begin();
63 std::same_as<R> decltype(auto) r = m.emplace_hint(hint, typename M::value_type(2, 2.0));
64 assert(r == m.begin());
65 assert(m.size() == 3);
66 assert(r->first == 2);
67 assert(r->second == 2.0);
68 }
69 {
70 // hints correct in the middle
71 M m = {{0, 0.0}, {1, 1.0}, {3, 3.0}, {4, 4.0}};
72 auto hint = m.begin() + 2;
73 std::same_as<R> decltype(auto) r = m.emplace_hint(hint, typename M::value_type(2, 2.0));
74 assert(r == m.begin() + 2);
75 assert(m.size() == 5);
76 assert(r->first == 2);
77 assert(r->second == 2.0);
78 }
79 {
80 // hints correct at the end
81 M m = {{0, 0.0}, {1, 1.0}};
82 auto hint = m.end();
83 std::same_as<R> decltype(auto) r = m.emplace_hint(hint, typename M::value_type(2, 2.0));
84 assert(r == m.begin() + 2);
85 assert(m.size() == 3);
86 assert(r->first == 2);
87 assert(r->second == 2.0);
88 }
89 {
90 // hints correct but key already exists
91 M m = {{0, 0.0}, {1, 1.0}, {2, 1.9}, {3, 3.0}, {4, 4.0}};
92 auto hint = m.begin() + 2;
93 std::same_as<R> decltype(auto) r = m.emplace_hint(hint, typename M::value_type(2, 2.0));
94 assert(r == m.begin() + 2);
95 assert(m.size() == 5);
96 assert(r->first == 2);
97 assert(r->second == 1.9);
98 }
99 {
100 // hints incorrectly at the begin
101 M m = {{1, 1.0}, {4, 4.0}};
102 auto hint = m.begin();
103 std::same_as<R> decltype(auto) r = m.emplace_hint(hint, typename M::value_type(2, 2.0));
104 assert(r == m.begin() + 1);
105 assert(m.size() == 3);
106 assert(r->first == 2);
107 assert(r->second == 2.0);
108 }
109 {
110 // hints incorrectly in the middle
111 M m = {{0, 0.0}, {1, 1.0}, {3, 3.0}, {4, 4.0}};
112 auto hint = m.begin() + 1;
113 std::same_as<R> decltype(auto) r = m.emplace_hint(hint, typename M::value_type(2, 2.0));
114 assert(r == m.begin() + 2);
115 assert(m.size() == 5);
116 assert(r->first == 2);
117 assert(r->second == 2.0);
118 }
119 {
120 // hints incorrectly at the end
121 M m = {{0, 0.0}, {3, 3.0}};
122 auto hint = m.end();
123 std::same_as<R> decltype(auto) r = m.emplace_hint(hint, typename M::value_type(2, 2.0));
124 assert(r == m.begin() + 1);
125 assert(m.size() == 3);
126 assert(r->first == 2);
127 assert(r->second == 2.0);
128 }
129 {
130 // hints incorrect and key already exists
131 M m = {{0, 0.0}, {1, 1.0}, {2, 1.9}, {3, 3.0}, {4, 4.0}};
132 auto hint = m.begin();
133 std::same_as<R> decltype(auto) r = m.emplace_hint(hint, typename M::value_type(2, 2.0));
134 assert(r == m.begin() + 2);
135 assert(m.size() == 5);
136 assert(r->first == 2);
137 assert(r->second == 1.9);
138 }
139}
140
141template <class KeyContainer, class ValueContainer>
142void test_emplaceable() {
143 using M = std::flat_map<int, Emplaceable, std::less<int>, KeyContainer, ValueContainer>;
144 using R = M::iterator;
145
146 M m;
147 ASSERT_SAME_TYPE(decltype(m.emplace_hint(m.cbegin())), R);
148 R r = m.emplace_hint(m.end(), std::piecewise_construct, std::forward_as_tuple(2), std::forward_as_tuple());
149 assert(r == m.begin());
150 assert(m.size() == 1);
151 assert(m.begin()->first == 2);
152 assert(m.begin()->second == Emplaceable());
153 r = m.emplace_hint(m.end(), std::piecewise_construct, std::forward_as_tuple(args: 1), std::forward_as_tuple(args: 2, args: 3.5));
154 assert(r == m.begin());
155 assert(m.size() == 2);
156 assert(m.begin()->first == 1);
157 assert(m.begin()->second == Emplaceable(2, 3.5));
158 r = m.emplace_hint(m.end(), std::piecewise_construct, std::forward_as_tuple(args: 1), std::forward_as_tuple(args: 2, args: 3.5));
159 assert(r == m.begin());
160 assert(m.size() == 2);
161 assert(m.begin()->first == 1);
162 assert(m.begin()->second == Emplaceable(2, 3.5));
163}
164
165int main(int, char**) {
166 test<std::vector<int>, std::vector<double>>();
167 test<std::deque<int>, std::vector<double>>();
168 test<MinSequenceContainer<int>, MinSequenceContainer<double>>();
169 test<std::vector<int, min_allocator<int>>, std::vector<double, min_allocator<double>>>();
170
171 test_emplaceable<std::vector<int>, std::vector<Emplaceable>>();
172 test_emplaceable<std::deque<int>, std::vector<Emplaceable>>();
173 test_emplaceable<MinSequenceContainer<int>, MinSequenceContainer<Emplaceable>>();
174 test_emplaceable<std::vector<int, min_allocator<int>>, std::vector<Emplaceable, min_allocator<Emplaceable>>>();
175
176 {
177 auto emplace_func = [](auto& m, auto key_arg, auto value_arg) {
178 m.emplace_hint(m.begin(), std::piecewise_construct, std::tuple(key_arg), std::tuple(value_arg));
179 };
180 test_emplace_exception_guarantee(emplace_function&: emplace_func);
181 }
182
183 return 0;
184}
185

source code of libcxx/test/std/containers/container.adaptors/flat.map/flat.map.modifiers/emplace_hint.pass.cpp