1 
2 // Copyright 2006-2010 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)
5 
6 #if !defined(PIECEWISE_TEST_NAME)
7 
8 // clang-format off
9 #include "../helpers/prefix.hpp"
10 #include <boost/unordered_set.hpp>
11 #include <boost/unordered_map.hpp>
12 #include "../helpers/postfix.hpp"
13 // clang-format on
14 
15 #include "../helpers/test.hpp"
16 #include "../objects/test.hpp"
17 #include "../helpers/random_values.hpp"
18 #include "../helpers/tracker.hpp"
19 #include "../helpers/equivalent.hpp"
20 #include "../helpers/invariants.hpp"
21 #include "../helpers/input_iterator.hpp"
22 #include "../helpers/helpers.hpp"
23 
24 namespace insert_tests {
25 
26   test::seed_t initialize_seed(243432);
27 
28   template <class X>
unique_insert_tests1(X *,test::random_generator generator)29   void unique_insert_tests1(X*, test::random_generator generator)
30   {
31     test::check_instances check_;
32 
33     typedef typename X::iterator iterator;
34     typedef test::ordered<X> ordered;
35 
36     UNORDERED_SUB_TEST("insert(value) tests for containers with unique keys")
37     {
38       X x;
39       test::ordered<X> tracker = test::create_ordered(x);
40 
41       test::random_values<X> v(1000, generator);
42 
43       for (typename test::random_values<X>::iterator it = v.begin();
44            it != v.end(); ++it) {
45 
46         typename X::size_type old_bucket_count = x.bucket_count();
47         float b = x.max_load_factor();
48 
49         std::pair<iterator, bool> r1 = x.insert(*it);
50         std::pair<typename ordered::iterator, bool> r2 = tracker.insert(*it);
51 
52         BOOST_TEST(r1.second == r2.second);
53         BOOST_TEST(*r1.first == *r2.first);
54 
55         tracker.compare_key(x, *it);
56 
57         if (static_cast<double>(x.size()) <=
58             b * static_cast<double>(old_bucket_count))
59           BOOST_TEST(x.bucket_count() == old_bucket_count);
60       }
61 
62       test::check_equivalent_keys(x);
63     }
64 
65     UNORDERED_SUB_TEST("insert(rvalue) tests for containers with unique keys")
66     {
67       X x;
68       test::ordered<X> tracker = test::create_ordered(x);
69 
70       test::random_values<X> v(1000, generator);
71 
72       for (typename test::random_values<X>::iterator it = v.begin();
73            it != v.end(); ++it) {
74 
75         typename X::size_type old_bucket_count = x.bucket_count();
76         float b = x.max_load_factor();
77 
78         typename X::value_type value = *it;
79         std::pair<iterator, bool> r1 = x.insert(boost::move(value));
80         std::pair<typename ordered::iterator, bool> r2 = tracker.insert(*it);
81 
82         BOOST_TEST(r1.second == r2.second);
83         BOOST_TEST(*r1.first == *r2.first);
84 
85         tracker.compare_key(x, *it);
86 
87         if (static_cast<double>(x.size()) <=
88             b * static_cast<double>(old_bucket_count))
89           BOOST_TEST(x.bucket_count() == old_bucket_count);
90       }
91 
92       test::check_equivalent_keys(x);
93     }
94   }
95 
96   template <class X>
equivalent_insert_tests1(X *,test::random_generator generator)97   void equivalent_insert_tests1(X*, test::random_generator generator)
98   {
99     test::check_instances check_;
100 
101     UNORDERED_SUB_TEST(
102       "insert(value) tests for containers with equivalent keys")
103     {
104       X x;
105       test::ordered<X> tracker = test::create_ordered(x);
106 
107       test::random_values<X> v(1000, generator);
108       for (typename test::random_values<X>::iterator it = v.begin();
109            it != v.end(); ++it) {
110         typename X::size_type old_bucket_count = x.bucket_count();
111         float b = x.max_load_factor();
112 
113         typename X::iterator r1 = x.insert(*it);
114         typename test::ordered<X>::iterator r2 = tracker.insert(*it);
115 
116         BOOST_TEST(*r1 == *r2);
117 
118         tracker.compare_key(x, *it);
119 
120         if (static_cast<double>(x.size()) <=
121             b * static_cast<double>(old_bucket_count))
122           BOOST_TEST(x.bucket_count() == old_bucket_count);
123       }
124 
125       test::check_equivalent_keys(x);
126     }
127 
128     UNORDERED_SUB_TEST(
129       "insert(rvalue) tests for containers with equivalent keys")
130     {
131       X x;
132       test::ordered<X> tracker = test::create_ordered(x);
133 
134       test::random_values<X> v(1000, generator);
135       for (typename test::random_values<X>::iterator it = v.begin();
136            it != v.end(); ++it) {
137         typename X::size_type old_bucket_count = x.bucket_count();
138         float b = x.max_load_factor();
139 
140         typename X::value_type value = *it;
141         typename X::iterator r1 = x.insert(boost::move(value));
142         typename test::ordered<X>::iterator r2 = tracker.insert(*it);
143 
144         BOOST_TEST(*r1 == *r2);
145 
146         tracker.compare_key(x, *it);
147 
148         if (static_cast<double>(x.size()) <=
149             b * static_cast<double>(old_bucket_count))
150           BOOST_TEST(x.bucket_count() == old_bucket_count);
151       }
152 
153       test::check_equivalent_keys(x);
154     }
155   }
156 
insert_tests2(X *,test::random_generator generator)157   template <class X> void insert_tests2(X*, test::random_generator generator)
158   {
159     typedef typename test::ordered<X> tracker_type;
160     typedef typename X::iterator iterator;
161     typedef typename X::const_iterator const_iterator;
162     typedef typename tracker_type::iterator tracker_iterator;
163 
164     UNORDERED_SUB_TEST("insert(begin(), value) tests")
165     {
166       test::check_instances check_;
167 
168       X x;
169       tracker_type tracker = test::create_ordered(x);
170 
171       test::random_values<X> v(1000, generator);
172       for (typename test::random_values<X>::iterator it = v.begin();
173            it != v.end(); ++it) {
174         typename X::size_type old_bucket_count = x.bucket_count();
175         float b = x.max_load_factor();
176 
177         iterator r1 = x.insert(x.begin(), *it);
178         tracker_iterator r2 = tracker.insert(tracker.begin(), *it);
179         BOOST_TEST(*r1 == *r2);
180         tracker.compare_key(x, *it);
181 
182         if (static_cast<double>(x.size()) <=
183             b * static_cast<double>(old_bucket_count))
184           BOOST_TEST(x.bucket_count() == old_bucket_count);
185       }
186 
187       tracker.compare(x);
188       test::check_equivalent_keys(x);
189     }
190 
191     UNORDERED_SUB_TEST("insert(end(), value) tests")
192     {
193       test::check_instances check_;
194 
195       X x;
196       X const& x_const = x;
197       tracker_type tracker = test::create_ordered(x);
198 
199       test::random_values<X> v(100, generator);
200       for (typename test::random_values<X>::iterator it = v.begin();
201            it != v.end(); ++it) {
202         typename X::size_type old_bucket_count = x.bucket_count();
203         float b = x.max_load_factor();
204 
205         const_iterator r1 = x.insert(x_const.end(), *it);
206         tracker_iterator r2 = tracker.insert(tracker.end(), *it);
207         BOOST_TEST(*r1 == *r2);
208         tracker.compare_key(x, *it);
209 
210         if (static_cast<double>(x.size()) <=
211             b * static_cast<double>(old_bucket_count))
212           BOOST_TEST(x.bucket_count() == old_bucket_count);
213       }
214 
215       tracker.compare(x);
216       test::check_equivalent_keys(x);
217     }
218 
219     UNORDERED_SUB_TEST("insert(pos, value) tests")
220     {
221       test::check_instances check_;
222 
223       X x;
224       const_iterator pos = x.begin();
225       tracker_type tracker = test::create_ordered(x);
226 
227       test::random_values<X> v(1000, generator);
228       for (typename test::random_values<X>::iterator it = v.begin();
229            it != v.end(); ++it) {
230         typename X::size_type old_bucket_count = x.bucket_count();
231         float b = x.max_load_factor();
232 
233         pos = x.insert(pos, *it);
234         tracker_iterator r2 = tracker.insert(tracker.begin(), *it);
235         BOOST_TEST(*pos == *r2);
236         tracker.compare_key(x, *it);
237 
238         if (static_cast<double>(x.size()) <=
239             b * static_cast<double>(old_bucket_count))
240           BOOST_TEST(x.bucket_count() == old_bucket_count);
241       }
242 
243       tracker.compare(x);
244       test::check_equivalent_keys(x);
245     }
246 
247     UNORDERED_SUB_TEST("insert(pos, rvalue) tests")
248     {
249       test::check_instances check_;
250 
251       X x;
252       const_iterator pos = x.begin();
253       tracker_type tracker = test::create_ordered(x);
254 
255       test::random_values<X> v(1000, generator);
256       for (typename test::random_values<X>::iterator it = v.begin();
257            it != v.end(); ++it) {
258         typename X::size_type old_bucket_count = x.bucket_count();
259         float b = x.max_load_factor();
260 
261         typename X::value_type value = *it;
262         pos = x.insert(pos, boost::move(value));
263         tracker_iterator r2 = tracker.insert(tracker.begin(), *it);
264         BOOST_TEST(*pos == *r2);
265         tracker.compare_key(x, *it);
266 
267         if (static_cast<double>(x.size()) <=
268             b * static_cast<double>(old_bucket_count))
269           BOOST_TEST(x.bucket_count() == old_bucket_count);
270       }
271 
272       tracker.compare(x);
273       test::check_equivalent_keys(x);
274     }
275 
276     UNORDERED_SUB_TEST("insert single item range tests")
277     {
278       test::check_instances check_;
279 
280       X x;
281       tracker_type tracker = test::create_ordered(x);
282 
283       test::random_values<X> v(1000, generator);
284       for (typename test::random_values<X>::iterator it = v.begin();
285            it != v.end(); ++it) {
286         typename X::size_type old_bucket_count = x.bucket_count();
287         float b = x.max_load_factor();
288 
289         x.insert(it, test::next(it));
290         tracker.insert(*it);
291         tracker.compare_key(x, *it);
292 
293         if (static_cast<double>(x.size()) <=
294             b * static_cast<double>(old_bucket_count))
295           BOOST_TEST(x.bucket_count() == old_bucket_count);
296       }
297 
298       tracker.compare(x);
299       test::check_equivalent_keys(x);
300     }
301 
302     UNORDERED_SUB_TEST("insert range tests")
303     {
304       test::check_instances check_;
305 
306       X x;
307 
308       test::random_values<X> v(1000, generator);
309       x.insert(v.begin(), v.end());
310 
311       test::check_container(x, v);
312       test::check_equivalent_keys(x);
313     }
314 
315     UNORDERED_SUB_TEST("insert range with rehash tests")
316     {
317       test::check_instances check_;
318 
319       X x;
320 
321       test::random_values<X> v(1000, generator);
322 
323       x.insert(*v.begin());
324       x.clear();
325 
326       x.insert(v.begin(), v.end());
327 
328       test::check_container(x, v);
329       test::check_equivalent_keys(x);
330     }
331 
332     UNORDERED_SUB_TEST("insert input iterator range tests")
333     {
334       test::check_instances check_;
335 
336       X x;
337 
338       test::random_values<X> v(1000, generator);
339       typename test::random_values<X>::const_iterator begin = v.begin(),
340                                                       end = v.end();
341       x.insert(test::input_iterator(begin), test::input_iterator(end));
342       test::check_container(x, v);
343 
344       test::check_equivalent_keys(x);
345     }
346 
347     UNORDERED_SUB_TEST("insert copy iterator range tests")
348     {
349       test::check_instances check_;
350 
351       X x;
352 
353       test::random_values<X> v(1000, generator);
354       x.insert(test::copy_iterator(v.begin()), test::copy_iterator(v.end()));
355       test::check_container(x, v);
356 
357       test::check_equivalent_keys(x);
358     }
359 
360     UNORDERED_SUB_TEST("insert copy iterator range test 2")
361     {
362       test::check_instances check_;
363 
364       X x;
365 
366       test::random_values<X> v1(500, generator);
367       test::random_values<X> v2(500, generator);
368       x.insert(test::copy_iterator(v1.begin()), test::copy_iterator(v1.end()));
369       x.insert(test::copy_iterator(v2.begin()), test::copy_iterator(v2.end()));
370 
371       test::check_equivalent_keys(x);
372     }
373 
374     UNORDERED_SUB_TEST("insert various ranges")
375     {
376       for (int i = 0; i < 100; ++i) {
377         X x;
378         test::ordered<X> tracker = test::create_ordered(x);
379 
380         test::random_values<X> v(1000, generator);
381 
382         for (typename test::random_values<X>::iterator it = v.begin();
383              it != v.end();) {
384           typename X::size_type old_bucket_count = x.bucket_count();
385           float b = x.max_load_factor();
386 
387           typename test::random_values<X>::iterator next = it;
388           for (std::size_t j = test::random_value(20); j > 0; ++j) {
389             ++next;
390             if (next == v.end()) {
391               break;
392             }
393           }
394 
395           x.insert(it, next);
396           tracker.insert(it, next);
397           it = next;
398 
399           tracker.compare(x); // Slow, but I can't see any other way.
400 
401           if (static_cast<double>(x.size()) <=
402               b * static_cast<double>(old_bucket_count))
403             BOOST_TEST(x.bucket_count() == old_bucket_count);
404         }
405 
406         test::check_equivalent_keys(x);
407       }
408     }
409   }
410 
411   template <class X>
unique_emplace_tests1(X *,test::random_generator generator)412   void unique_emplace_tests1(X*, test::random_generator generator)
413   {
414     typedef typename X::iterator iterator;
415     typedef test::ordered<X> ordered;
416 
417     X x;
418     test::ordered<X> tracker = test::create_ordered(x);
419 
420     test::random_values<X> v(1000, generator);
421 
422     for (typename test::random_values<X>::iterator it = v.begin();
423          it != v.end(); ++it) {
424 
425       typename X::size_type old_bucket_count = x.bucket_count();
426       float b = x.max_load_factor();
427 
428       std::pair<iterator, bool> r1 = x.emplace(*it);
429       std::pair<typename ordered::iterator, bool> r2 = tracker.insert(*it);
430 
431       BOOST_TEST(r1.second == r2.second);
432       BOOST_TEST(*r1.first == *r2.first);
433 
434       tracker.compare_key(x, *it);
435 
436       if (static_cast<double>(x.size()) <=
437           b * static_cast<double>(old_bucket_count))
438         BOOST_TEST(x.bucket_count() == old_bucket_count);
439     }
440 
441     tracker.compare(x);
442     test::check_equivalent_keys(x);
443   }
444 
445   template <class X>
equivalent_emplace_tests1(X *,test::random_generator generator)446   void equivalent_emplace_tests1(X*, test::random_generator generator)
447   {
448     X x;
449     test::ordered<X> tracker = test::create_ordered(x);
450 
451     test::random_values<X> v(1000, generator);
452     for (typename test::random_values<X>::iterator it = v.begin();
453          it != v.end(); ++it) {
454       typename X::size_type old_bucket_count = x.bucket_count();
455       float b = x.max_load_factor();
456 
457       typename X::iterator r1 = x.emplace(*it);
458       typename test::ordered<X>::iterator r2 = tracker.insert(*it);
459 
460       BOOST_TEST(*r1 == *r2);
461 
462       tracker.compare_key(x, *it);
463 
464       if (static_cast<double>(x.size()) <=
465           b * static_cast<double>(old_bucket_count))
466         BOOST_TEST(x.bucket_count() == old_bucket_count);
467     }
468 
469     tracker.compare(x);
470     test::check_equivalent_keys(x);
471   }
472 
473   template <class X>
move_emplace_tests(X *,test::random_generator generator)474   void move_emplace_tests(X*, test::random_generator generator)
475   {
476     X x;
477     test::ordered<X> tracker = test::create_ordered(x);
478 
479     test::random_values<X> v(1000, generator);
480 
481     for (typename test::random_values<X>::iterator it = v.begin();
482          it != v.end(); ++it) {
483 
484       typename X::size_type old_bucket_count = x.bucket_count();
485       float b = x.max_load_factor();
486 
487       typename X::value_type value = *it;
488       x.emplace(boost::move(value));
489       tracker.insert(*it);
490       tracker.compare_key(x, *it);
491 
492       if (static_cast<double>(x.size()) <=
493           b * static_cast<double>(old_bucket_count))
494         BOOST_TEST(x.bucket_count() == old_bucket_count);
495     }
496 
497     tracker.compare(x);
498     test::check_equivalent_keys(x);
499   }
500 
default_emplace_tests(X *,test::random_generator)501   template <class X> void default_emplace_tests(X*, test::random_generator)
502   {
503 #if !BOOST_UNORDERED_SUN_WORKAROUNDS1
504     bool is_unique = test::has_unique_keys<X>::value;
505 
506     X x;
507 
508     x.emplace();
509     BOOST_TEST(x.size() == 1);
510     x.emplace();
511     BOOST_TEST(x.size() == (is_unique ? 1u : 2u));
512     x.emplace();
513     BOOST_TEST(x.size() == (is_unique ? 1u : 3u));
514 
515     typename X::value_type y;
516     BOOST_TEST(x.count(test::get_key<X>(y)) == (is_unique ? 1u : 3u));
517     BOOST_TEST(*x.equal_range(test::get_key<X>(y)).first == y);
518 
519     x.emplace(y);
520     BOOST_TEST(x.size() == (is_unique ? 1u : 4u));
521     BOOST_TEST(x.count(test::get_key<X>(y)) == (is_unique ? 1u : 4u));
522     BOOST_TEST(*x.equal_range(test::get_key<X>(y)).first == y);
523 
524     x.clear();
525     BOOST_TEST(x.empty());
526     x.emplace(y);
527     BOOST_TEST(x.size() == 1);
528     x.emplace(y);
529     BOOST_TEST(x.size() == (is_unique ? 1u : 2u));
530 
531     BOOST_TEST(x.count(test::get_key<X>(y)) == (is_unique ? 1u : 2u));
532     BOOST_TEST(*x.equal_range(test::get_key<X>(y)).first == y);
533 #endif
534   }
535 
map_tests(X *,test::random_generator generator)536   template <class X> void map_tests(X*, test::random_generator generator)
537   {
538     X x;
539     test::ordered<X> tracker = test::create_ordered(x);
540 
541     test::random_values<X> v(1000, generator);
542     for (typename test::random_values<X>::iterator it = v.begin();
543          it != v.end(); ++it) {
544       typename X::size_type old_bucket_count = x.bucket_count();
545       float b = x.max_load_factor();
546 
547       x[it->first] = it->second;
548       tracker[it->first] = it->second;
549 
550       tracker.compare_key(x, *it);
551 
552       if (static_cast<double>(x.size()) <=
553           b * static_cast<double>(old_bucket_count))
554         BOOST_TEST(x.bucket_count() == old_bucket_count);
555     }
556 
557     tracker.compare(x);
558     test::check_equivalent_keys(x);
559   }
560 
map_tests2(X *,test::random_generator generator)561   template <class X> void map_tests2(X*, test::random_generator generator)
562   {
563     typedef typename X::iterator iterator;
564 
565     UNORDERED_SUB_TEST("insert_or_assign")
566     {
567       test::check_instances check_;
568 
569       X x;
570       test::ordered<X> tracker = test::create_ordered(x);
571 
572       test::random_values<X> v(1000, generator);
573       for (typename test::random_values<X>::iterator it = v.begin();
574            it != v.end(); ++it) {
575         typename X::size_type old_bucket_count = x.bucket_count();
576         float b = x.max_load_factor();
577 
578         std::pair<iterator, bool> r = x.insert_or_assign(it->first, it->second);
579         BOOST_TEST(*r.first == *it);
580 
581         tracker[it->first] = it->second;
582         tracker.compare_key(x, *it);
583 
584         if (static_cast<double>(x.size()) <
585             b * static_cast<double>(old_bucket_count))
586           BOOST_TEST(x.bucket_count() == old_bucket_count);
587       }
588 
589       tracker.compare(x);
590       test::check_equivalent_keys(x);
591     }
592 
593     UNORDERED_SUB_TEST("insert_or_assign(begin)")
594     {
595       test::check_instances check_;
596 
597       X x;
598       test::ordered<X> tracker = test::create_ordered(x);
599 
600       test::random_values<X> v(1000, generator);
601       for (typename test::random_values<X>::iterator it = v.begin();
602            it != v.end(); ++it) {
603         typename X::size_type old_bucket_count = x.bucket_count();
604         float b = x.max_load_factor();
605 
606         iterator r = x.insert_or_assign(x.begin(), it->first, it->second);
607         BOOST_TEST(*r == *it);
608 
609         tracker[it->first] = it->second;
610         tracker.compare_key(x, *it);
611 
612         if (static_cast<double>(x.size()) <
613             b * static_cast<double>(old_bucket_count))
614           BOOST_TEST(x.bucket_count() == old_bucket_count);
615       }
616 
617       tracker.compare(x);
618       test::check_equivalent_keys(x);
619     }
620 
621     UNORDERED_SUB_TEST("insert_or_assign(end)")
622     {
623       test::check_instances check_;
624 
625       X x;
626       test::ordered<X> tracker = test::create_ordered(x);
627 
628       test::random_values<X> v(1000, generator);
629       for (typename test::random_values<X>::iterator it = v.begin();
630            it != v.end(); ++it) {
631         typename X::size_type old_bucket_count = x.bucket_count();
632         float b = x.max_load_factor();
633 
634         iterator r = x.insert_or_assign(x.end(), it->first, it->second);
635         BOOST_TEST(*r == *it);
636 
637         tracker[it->first] = it->second;
638         tracker.compare_key(x, *it);
639 
640         if (static_cast<double>(x.size()) <
641             b * static_cast<double>(old_bucket_count))
642           BOOST_TEST(x.bucket_count() == old_bucket_count);
643       }
644 
645       tracker.compare(x);
646       test::check_equivalent_keys(x);
647     }
648 
649     UNORDERED_SUB_TEST("insert_or_assign(last)")
650     {
651       test::check_instances check_;
652 
653       X x;
654       test::ordered<X> tracker = test::create_ordered(x);
655       iterator last = x.begin();
656 
657       test::random_values<X> v(1000, generator);
658       for (typename test::random_values<X>::iterator it = v.begin();
659            it != v.end(); ++it) {
660         typename X::size_type old_bucket_count = x.bucket_count();
661         float b = x.max_load_factor();
662 
663         iterator r = x.insert_or_assign(last, it->first, it->second);
664         BOOST_TEST(*r == *it);
665 
666         tracker[it->first] = it->second;
667         tracker.compare_key(x, *it);
668 
669         if (static_cast<double>(x.size()) <
670             b * static_cast<double>(old_bucket_count))
671           BOOST_TEST(x.bucket_count() == old_bucket_count);
672 
673         last = r;
674       }
675 
676       tracker.compare(x);
677       test::check_equivalent_keys(x);
678     }
679   }
680 
681   template <class X>
try_emplace_tests(X *,test::random_generator generator)682   void try_emplace_tests(X*, test::random_generator generator)
683   {
684     typedef typename X::iterator iterator;
685 
686     UNORDERED_SUB_TEST("try_emplace(key, value)")
687     {
688       test::check_instances check_;
689 
690       X x;
691       test::ordered<X> tracker = test::create_ordered(x);
692 
693       test::random_values<X> v(1000, generator);
694       for (typename test::random_values<X>::iterator it = v.begin();
695            it != v.end(); ++it) {
696         typename X::size_type old_bucket_count = x.bucket_count();
697         float b = x.max_load_factor();
698 
699         iterator pos = x.find(it->first);
700         bool found = pos != x.end();
701 
702         std::pair<typename X::iterator, bool> r =
703           x.try_emplace(it->first, it->second);
704         if (found) {
705           BOOST_TEST(pos == r.first);
706           BOOST_TEST(!r.second);
707         } else {
708           BOOST_TEST(r.second);
709         }
710         BOOST_TEST_EQ(r.first->first, it->first);
711         BOOST_TEST_EQ(r.first->second, it->second);
712 
713         tracker.insert(*it);
714         tracker.compare_key(x, *it);
715 
716         if (static_cast<double>(x.size()) <
717             b * static_cast<double>(old_bucket_count))
718           BOOST_TEST(x.bucket_count() == old_bucket_count);
719       }
720 
721       test::check_equivalent_keys(x);
722     }
723 
724     typedef typename X::iterator iterator;
725 
726     UNORDERED_SUB_TEST("try_emplace(begin(), key, value)")
727     {
728       test::check_instances check_;
729 
730       X x;
731       test::ordered<X> tracker = test::create_ordered(x);
732 
733       test::random_values<X> v(1000, generator);
734       for (typename test::random_values<X>::iterator it = v.begin();
735            it != v.end(); ++it) {
736         typename X::size_type old_bucket_count = x.bucket_count();
737         float b = x.max_load_factor();
738 
739         iterator pos = x.find(it->first);
740         bool found = pos != x.end();
741 
742         typename X::iterator r =
743           x.try_emplace(r.begin(), it->first, it->second);
744         if (found) {
745           BOOST_TEST(pos == r);
746         }
747         BOOST_TEST_EQ(r->first, it->first);
748         BOOST_TEST_EQ(r->second, it->second);
749 
750         tracker.insert(*it);
751         tracker.compare_key(x, *it);
752 
753         if (static_cast<double>(x.size()) <
754             b * static_cast<double>(old_bucket_count))
755           BOOST_TEST(x.bucket_count() == old_bucket_count);
756       }
757 
758       test::check_equivalent_keys(x);
759     }
760 
761     typedef typename X::iterator iterator;
762 
763     UNORDERED_SUB_TEST("try_emplace(end(), key, value)")
764     {
765       test::check_instances check_;
766 
767       X x;
768       test::ordered<X> tracker = test::create_ordered(x);
769 
770       test::random_values<X> v(1000, generator);
771       for (typename test::random_values<X>::iterator it = v.begin();
772            it != v.end(); ++it) {
773         typename X::size_type old_bucket_count = x.bucket_count();
774         float b = x.max_load_factor();
775 
776         iterator pos = x.find(it->first);
777         bool found = pos != x.end();
778 
779         typename X::iterator r = x.try_emplace(r.end(), it->first, it->second);
780         if (found) {
781           BOOST_TEST(pos == r);
782         }
783         BOOST_TEST_EQ(r->first, it->first);
784         BOOST_TEST_EQ(r->second, it->second);
785 
786         tracker.insert(*it);
787         tracker.compare_key(x, *it);
788 
789         if (static_cast<double>(x.size()) <
790             b * static_cast<double>(old_bucket_count))
791           BOOST_TEST(x.bucket_count() == old_bucket_count);
792       }
793 
794       test::check_equivalent_keys(x);
795     }
796 
797     typedef typename X::iterator iterator;
798 
799     UNORDERED_SUB_TEST("try_emplace(pos, key, value)")
800     {
801       test::check_instances check_;
802 
803       X x;
804       test::ordered<X> tracker = test::create_ordered(x);
805 
806       test::random_values<X> v(1000, generator);
807       for (typename test::random_values<X>::iterator it = v.begin();
808            it != v.end(); ++it) {
809         typename X::size_type old_bucket_count = x.bucket_count();
810         float b = x.max_load_factor();
811 
812         iterator pos = x.find(it->first);
813         bool found = pos != x.end();
814 
815         typename X::iterator r = x.try_emplace(pos, it->first, it->second);
816         if (found) {
817           BOOST_TEST(pos == r);
818         }
819         BOOST_TEST_EQ(r->first, it->first);
820         BOOST_TEST_EQ(r->second, it->second);
821 
822         tracker.insert(*it);
823         tracker.compare_key(x, *it);
824 
825         if (static_cast<double>(x.size()) <
826             b * static_cast<double>(old_bucket_count))
827           BOOST_TEST(x.bucket_count() == old_bucket_count);
828       }
829 
830       test::check_equivalent_keys(x);
831     }
832   }
833 
834   // Some tests for when the range's value type doesn't match the container's
835   // value type.
836 
837   template <class X>
map_insert_range_test1(X *,test::random_generator generator)838   void map_insert_range_test1(X*, test::random_generator generator)
839   {
840     test::check_instances check_;
841 
842     typedef test::list<
843       std::pair<typename X::key_type, typename X::mapped_type> >
844       list;
845     test::random_values<X> v(1000, generator);
846     list l(v.begin(), v.end());
847 
848     X x;
849     x.insert(l.begin(), l.end());
850 
851     test::check_equivalent_keys(x);
852   }
853 
854   template <class X>
map_insert_range_test2(X *,test::random_generator generator)855   void map_insert_range_test2(X*, test::random_generator generator)
856   {
857     test::check_instances check_;
858 
859     typedef test::list<
860       std::pair<typename X::key_type const, test::implicitly_convertible> >
861       list;
862     test::random_values<
863       boost::unordered_map<typename X::key_type, test::implicitly_convertible> >
864       v(1000, generator);
865     list l(v.begin(), v.end());
866 
867     X x;
868     x.insert(l.begin(), l.end());
869 
870     test::check_equivalent_keys(x);
871   }
872 
873   boost::unordered_set<test::movable, test::hash, test::equal_to,
874     std::allocator<test::movable> >* test_set_std_alloc;
875   boost::unordered_multimap<test::object, test::object, test::hash,
876     test::equal_to, std::allocator<test::object> >* test_multimap_std_alloc;
877 
878   boost::unordered_set<test::object, test::hash, test::equal_to,
879     test::allocator1<test::object> >* test_set;
880   boost::unordered_multiset<test::movable, test::hash, test::equal_to,
881     test::allocator2<test::movable> >* test_multiset;
882   boost::unordered_map<test::movable, test::movable, test::hash, test::equal_to,
883     test::allocator2<test::movable> >* test_map;
884   boost::unordered_multimap<test::object, test::object, test::hash,
885     test::equal_to, test::allocator1<test::object> >* test_multimap;
886 
887   using test::default_generator;
888   using test::generate_collisions;
889   using test::limited_range;
890 
891   UNORDERED_TEST(unique_insert_tests1,
892     ((test_set_std_alloc)(test_set)(test_map))(
893       (default_generator)(generate_collisions)(limited_range)))
894 
895   UNORDERED_TEST(equivalent_insert_tests1,
896     ((test_multimap_std_alloc)(test_multiset)(test_multimap))(
897       (default_generator)(generate_collisions)(limited_range)))
898 
899   UNORDERED_TEST(insert_tests2,
900     ((test_multimap_std_alloc)(test_set)(test_multiset)(test_map)(
901       test_multimap))((default_generator)(generate_collisions)(limited_range)))
902 
903   UNORDERED_TEST(unique_emplace_tests1,
904     ((test_set_std_alloc)(test_set)(test_map))(
905       (default_generator)(generate_collisions)(limited_range)))
906 
907   UNORDERED_TEST(equivalent_emplace_tests1,
908     ((test_multimap_std_alloc)(test_multiset)(test_multimap))(
909       (default_generator)(generate_collisions)(limited_range)))
910 
911   UNORDERED_TEST(move_emplace_tests,
912     ((test_set_std_alloc)(test_multimap_std_alloc)(test_set)(test_map)(
913       test_multiset)(test_multimap))(
914       (default_generator)(generate_collisions)(limited_range)))
915 
916   UNORDERED_TEST(default_emplace_tests,
917     ((test_set_std_alloc)(test_multimap_std_alloc)(test_set)(test_map)(
918       test_multiset)(test_multimap))(
919       (default_generator)(generate_collisions)(limited_range)))
920 
921   UNORDERED_TEST(map_tests,
922     ((test_map))((default_generator)(generate_collisions)(limited_range)))
923 
924   UNORDERED_TEST(
925     map_tests2, ((test_map))((default_generator)(generate_collisions)))
926 
927   UNORDERED_TEST(map_insert_range_test1,
928     ((test_multimap_std_alloc)(test_map)(test_multimap))(
929       (default_generator)(generate_collisions)(limited_range)))
930 
931   UNORDERED_TEST(map_insert_range_test2,
932     ((test_multimap_std_alloc)(test_map)(test_multimap))(
933       (default_generator)(generate_collisions)(limited_range)))
934 
935 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
936 
937   struct initialize_from_two_ints
938   {
939     int a, b;
940 
hash_value(initialize_from_two_ints const & x)941     friend std::size_t hash_value(initialize_from_two_ints const& x)
942     {
943       return static_cast<std::size_t>(x.a + x.b);
944     }
945 
operator ==insert_tests::initialize_from_two_ints946     bool operator==(initialize_from_two_ints const& x) const
947     {
948       return a == x.a && b == x.b;
949     }
950   };
951 
UNORDERED_AUTO_TEST(insert_initializer_list_set)952   UNORDERED_AUTO_TEST (insert_initializer_list_set) {
953     boost::unordered_set<int> set;
954     set.insert({1, 2, 3, 1});
955     BOOST_TEST_EQ(set.size(), 3u);
956     BOOST_TEST(set.find(1) != set.end());
957     BOOST_TEST(set.find(4) == set.end());
958 
959     boost::unordered_set<initialize_from_two_ints> set2;
960 
961 #if defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 5))
962     set2.insert({{1, 2}});
963 #else
964     set2.insert({1, 2});
965 #endif
966     BOOST_TEST(set2.size() == 1);
967     BOOST_TEST(set2.find({1, 2}) != set2.end());
968     BOOST_TEST(set2.find({2, 1}) == set2.end());
969 
970     set2.insert({{3, 4}, {5, 6}, {7, 8}});
971     BOOST_TEST(set2.size() == 4);
972     BOOST_TEST(set2.find({1, 2}) != set2.end());
973     BOOST_TEST(set2.find({3, 4}) != set2.end());
974     BOOST_TEST(set2.find({5, 6}) != set2.end());
975     BOOST_TEST(set2.find({7, 8}) != set2.end());
976     BOOST_TEST(set2.find({8, 7}) == set2.end());
977 
978     set2.insert({{2, 1}, {3, 4}});
979     BOOST_TEST(set2.size() == 5);
980     BOOST_TEST(set2.find({1, 2}) != set2.end());
981     BOOST_TEST(set2.find({2, 1}) != set2.end());
982     BOOST_TEST(set2.find({3, 4}) != set2.end());
983     BOOST_TEST(set2.find({5, 6}) != set2.end());
984     BOOST_TEST(set2.find({7, 8}) != set2.end());
985     BOOST_TEST(set2.find({8, 7}) == set2.end());
986   }
987 
988 #if !BOOST_WORKAROUND(BOOST_MSVC, == 1800)
989 
UNORDERED_AUTO_TEST(insert_initializer_list_multiset)990   UNORDERED_AUTO_TEST (insert_initializer_list_multiset) {
991     boost::unordered_multiset<std::string> multiset;
992     // multiset.insert({});
993     BOOST_TEST(multiset.empty());
994     multiset.insert({"a"});
995     BOOST_TEST_EQ(multiset.size(), 1u);
996     BOOST_TEST(multiset.find("a") != multiset.end());
997     BOOST_TEST(multiset.find("b") == multiset.end());
998     multiset.insert({"a", "b"});
999     BOOST_TEST(multiset.size() == 3);
1000     BOOST_TEST_EQ(multiset.count("a"), 2u);
1001     BOOST_TEST_EQ(multiset.count("b"), 1u);
1002     BOOST_TEST_EQ(multiset.count("c"), 0u);
1003   }
1004 
1005 #endif
1006 
UNORDERED_AUTO_TEST(insert_initializer_list_map)1007   UNORDERED_AUTO_TEST (insert_initializer_list_map) {
1008     boost::unordered_map<std::string, std::string> map;
1009     // map.insert({});
1010     BOOST_TEST(map.empty());
1011     map.insert({{"a", "b"}, {"a", "b"}, {"d", ""}});
1012     BOOST_TEST_EQ(map.size(), 2u);
1013   }
1014 
UNORDERED_AUTO_TEST(insert_initializer_list_multimap)1015   UNORDERED_AUTO_TEST (insert_initializer_list_multimap) {
1016     boost::unordered_multimap<std::string, std::string> multimap;
1017     // multimap.insert({});
1018     BOOST_TEST(multimap.empty());
1019     multimap.insert({{"a", "b"}, {"a", "b"}, {"d", ""}});
1020     BOOST_TEST_EQ(multimap.size(), 3u);
1021     BOOST_TEST_EQ(multimap.count("a"), 2u);
1022   }
1023 
1024 #endif
1025 
1026   struct overloaded_constructor
1027   {
overloaded_constructorinsert_tests::overloaded_constructor1028     overloaded_constructor(int x1_ = 1, int x2_ = 2, int x3_ = 3, int x4_ = 4)
1029         : x1(x1_), x2(x2_), x3(x3_), x4(x4_)
1030     {
1031     }
1032 
1033     int x1, x2, x3, x4;
1034 
operator ==insert_tests::overloaded_constructor1035     bool operator==(overloaded_constructor const& rhs) const
1036     {
1037       return x1 == rhs.x1 && x2 == rhs.x2 && x3 == rhs.x3 && x4 == rhs.x4;
1038     }
1039 
hash_value(overloaded_constructor const & x)1040     friend std::size_t hash_value(overloaded_constructor const& x)
1041     {
1042       std::size_t hash = 0;
1043       boost::hash_combine(hash, x.x1);
1044       boost::hash_combine(hash, x.x2);
1045       boost::hash_combine(hash, x.x3);
1046       boost::hash_combine(hash, x.x4);
1047       return hash;
1048     }
1049   };
1050 
UNORDERED_AUTO_TEST(map_emplace_test)1051   UNORDERED_AUTO_TEST (map_emplace_test) {
1052     {
1053       boost::unordered_map<int, overloaded_constructor, test::hash,
1054         test::equal_to,
1055         test::allocator1<std::pair<int const, overloaded_constructor> > >
1056         x;
1057 
1058 #if !BOOST_UNORDERED_SUN_WORKAROUNDS1
1059       x.emplace();
1060       BOOST_TEST(
1061         x.find(0) != x.end() && x.find(0)->second == overloaded_constructor());
1062 #endif
1063 
1064       x.emplace(2, 3);
1065       BOOST_TEST(
1066         x.find(2) != x.end() && x.find(2)->second == overloaded_constructor(3));
1067 
1068       x.try_emplace(5);
1069       BOOST_TEST(
1070         x.find(5) != x.end() && x.find(5)->second == overloaded_constructor());
1071     }
1072 
1073     {
1074       boost::unordered_multimap<int, overloaded_constructor, test::hash,
1075         test::equal_to,
1076         test::allocator1<std::pair<int const, overloaded_constructor> > >
1077         x;
1078 
1079 #if !BOOST_UNORDERED_SUN_WORKAROUNDS1
1080       x.emplace();
1081       BOOST_TEST(
1082         x.find(0) != x.end() && x.find(0)->second == overloaded_constructor());
1083 #endif
1084 
1085       x.emplace(2, 3);
1086       BOOST_TEST(
1087         x.find(2) != x.end() && x.find(2)->second == overloaded_constructor(3));
1088     }
1089   }
1090 
UNORDERED_AUTO_TEST(set_emplace_test)1091   UNORDERED_AUTO_TEST (set_emplace_test) {
1092     boost::unordered_set<overloaded_constructor> x;
1093     overloaded_constructor check;
1094 
1095 #if !BOOST_UNORDERED_SUN_WORKAROUNDS1
1096     x.emplace();
1097     BOOST_TEST(x.find(check) != x.end() && *x.find(check) == check);
1098 #endif
1099 
1100     x.clear();
1101     x.emplace(1);
1102     check = overloaded_constructor(1);
1103     BOOST_TEST(x.find(check) != x.end() && *x.find(check) == check);
1104 
1105     x.clear();
1106     x.emplace(2, 3);
1107     check = overloaded_constructor(2, 3);
1108     BOOST_TEST(x.find(check) != x.end() && *x.find(check) == check);
1109 
1110     x.clear();
1111     x.emplace(4, 5, 6);
1112     check = overloaded_constructor(4, 5, 6);
1113     BOOST_TEST(x.find(check) != x.end() && *x.find(check) == check);
1114 
1115     x.clear();
1116     x.emplace(7, 8, 9, 10);
1117     check = overloaded_constructor(7, 8, 9, 10);
1118     BOOST_TEST(x.find(check) != x.end() && *x.find(check) == check);
1119   }
1120 
1121   struct derived_from_piecewise_construct_t
1122     : boost::unordered::piecewise_construct_t
1123   {
1124   };
1125 
piecewise_rvalue()1126   derived_from_piecewise_construct_t piecewise_rvalue()
1127   {
1128     return derived_from_piecewise_construct_t();
1129   }
1130 
1131   struct convertible_to_piecewise
1132   {
operator boost::unordered::piecewise_construct_tinsert_tests::convertible_to_piecewise1133     operator boost::unordered::piecewise_construct_t() const
1134     {
1135       return boost::unordered::piecewise_construct;
1136     }
1137   };
1138 
UNORDERED_AUTO_TEST(map_emplace_test2)1139   UNORDERED_AUTO_TEST (map_emplace_test2) {
1140     // Emulating piecewise construction with boost::tuple bypasses the
1141     // allocator's construct method, but still uses test destroy method.
1142     test::detail::disable_construction_tracking _scoped;
1143 
1144     {
1145       boost::unordered_map<overloaded_constructor, overloaded_constructor,
1146         boost::hash<overloaded_constructor>,
1147         std::equal_to<overloaded_constructor>,
1148         test::allocator1<
1149           std::pair<overloaded_constructor const, overloaded_constructor> > >
1150         x;
1151 
1152       x.emplace(boost::unordered::piecewise_construct, boost::make_tuple(),
1153         boost::make_tuple());
1154       BOOST_TEST(
1155         x.find(overloaded_constructor()) != x.end() &&
1156         x.find(overloaded_constructor())->second == overloaded_constructor());
1157 
1158       x.emplace(
1159         convertible_to_piecewise(), boost::make_tuple(1), boost::make_tuple());
1160       BOOST_TEST(
1161         x.find(overloaded_constructor(1)) != x.end() &&
1162         x.find(overloaded_constructor(1))->second == overloaded_constructor());
1163 
1164       x.emplace(piecewise_rvalue(), boost::make_tuple(2, 3),
1165         boost::make_tuple(4, 5, 6));
1166       BOOST_TEST(x.find(overloaded_constructor(2, 3)) != x.end() &&
1167                  x.find(overloaded_constructor(2, 3))->second ==
1168                    overloaded_constructor(4, 5, 6));
1169 
1170       derived_from_piecewise_construct_t d;
1171       x.emplace(d, boost::make_tuple(9, 3, 1), boost::make_tuple(10));
1172       BOOST_TEST(x.find(overloaded_constructor(9, 3, 1)) != x.end() &&
1173                  x.find(overloaded_constructor(9, 3, 1))->second ==
1174                    overloaded_constructor(10));
1175 
1176       x.clear();
1177 
1178       x.try_emplace(overloaded_constructor());
1179       BOOST_TEST(
1180         x.find(overloaded_constructor()) != x.end() &&
1181         x.find(overloaded_constructor())->second == overloaded_constructor());
1182 
1183       x.try_emplace(1);
1184       BOOST_TEST(
1185         x.find(overloaded_constructor(1)) != x.end() &&
1186         x.find(overloaded_constructor(1))->second == overloaded_constructor());
1187 
1188       x.try_emplace(overloaded_constructor(2, 3), 4, 5, 6);
1189       BOOST_TEST(x.find(overloaded_constructor(2, 3)) != x.end() &&
1190                  x.find(overloaded_constructor(2, 3))->second ==
1191                    overloaded_constructor(4, 5, 6));
1192 
1193       x.clear();
1194 
1195       x.try_emplace(x.begin(), overloaded_constructor());
1196       BOOST_TEST(
1197         x.find(overloaded_constructor()) != x.end() &&
1198         x.find(overloaded_constructor())->second == overloaded_constructor());
1199 
1200       x.try_emplace(x.end(), 1);
1201       BOOST_TEST(
1202         x.find(overloaded_constructor(1)) != x.end() &&
1203         x.find(overloaded_constructor(1))->second == overloaded_constructor());
1204 
1205       x.try_emplace(x.begin(), overloaded_constructor(2, 3), 4, 5, 6);
1206       BOOST_TEST(x.find(overloaded_constructor(2, 3)) != x.end() &&
1207                  x.find(overloaded_constructor(2, 3))->second ==
1208                    overloaded_constructor(4, 5, 6));
1209     }
1210 
1211     {
1212       boost::unordered_multimap<overloaded_constructor, overloaded_constructor,
1213         boost::hash<overloaded_constructor>,
1214         std::equal_to<overloaded_constructor>,
1215         test::allocator1<
1216           std::pair<overloaded_constructor const, overloaded_constructor> > >
1217         x;
1218 
1219       x.emplace(boost::unordered::piecewise_construct, boost::make_tuple(),
1220         boost::make_tuple());
1221       BOOST_TEST(
1222         x.find(overloaded_constructor()) != x.end() &&
1223         x.find(overloaded_constructor())->second == overloaded_constructor());
1224 
1225       x.emplace(
1226         convertible_to_piecewise(), boost::make_tuple(1), boost::make_tuple());
1227       BOOST_TEST(
1228         x.find(overloaded_constructor(1)) != x.end() &&
1229         x.find(overloaded_constructor(1))->second == overloaded_constructor());
1230 
1231       x.emplace(piecewise_rvalue(), boost::make_tuple(2, 3),
1232         boost::make_tuple(4, 5, 6));
1233       BOOST_TEST(x.find(overloaded_constructor(2, 3)) != x.end() &&
1234                  x.find(overloaded_constructor(2, 3))->second ==
1235                    overloaded_constructor(4, 5, 6));
1236 
1237       derived_from_piecewise_construct_t d;
1238       x.emplace(d, boost::make_tuple(9, 3, 1), boost::make_tuple(10));
1239       BOOST_TEST(x.find(overloaded_constructor(9, 3, 1)) != x.end() &&
1240                  x.find(overloaded_constructor(9, 3, 1))->second ==
1241                    overloaded_constructor(10));
1242     }
1243   }
1244 
UNORDERED_AUTO_TEST(set_emplace_test2)1245   UNORDERED_AUTO_TEST (set_emplace_test2) {
1246     boost::unordered_set<
1247       std::pair<overloaded_constructor, overloaded_constructor> >
1248       x;
1249     std::pair<overloaded_constructor, overloaded_constructor> check;
1250 
1251     x.emplace(boost::unordered::piecewise_construct, boost::make_tuple(),
1252       boost::make_tuple());
1253     BOOST_TEST(x.find(check) != x.end() && *x.find(check) == check);
1254 
1255     x.clear();
1256     x.emplace(boost::unordered::piecewise_construct, boost::make_tuple(1),
1257       boost::make_tuple(2, 3));
1258     check =
1259       std::make_pair(overloaded_constructor(1), overloaded_constructor(2, 3));
1260     BOOST_TEST(x.find(check) != x.end() && *x.find(check) == check);
1261   }
1262 
1263 // Use the preprocessor to generate tests using different combinations of
1264 // boost/std piecewise_construct_t/tuple.
1265 
1266 #define PIECEWISE_TEST_NAME boost_tuple_piecewise_tests
1267 #define PIECEWISE_NAMESPACE boost::unordered
1268 #define TUPLE_NAMESPACE boost
1269 #define EMULATING_PIECEWISE_CONSTRUCTION 1
1270 #include "./insert_tests.cpp"
1271 
1272 #if BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT
1273 
1274 #define PIECEWISE_TEST_NAME boost_tuple_std_piecewise_tests
1275 #define PIECEWISE_NAMESPACE std
1276 #define TUPLE_NAMESPACE boost
1277 #define EMULATING_PIECEWISE_CONSTRUCTION 1
1278 #include "./insert_tests.cpp"
1279 
1280 #endif
1281 
1282 #if !defined(BOOST_NO_CXX11_HDR_TUPLE)
1283 
1284 #define PIECEWISE_TEST_NAME std_tuple_boost_piecewise_tests
1285 #define PIECEWISE_NAMESPACE boost::unordered
1286 #define TUPLE_NAMESPACE std
1287 #define EMULATING_PIECEWISE_CONSTRUCTION 0
1288 #include "./insert_tests.cpp"
1289 
1290 #endif
1291 
1292 #if !defined(BOOST_NO_CXX11_HDR_TUPLE) &&                                      \
1293   BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT
1294 
1295 #define PIECEWISE_TEST_NAME std_piecewise_tests
1296 #define PIECEWISE_NAMESPACE std
1297 #define TUPLE_NAMESPACE std
1298 #define EMULATING_PIECEWISE_CONSTRUCTION 0
1299 #include "./insert_tests.cpp"
1300 
1301 #endif
1302 }
1303 
1304 RUN_TESTS_QUIET()
1305 
1306 #else // PIECEWISE_TEST_NAME
1307 
1308 UNORDERED_AUTO_TEST (PIECEWISE_TEST_NAME) {
1309 #if EMULATING_PIECEWISE_CONSTRUCTION
1310   test::detail::disable_construction_tracking _scoped;
1311 #endif
1312 
1313   {
1314     boost::unordered_map<overloaded_constructor, overloaded_constructor,
1315       boost::hash<overloaded_constructor>,
1316       std::equal_to<overloaded_constructor>,
1317       test::allocator1<
1318         std::pair<overloaded_constructor const, overloaded_constructor> > >
1319       x;
1320 
1321     x.emplace(PIECEWISE_NAMESPACE::piecewise_construct,
1322       TUPLE_NAMESPACE::make_tuple(), TUPLE_NAMESPACE::make_tuple());
1323     BOOST_TEST(
1324       x.find(overloaded_constructor()) != x.end() &&
1325       x.find(overloaded_constructor())->second == overloaded_constructor());
1326 
1327     x.emplace(convertible_to_piecewise(), TUPLE_NAMESPACE::make_tuple(1),
1328       TUPLE_NAMESPACE::make_tuple());
1329     BOOST_TEST(
1330       x.find(overloaded_constructor(1)) != x.end() &&
1331       x.find(overloaded_constructor(1))->second == overloaded_constructor());
1332 
1333     x.emplace(piecewise_rvalue(), TUPLE_NAMESPACE::make_tuple(2, 3),
1334       TUPLE_NAMESPACE::make_tuple(4, 5, 6));
1335     BOOST_TEST(x.find(overloaded_constructor(2, 3)) != x.end() &&
1336                x.find(overloaded_constructor(2, 3))->second ==
1337                  overloaded_constructor(4, 5, 6));
1338 
1339     derived_from_piecewise_construct_t d;
1340     x.emplace(
1341       d, TUPLE_NAMESPACE::make_tuple(9, 3, 1), TUPLE_NAMESPACE::make_tuple(10));
1342     BOOST_TEST(x.find(overloaded_constructor(9, 3, 1)) != x.end() &&
1343                x.find(overloaded_constructor(9, 3, 1))->second ==
1344                  overloaded_constructor(10));
1345 
1346     x.clear();
1347 
1348     x.try_emplace(overloaded_constructor());
1349     BOOST_TEST(
1350       x.find(overloaded_constructor()) != x.end() &&
1351       x.find(overloaded_constructor())->second == overloaded_constructor());
1352 
1353     x.try_emplace(1);
1354     BOOST_TEST(
1355       x.find(overloaded_constructor(1)) != x.end() &&
1356       x.find(overloaded_constructor(1))->second == overloaded_constructor());
1357 
1358     x.try_emplace(overloaded_constructor(2, 3), 4, 5, 6);
1359     BOOST_TEST(x.find(overloaded_constructor(2, 3)) != x.end() &&
1360                x.find(overloaded_constructor(2, 3))->second ==
1361                  overloaded_constructor(4, 5, 6));
1362   }
1363   {
1364     boost::unordered_multimap<overloaded_constructor, overloaded_constructor,
1365       boost::hash<overloaded_constructor>,
1366       std::equal_to<overloaded_constructor>,
1367       test::allocator1<
1368         std::pair<overloaded_constructor const, overloaded_constructor> > >
1369       x;
1370 
1371     x.emplace(PIECEWISE_NAMESPACE::piecewise_construct,
1372       TUPLE_NAMESPACE::make_tuple(), TUPLE_NAMESPACE::make_tuple());
1373     BOOST_TEST(
1374       x.find(overloaded_constructor()) != x.end() &&
1375       x.find(overloaded_constructor())->second == overloaded_constructor());
1376 
1377     x.emplace(convertible_to_piecewise(), TUPLE_NAMESPACE::make_tuple(1),
1378       TUPLE_NAMESPACE::make_tuple());
1379     BOOST_TEST(
1380       x.find(overloaded_constructor(1)) != x.end() &&
1381       x.find(overloaded_constructor(1))->second == overloaded_constructor());
1382 
1383     x.emplace(piecewise_rvalue(), TUPLE_NAMESPACE::make_tuple(2, 3),
1384       TUPLE_NAMESPACE::make_tuple(4, 5, 6));
1385     BOOST_TEST(x.find(overloaded_constructor(2, 3)) != x.end() &&
1386                x.find(overloaded_constructor(2, 3))->second ==
1387                  overloaded_constructor(4, 5, 6));
1388 
1389     derived_from_piecewise_construct_t d;
1390     x.emplace(
1391       d, TUPLE_NAMESPACE::make_tuple(9, 3, 1), TUPLE_NAMESPACE::make_tuple(10));
1392     BOOST_TEST(x.find(overloaded_constructor(9, 3, 1)) != x.end() &&
1393                x.find(overloaded_constructor(9, 3, 1))->second ==
1394                  overloaded_constructor(10));
1395   }
1396 }
1397 
1398 UNORDERED_AUTO_TEST (BOOST_PP_CAT(PIECEWISE_TEST_NAME, 2)) {
1399 #if EMULATING_PIECEWISE_CONSTRUCTION
1400   test::detail::disable_construction_tracking _scoped;
1401 #endif
1402 
1403   boost::unordered_set<
1404     std::pair<overloaded_constructor, overloaded_constructor> >
1405     x;
1406   std::pair<overloaded_constructor, overloaded_constructor> check;
1407 
1408   x.emplace(PIECEWISE_NAMESPACE::piecewise_construct,
1409     TUPLE_NAMESPACE::make_tuple(), TUPLE_NAMESPACE::make_tuple());
1410   BOOST_TEST(x.find(check) != x.end() && *x.find(check) == check);
1411 
1412   x.clear();
1413   x.emplace(PIECEWISE_NAMESPACE::piecewise_construct,
1414     TUPLE_NAMESPACE::make_tuple(1), TUPLE_NAMESPACE::make_tuple(2, 3));
1415   check =
1416     std::make_pair(overloaded_constructor(1), overloaded_constructor(2, 3));
1417   BOOST_TEST(x.find(check) != x.end() && *x.find(check) == check);
1418 }
1419 
1420 #undef PIECEWISE_TEST_NAME
1421 #undef PIECEWISE_NAMESPACE
1422 #undef TUPLE_NAMESPACE
1423 #undef EMULATING_PIECEWISE_CONSTRUCTION
1424 
1425 #endif
1426