2 // Copyright 2016 Daniel James.
3 // Distributed under the Boost Software License, Version 1.0. (See accompanying
4 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 #include "../helpers/postfix.hpp"
7 #include "../helpers/prefix.hpp"
8 #include <boost/unordered_map.hpp>
9 #include <boost/unordered_set.hpp>
11 #include "../helpers/helpers.hpp"
12 #include "../helpers/metafunctions.hpp"
13 #include "../helpers/test.hpp"
14 #include <boost/static_assert.hpp>
15 #include <boost/type_traits/is_same.hpp>
19 UNORDERED_AUTO_TEST (example1
) {
20 typedef boost::unordered_map
<int, std::string
>::insert_return_type
23 boost::unordered_map
<int, std::string
> src
;
24 src
.emplace(1, "one");
25 src
.emplace(2, "two");
26 src
.emplace(3, "buckle my shoe");
27 boost::unordered_map
<int, std::string
> dst
;
28 dst
.emplace(3, "three");
30 dst
.insert(src
.extract(src
.find(1)));
31 dst
.insert(src
.extract(2));
32 insert_return_type r
= dst
.insert(src
.extract(3));
34 BOOST_TEST(src
.empty());
35 BOOST_TEST(dst
.size() == 3);
36 BOOST_TEST(dst
[1] == "one");
37 BOOST_TEST(dst
[2] == "two");
38 BOOST_TEST(dst
[3] == "three");
39 BOOST_TEST(!r
.inserted
);
40 BOOST_TEST(r
.position
== dst
.find(3));
41 BOOST_TEST(r
.node
.mapped() == "buckle my shoe");
44 UNORDERED_AUTO_TEST (example2
) {
45 boost::unordered_set
<int> src
;
49 boost::unordered_set
<int> dst
;
54 // Merge src into dst.
56 // dst == {1, 2, 3, 4, 5}
59 UNORDERED_AUTO_TEST (example3
) {
60 typedef boost::unordered_set
<int>::iterator iterator
;
62 boost::unordered_set
<int> src
;
66 boost::unordered_set
<int> dst
;
70 for (iterator i
= src
.begin(); i
!= src
.end();) {
71 std::pair
<iterator
, iterator
> p
= dst
.equal_range(*i
);
72 if (p
.first
== p
.second
)
73 dst
.insert(p
.first
, src
.extract(i
++));
77 BOOST_TEST(src
.size() == 1);
78 BOOST_TEST(*src
.begin() == 5);
80 std::set
<int> dst2(dst
.begin(), dst
.end());
81 std::set
<int>::iterator it
= dst2
.begin();
82 BOOST_TEST(*it
++ == 1);
83 BOOST_TEST(*it
++ == 2);
84 BOOST_TEST(*it
++ == 3);
85 BOOST_TEST(*it
++ == 4);
86 BOOST_TEST(*it
++ == 5);
87 BOOST_TEST(it
== dst2
.end());
90 UNORDERED_AUTO_TEST (failed_insertion_with_hint
) {
92 boost::unordered_set
<int> src
;
93 boost::unordered_set
<int> dst
;
99 boost::unordered_set
<int>::node_type nh
= src
.extract(10);
101 BOOST_TEST(dst
.insert(dst
.find(10), boost::move(nh
)) == dst
.find(10));
103 BOOST_TEST(!nh
.empty());
104 BOOST_TEST(nh
.value() == 10);
106 BOOST_TEST(dst
.insert(dst
.find(20), boost::move(nh
)) == dst
.find(10));
108 BOOST_TEST(!nh
.empty());
109 BOOST_TEST(nh
.value() == 10);
111 BOOST_TEST(src
.count(10) == 0);
112 BOOST_TEST(src
.count(20) == 1);
113 BOOST_TEST(dst
.count(10) == 1);
114 BOOST_TEST(dst
.count(20) == 1);
118 boost::unordered_map
<int, int> src
;
119 boost::unordered_map
<int, int> dst
;
125 boost::unordered_map
<int, int>::node_type nh
= src
.extract(10);
126 BOOST_TEST(dst
.insert(dst
.find(10), boost::move(nh
)) == dst
.find(10));
128 BOOST_TEST(!nh
.empty());
129 BOOST_TEST(nh
.key() == 10);
130 BOOST_TEST(nh
.mapped() == 30);
131 BOOST_TEST(dst
[10] == 20);
133 BOOST_TEST(dst
.insert(dst
.find(20), boost::move(nh
)) == dst
.find(10));
135 BOOST_TEST(!nh
.empty());
136 BOOST_TEST(nh
.key() == 10);
137 BOOST_TEST(nh
.mapped() == 30);
138 BOOST_TEST(dst
[10] == 20);
140 BOOST_TEST(src
.count(10) == 0);
141 BOOST_TEST(src
.count(20) == 1);
142 BOOST_TEST(dst
.count(10) == 1);
143 BOOST_TEST(dst
.count(20) == 1);
147 template <typename NodeHandle
>
148 bool node_handle_compare(
149 NodeHandle
const& nh
, BOOST_DEDUCED_TYPENAME
NodeHandle::value_type
const& x
)
151 return x
== nh
.value();
154 template <typename NodeHandle
>
155 bool node_handle_compare(NodeHandle
const& nh
,
156 std::pair
<BOOST_DEDUCED_TYPENAME
NodeHandle::key_type
const,
157 BOOST_DEDUCED_TYPENAME
NodeHandle::mapped_type
> const& x
)
159 return x
.first
== nh
.key() && x
.second
== nh
.mapped();
162 template <typename Container
> void node_handle_tests_impl(Container
& c
)
164 typedef BOOST_DEDUCED_TYPENAME
Container::node_type node_type
;
166 BOOST_DEDUCED_TYPENAME
Container::value_type value
= *c
.begin();
170 BOOST_TEST(n1
.empty());
172 node_type n2
= c
.extract(c
.begin());
174 BOOST_TEST(!n2
.empty());
175 node_handle_compare(n2
, value
);
177 node_type n3
= boost::move(n2
);
180 node_handle_compare(n3
, value
);
181 // TODO: Check that n2 doesn't have an allocator?
182 // Maybe by swapping and observing that the allocator is
183 // swapped rather than moved?
185 n1
= boost::move(n3
);
188 node_handle_compare(n1
, value
);
190 // Self move-assignment empties the node_handle.
191 n1
= boost::move(n1
);
194 n3
= boost::move(n3
);
197 BOOST_DEDUCED_TYPENAME
Container::value_type value1
= *c
.begin();
198 n1
= c
.extract(c
.begin());
199 BOOST_DEDUCED_TYPENAME
Container::value_type value2
= *c
.begin();
200 n2
= c
.extract(c
.begin());
203 node_handle_compare(n1
, value1
);
204 node_handle_compare(n2
, value2
);
208 node_handle_compare(n1
, value2
);
209 node_handle_compare(n2
, value1
);
216 node_handle_compare(n3
, value2
);
223 node_handle_compare(n1
, value1
);
233 UNORDERED_AUTO_TEST (node_handle_tests
) {
234 boost::unordered_set
<int> x1
;
238 node_handle_tests_impl(x1
);
240 boost::unordered_map
<int, std::string
> x2
;
241 x2
.emplace(10, "ten");
242 x2
.emplace(-23, "twenty");
243 x2
.emplace(-76, "thirty");
244 node_handle_tests_impl(x2
);
247 template <typename Container1
, typename Container2
>
248 void insert_node_handle_unique(Container1
& c1
, Container2
& c2
)
250 typedef BOOST_DEDUCED_TYPENAME
Container1::node_type node_type
;
251 typedef BOOST_DEDUCED_TYPENAME
Container1::value_type value_type
;
252 BOOST_STATIC_ASSERT(boost::is_same
<node_type
,
253 BOOST_DEDUCED_TYPENAME
Container2::node_type
>::value
);
255 typedef BOOST_DEDUCED_TYPENAME
Container1::insert_return_type
257 typedef BOOST_DEDUCED_TYPENAME
Container2::insert_return_type
260 insert_return_type1 r1
= c1
.insert(node_type());
261 insert_return_type2 r2
= c2
.insert(node_type());
262 BOOST_TEST(!r1
.inserted
);
263 BOOST_TEST(!r1
.node
);
264 BOOST_TEST(r1
.position
== c1
.end());
265 BOOST_TEST(!r2
.inserted
);
266 BOOST_TEST(!r2
.node
);
267 BOOST_TEST(r2
.position
== c2
.end());
269 while (!c1
.empty()) {
270 value_type v
= *c1
.begin();
271 value_type
const* v_ptr
= boost::addressof(*c1
.begin());
272 std::size_t count
= c2
.count(test::get_key
<Container1
>(v
));
273 insert_return_type2 r
= c2
.insert(c1
.extract(c1
.begin()));
275 BOOST_TEST(r
.inserted
);
276 BOOST_TEST_EQ(c2
.count(test::get_key
<Container1
>(v
)), count
+ 1);
277 BOOST_TEST(r
.position
!= c2
.end());
278 BOOST_TEST(boost::addressof(*r
.position
) == v_ptr
);
281 BOOST_TEST(!r
.inserted
);
282 BOOST_TEST_EQ(c2
.count(test::get_key
<Container1
>(v
)), count
);
283 BOOST_TEST(r
.position
!= c2
.end());
285 test::get_key
<Container2
>(*r
.position
) == test::get_key
<Container2
>(v
));
287 node_handle_compare(r
.node
, v
);
292 template <typename Container1
, typename Container2
>
293 void insert_node_handle_unique2(Container1
& c1
, Container2
& c2
)
295 typedef BOOST_DEDUCED_TYPENAME
Container1::node_type node_type
;
296 typedef BOOST_DEDUCED_TYPENAME
Container1::value_type value_type
;
297 BOOST_STATIC_ASSERT(boost::is_same
<node_type
,
298 BOOST_DEDUCED_TYPENAME
Container2::node_type
>::value
);
300 // typedef BOOST_DEDUCED_TYPENAME Container1::insert_return_type
301 // insert_return_type1;
302 typedef BOOST_DEDUCED_TYPENAME
Container2::insert_return_type
305 while (!c1
.empty()) {
306 value_type v
= *c1
.begin();
307 value_type
const* v_ptr
= boost::addressof(*c1
.begin());
308 std::size_t count
= c2
.count(test::get_key
<Container1
>(v
));
309 insert_return_type2 r
= c2
.insert(c1
.extract(test::get_key
<Container1
>(v
)));
311 BOOST_TEST_EQ(c2
.count(test::get_key
<Container1
>(v
)), count
+ 1);
312 BOOST_TEST(r
.position
!= c2
.end());
313 BOOST_TEST(boost::addressof(*r
.position
) == v_ptr
);
316 BOOST_TEST_EQ(c2
.count(test::get_key
<Container1
>(v
)), count
);
317 BOOST_TEST(r
.position
!= c2
.end());
319 test::get_key
<Container2
>(*r
.position
) == test::get_key
<Container2
>(v
));
321 node_handle_compare(r
.node
, v
);
326 template <typename Container1
, typename Container2
>
327 void insert_node_handle_equiv(Container1
& c1
, Container2
& c2
)
329 typedef BOOST_DEDUCED_TYPENAME
Container1::node_type node_type
;
330 typedef BOOST_DEDUCED_TYPENAME
Container1::value_type value_type
;
331 BOOST_STATIC_ASSERT(boost::is_same
<node_type
,
332 BOOST_DEDUCED_TYPENAME
Container2::node_type
>::value
);
334 typedef BOOST_DEDUCED_TYPENAME
Container1::iterator iterator1
;
335 typedef BOOST_DEDUCED_TYPENAME
Container2::iterator iterator2
;
337 iterator1 r1
= c1
.insert(node_type());
338 iterator2 r2
= c2
.insert(node_type());
339 BOOST_TEST(r1
== c1
.end());
340 BOOST_TEST(r2
== c2
.end());
342 while (!c1
.empty()) {
343 value_type v
= *c1
.begin();
344 value_type
const* v_ptr
= boost::addressof(*c1
.begin());
345 std::size_t count
= c2
.count(test::get_key
<Container1
>(v
));
346 iterator2 r
= c2
.insert(c1
.extract(c1
.begin()));
347 BOOST_TEST_EQ(c2
.count(test::get_key
<Container1
>(v
)), count
+ 1);
348 BOOST_TEST(r
!= c2
.end());
349 BOOST_TEST(boost::addressof(*r
) == v_ptr
);
355 std::size_t operator()(int x
) const
357 return static_cast<std::size_t>(x
* 13 + 5);
361 UNORDERED_AUTO_TEST (insert_node_handle_unique_tests
) {
363 boost::unordered_set
<int> x1
;
364 boost::unordered_set
<int> x2
;
369 insert_node_handle_unique(x1
, x2
);
370 BOOST_TEST(x2
.size() == 3);
374 boost::unordered_map
<int, int, hash_thing
> x1
;
375 boost::unordered_map
<int, int> x2
;
381 insert_node_handle_unique(x1
, x2
);
382 BOOST_TEST(x2
.size() == 4);
386 UNORDERED_AUTO_TEST (insert_node_handle_equiv_tests
) {
388 boost::unordered_multimap
<int, int, hash_thing
> x1
;
389 boost::unordered_multimap
<int, int> x2
;
396 insert_node_handle_equiv(x1
, x2
);
397 BOOST_TEST(x2
.size() == 6);
401 UNORDERED_AUTO_TEST (insert_node_handle_unique_tests2
) {
403 boost::unordered_set
<int> x1
;
404 boost::unordered_set
<int> x2
;
409 insert_node_handle_unique2(x1
, x2
);
410 BOOST_TEST(x2
.size() == 3);
414 boost::unordered_map
<int, int, hash_thing
> x1
;
415 boost::unordered_map
<int, int> x2
;
421 insert_node_handle_unique2(x1
, x2
);
422 BOOST_TEST(x2
.size() == 4);