1 //===----------------------------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
13 // template<class K, class... Args>
14 // pair<iterator, bool> try_emplace(K&& k, Args&&... args);
15 // template<class K, class... Args>
16 // iterator try_emplace(const_iterator hint, K&& k, Args&&... args);
24 #include "MinSequenceContainer.h"
25 #include "test_macros.h"
26 #include "../helpers.h"
27 #include "min_allocator.h"
28 #include "../../../Emplaceable.h"
31 // The qualified-id Compare::is_transparent is valid and denotes a type.
32 // is_constructible_v<key_type, K> is true.
33 // is_constructible_v<mapped_type, Args...> is true.
34 // For the first overload, is_convertible_v<K&&, const_iterator> and is_convertible_v<K&&, iterator> are both false
35 template <class M
, class... Args
>
36 concept CanTryEmplace
= requires(M m
, Args
&&... args
) { m
.try_emplace(std::forward
<Args
>(args
)...); };
38 using TransparentMap
= std::flat_map
<int, Emplaceable
, TransparentComparator
>;
39 using NonTransparentMap
= std::flat_map
<int, Emplaceable
, NonTransparentComparator
>;
41 using TransparentMapIter
= typename
TransparentMap::iterator
;
42 using TransparentMapConstIter
= typename
TransparentMap::const_iterator
;
44 static_assert(!CanTryEmplace
<TransparentMap
>);
45 static_assert(!CanTryEmplace
<NonTransparentMap
>);
47 static_assert(CanTryEmplace
<TransparentMap
, ConvertibleTransparent
<int>>);
48 static_assert(CanTryEmplace
<TransparentMap
, ConvertibleTransparent
<int>, Emplaceable
>);
49 static_assert(CanTryEmplace
<TransparentMap
, ConvertibleTransparent
<int>, int, double>);
50 static_assert(!CanTryEmplace
<TransparentMap
, ConvertibleTransparent
<int>, const Emplaceable
&>);
51 static_assert(!CanTryEmplace
<TransparentMap
, ConvertibleTransparent
<int>, int>);
52 static_assert(!CanTryEmplace
<TransparentMap
, NonConvertibleTransparent
<int>, Emplaceable
>);
53 static_assert(!CanTryEmplace
<NonTransparentMap
, NonConvertibleTransparent
<int>, Emplaceable
>);
54 static_assert(!CanTryEmplace
<TransparentMap
, ConvertibleTransparent
<int>, int>);
55 static_assert(!CanTryEmplace
<TransparentMap
, TransparentMapIter
, Emplaceable
>);
56 static_assert(!CanTryEmplace
<TransparentMap
, TransparentMapConstIter
, Emplaceable
>);
58 static_assert(CanTryEmplace
<TransparentMap
, TransparentMapConstIter
, ConvertibleTransparent
<int>>);
59 static_assert(CanTryEmplace
<TransparentMap
, TransparentMapConstIter
, ConvertibleTransparent
<int>, Emplaceable
>);
60 static_assert(CanTryEmplace
<TransparentMap
, TransparentMapConstIter
, ConvertibleTransparent
<int>, int, double>);
61 static_assert(!CanTryEmplace
<TransparentMap
, TransparentMapConstIter
, ConvertibleTransparent
<int>, const Emplaceable
&>);
62 static_assert(!CanTryEmplace
<TransparentMap
, TransparentMapConstIter
, ConvertibleTransparent
<int>, int>);
63 static_assert(!CanTryEmplace
<TransparentMap
, TransparentMapConstIter
, NonConvertibleTransparent
<int>, Emplaceable
>);
64 static_assert(!CanTryEmplace
<NonTransparentMap
, TransparentMapConstIter
, NonConvertibleTransparent
<int>, Emplaceable
>);
65 static_assert(!CanTryEmplace
<TransparentMap
, TransparentMapConstIter
, ConvertibleTransparent
<int>, int>);
67 template <class KeyContainer
, class ValueContainer
>
69 using Key
= typename
KeyContainer::value_type
;
70 using Value
= typename
ValueContainer::value_type
;
71 using M
= std::flat_map
<Key
, Value
, TransparentComparator
, KeyContainer
, ValueContainer
>;
73 { // pair<iterator, bool> try_emplace(K&& k, Args&&... args);
74 using R
= std::pair
<typename
M::iterator
, bool>;
76 for (int i
= 0; i
< 20; i
+= 2)
77 m
.emplace(i
, Moveable(i
, (double)i
));
79 assert(m
.size() == 10);
82 for (int i
= 0; i
< 20; i
+= 2) {
83 std::same_as
<R
> decltype(auto) r
= m
.try_emplace(ConvertibleTransparent
<int>{i
}, std::move(mv1
));
84 assert(m
.size() == 10);
85 assert(!r
.second
); // was not inserted
86 assert(!mv1
.moved()); // was not moved from
87 assert(r
.first
->first
== i
); // key
90 std::same_as
<R
> decltype(auto) r2
= m
.try_emplace(ConvertibleTransparent
<int>{-1}, std::move(mv1
));
91 assert(m
.size() == 11);
92 assert(r2
.second
); // was inserted
93 assert(mv1
.moved()); // was moved from
94 assert(r2
.first
->first
== -1); // key
95 assert(r2
.first
->second
.get() == 3); // value
98 std::same_as
<R
> decltype(auto) r3
= m
.try_emplace(ConvertibleTransparent
<int>{5}, std::move(mv2
));
99 assert(m
.size() == 12);
100 assert(r3
.second
); // was inserted
101 assert(mv2
.moved()); // was moved from
102 assert(r3
.first
->first
== 5); // key
103 assert(r3
.first
->second
.get() == 5); // value
105 Moveable
mv3(-1, 3.0);
106 std::same_as
<R
> decltype(auto) r4
= m
.try_emplace(ConvertibleTransparent
<int>{117}, std::move(mv2
));
107 assert(m
.size() == 13);
108 assert(r4
.second
); // was inserted
109 assert(mv2
.moved()); // was moved from
110 assert(r4
.first
->first
== 117); // key
111 assert(r4
.first
->second
.get() == -1); // value
114 { // iterator try_emplace(const_iterator hint, K&& k, Args&&... args);
115 using R
= typename
M::iterator
;
117 for (int i
= 0; i
< 20; i
+= 2)
118 m
.try_emplace(i
, Moveable(i
, (double)i
));
119 assert(m
.size() == 10);
120 typename
M::const_iterator it
= m
.find(2);
122 Moveable
mv1(3, 3.0);
123 for (int i
= 0; i
< 20; i
+= 2) {
124 std::same_as
<R
> decltype(auto) r1
= m
.try_emplace(it
, ConvertibleTransparent
<int>{i
}, std::move(mv1
));
125 assert(m
.size() == 10);
126 assert(!mv1
.moved()); // was not moved from
127 assert(r1
->first
== i
); // key
128 assert(r1
->second
.get() == i
); // value
131 std::same_as
<R
> decltype(auto) r2
= m
.try_emplace(it
, ConvertibleTransparent
<int>{3}, std::move(mv1
));
132 assert(m
.size() == 11);
133 assert(mv1
.moved()); // was moved from
134 assert(r2
->first
== 3); // key
135 assert(r2
->second
.get() == 3); // value
139 int main(int, char**) {
140 test
<std::vector
<int>, std::vector
<Moveable
>>();
141 test
<std::deque
<int>, std::vector
<Moveable
>>();
142 test
<MinSequenceContainer
<int>, MinSequenceContainer
<Moveable
>>();
143 test
<std::vector
<int, min_allocator
<int>>, std::vector
<Moveable
, min_allocator
<Moveable
>>>();
146 bool transparent_used
= false;
147 TransparentComparator
c(transparent_used
);
148 std::flat_map
<int, int, TransparentComparator
> m(std::sorted_unique
, {{1, 1}, {2, 2}, {3, 3}}, c
);
149 assert(!transparent_used
);
150 auto p
= m
.try_emplace(ConvertibleTransparent
<int>{3}, 3);
152 assert(transparent_used
);
155 bool transparent_used
= false;
156 TransparentComparator
c(transparent_used
);
157 std::flat_map
<int, int, TransparentComparator
> m(std::sorted_unique
, {{1, 1}, {2, 2}, {3, 3}}, c
);
158 assert(!transparent_used
);
159 auto p
= m
.try_emplace(m
.begin(), ConvertibleTransparent
<int>{3}, 3);
160 assert(p
->second
== 3);
161 assert(transparent_used
);
164 auto try_emplace
= [](auto& m
, auto key_arg
, auto value_arg
) {
165 using M
= std::decay_t
<decltype(m
)>;
166 using Key
= typename
M::key_type
;
167 m
.try_emplace(ConvertibleTransparent
<Key
>{key_arg
}, value_arg
);
169 test_emplace_exception_guarantee(try_emplace
);
173 auto try_emplace_iter
= [](auto& m
, auto key_arg
, auto value_arg
) {
174 using M
= std::decay_t
<decltype(m
)>;
175 using Key
= typename
M::key_type
;
176 m
.try_emplace(m
.begin(), ConvertibleTransparent
<Key
>{key_arg
}, value_arg
);
178 test_emplace_exception_guarantee(try_emplace_iter
);