Compare commits

...

322 Commits

Author SHA1 Message Date
joaquintides
37168ad39a removed overzealous inlines 2022-10-27 19:48:13 +02:00
joaquintides
40ced996fd reverted 2022-10-27 19:13:01 +02:00
joaquintides
b5df79599e deinlined pow2_quadratic_prober::next 2022-10-27 18:57:48 +02:00
joaquintides
231f9785ff reverted 2022-10-27 18:56:18 +02:00
joaquintides
dd6e0439f9 suppressed call to key_from (experiment) 2022-10-27 18:42:47 +02:00
joaquintides
00a9266096 reverted 2022-10-27 18:41:21 +02:00
joaquintides
f9b1a5f105 added cast 2022-10-27 18:26:46 +02:00
joaquintides
bb30498399 s/unchecked_countr_zero/__builtin_ctz 2022-10-27 18:22:46 +02:00
joaquintides
bfd11a70a0 reverted 2022-10-27 18:16:26 +02:00
joaquintides
3aff6ba0e6 streamlined mixing into find (experiment) 2022-10-27 18:01:16 +02:00
joaquintides
b314cf1659 reverted 2022-10-27 17:50:34 +02:00
joaquintides
ac1de3c0af inlined type policy functions 2022-10-27 13:36:14 +02:00
joaquintides
4190720406 reverted 2022-10-27 13:23:50 +02:00
joaquintides
07b452b4d4 s/prefetch_elements/prefe 2022-10-27 12:53:29 +02:00
joaquintides
bfde38c58b reverted 2022-10-27 12:51:26 +02:00
joaquintides
dfadb54df3 removed explicit bool cast in find_impl 2022-10-27 12:32:18 +02:00
joaquintides
883789611c inlined h, pred, al accessors 2022-10-27 12:27:17 +02:00
joaquintides
5e639a97a4 passed BOOST_UNORDERED_ASSUME a true boolean 2022-10-26 10:39:34 +02:00
joaquintides
fb315252b3 added missing BOOST_FORCEINLINE 2022-10-25 19:53:18 +02:00
joaquintides
d12ed06c3d removed #ifdef'd out code 2022-10-25 19:53:03 +02:00
joaquintides
49fc08b934 refactored emplace_impl to improve inlining 2022-10-25 19:48:19 +02:00
Christian Mazakas
4f0edf9013 Decorate containers with more BOOST_FORCEINLINE 2022-10-25 09:01:38 -07:00
joaquintides
2afd1c5c9a copied Neon group15::is_sentinel from foa_unordered_rc.hpp
(possible performance impact)
2022-10-25 14:45:38 +02:00
joaquintides
492df9c9c6 restored uint64.cpp 2022-10-25 14:33:07 +02:00
joaquintides
e29bf7a4a0 reverted 2022-10-25 14:31:27 +02:00
joaquintides
7db310f6d2 reverted 0b575dc983 (may affect performance) 2022-10-25 11:48:41 +02:00
Christian Mazakas
1f781a407e Test cleanup 2022-10-24 15:05:49 -07:00
Christian Mazakas
ef54c6bd14 Clean up u64 benchmarks 2022-10-24 15:04:24 -07:00
Christian Mazakas
fb1b1dfe2d Add missing copyright updates 2022-10-24 11:31:25 -07:00
Christian Mazakas
222f0a737d Split AppVeyor jobs to avoid timeouts 2022-10-24 11:17:37 -07:00
Christian Mazakas
6c0d121e5b Update requirements for testing to include support for alignas(N) 2022-10-24 11:17:24 -07:00
Christian Mazakas
955dab4637 Add missing init_type overloads for insert(hint) 2022-10-24 11:17:05 -07:00
Christian Mazakas
375d7157b6 Add tests for missing typedefs in flat containers 2022-10-24 09:54:57 -07:00
Christian Mazakas
01053738eb Rewrite test constraints in terms of config checks 2022-10-24 08:21:54 -07:00
joaquintides
d8f226d429 reverted "Push up partial refactor for older msvc"
This reverts commit 627ffe4ed7.
2022-10-22 12:28:04 +02:00
Christian Mazakas
627ffe4ed7 Push up partial refactor for older msvc 2022-10-21 15:38:19 -07:00
Christian Mazakas
2adab2be61 Fix signed-unsigned comparison warning 2022-10-21 15:37:51 -07:00
Christian Mazakas
e0b680ac29 Update insert(Iterator, Iterator) overloads to use emplace internally instead of insert()'ing 2022-10-21 11:24:34 -07:00
Christian Mazakas
ad1e3a49a5 Update tracking counts to be unsigned in init_type_insert_tests 2022-10-21 11:23:46 -07:00
joaquintides
1d15067ef2 removed sign conversion warnings 2022-10-21 13:14:39 +02:00
joaquintides
8a3e5dd918 added workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56480 2022-10-21 11:13:13 +02:00
joaquintides
2aa62c63c1 stylistic 2022-10-21 10:46:22 +02:00
joaquintides
c9d1b6009e stylistic 2022-10-21 10:02:49 +02:00
joaquintides
1d553447a0 refactored insert overloads 2022-10-21 10:01:51 +02:00
Christian Mazakas
703f8d1065 Delete boost-level headers as they're no longer considered idiomatic and update all tests to use the test/helpers/unorderd.hpp header where applicable 2022-10-20 15:25:40 -07:00
Christian Mazakas
fe32f153a2 Add draft of insert(init_type&&) for unordered_flat_map 2022-10-20 14:59:33 -07:00
Christian Mazakas
59f4da0a47 Add init_type public typedefs 2022-10-20 14:58:38 -07:00
joaquintides
99ad45ed77 removed spurious consts 2022-10-20 20:02:55 +02:00
joaquintides
d93875a65e refactored value_from and insert overloads 2022-10-20 19:48:17 +02:00
Christian Mazakas
c1d5902911 Remove unnecessary value_type conversion by expanding overloads for value_from() 2022-10-20 08:43:42 -07:00
Christian Mazakas
0ac4aeca50 Add swap_exception_tests for FOA, only testing weak exception guarantee 2022-10-19 11:05:09 -07:00
Christian Mazakas
776935f24d Reintroduce strong guarantee checking 2022-10-19 11:04:38 -07:00
joaquintides
2f048ea6ac s/=/== 2022-10-19 17:50:21 +02:00
joaquintides
f3353c9be3 made sure source values are destroyed on copy-based rehash 2022-10-19 17:42:59 +02:00
joaquintides
3d07c33efe Merge branch 'feature/foa_rc' of https://github.com/boostorg/unordered into feature/foa_rc 2022-10-19 15:47:47 +02:00
joaquintides
8a1562cc78 implemented strong exception guarantee on rehash and single insert/emplace 2022-10-19 15:46:57 +02:00
Christian Mazakas
4de1be8911 Add the rest of the exception tests sans swap 2022-10-18 15:54:02 -07:00
Christian Mazakas
46065065be Temporarily disable strong checks for FOA 2022-10-18 15:54:02 -07:00
joaquintides
8e42367a62 stylistic 2022-10-18 19:33:52 +02:00
joaquintides
d13a9dcaaf stylistic 2022-10-18 18:35:41 +02:00
joaquintides
64cb43ce32 protected against hash throwing in nosize_transfer_element 2022-10-18 17:42:22 +02:00
joaquintides
c9340390b0 completed previous commit 2022-10-18 17:28:57 +02:00
joaquintides
c76f44a8b3 hardened unchecked_rehash against exceptions thrown in the middle of value move construction 2022-10-18 16:18:05 +02:00
joaquintides
2290375515 replaced try blocks with scope guards 2022-10-18 16:14:29 +02:00
joaquintides
a200af610f refactored table's allocator-extended copy tor 2022-10-18 15:41:33 +02:00
joaquintides
2cb1d2bdf0 removed duplicated call to destroy 2022-10-18 15:25:54 +02:00
joaquintides
ac2bc8d615 made group initialization more straightforward 2022-10-18 12:17:40 +02:00
Christian Mazakas
0d6ebb4d2f Add copy_exception_tests for FOA 2022-10-17 13:27:36 -07:00
Christian Mazakas
27c386d47b Revert "used regular method for group resetting in clear"
This reverts commit eb5351b2c6.
2022-10-17 13:20:01 -07:00
Christian Mazakas
cf6f4023bb Make sure mask is properly cleared during rehash cleanup 2022-10-17 13:19:57 -07:00
Christian Mazakas
aa41ab4195 Add constructor_exception tests for FOA 2022-10-17 13:19:29 -07:00
joaquintides
6e4e5ead03 made Neon group15 compatible with A32 2022-10-17 18:43:48 +02:00
joaquintides
eb5351b2c6 used regular method for group resetting in clear 2022-10-17 18:21:41 +02:00
joaquintides
599dee204f micro-optimized table destruction 2022-10-17 18:00:15 +02:00
joaquintides
6b1d2f13da made clear reset overflow bytes 2022-10-17 17:51:43 +02:00
joaquintides
b0f6bb128f micro-optimized group loops 2022-10-17 09:43:22 +02:00
joaquintides
0389e0bc16 reverted 2022-10-16 22:17:53 +02:00
joaquintides
9246c30178 activated alternative impl of nosize_unchecked_emplace_at 2022-10-16 21:33:40 +02:00
joaquintides
bb6b57d1a4 typo 2022-10-16 17:45:17 +02:00
joaquintides
4fa61b98eb made rehash work with exact capacities, refactored capacity calculations 2022-10-16 10:11:47 +02:00
joaquintides
5535faf3cc introduced internal noshrink_reserve 2022-10-15 18:56:46 +02:00
joaquintides
ec389cdecd kept adding design/implementation notes 2022-10-15 18:33:59 +02:00
joaquintides
7c5bad60c6 reordered #includes 2022-10-15 13:14:32 +02:00
joaquintides
cc75360f4c kept adding design/implementation notes 2022-10-15 12:38:39 +02:00
joaquintides
3a0b752363 reorganized function definitions 2022-10-15 11:17:51 +02:00
joaquintides
63eaed843f stylistic 2022-10-15 11:15:29 +02:00
joaquintides
0b575dc983 s/const/constexpr in simde_mm_movemask_epi8 2022-10-15 11:14:36 +02:00
joaquintides
b8d4df2b5c stylistic 2022-10-15 11:07:48 +02:00
joaquintides
3bf28d7b61 stylistic 2022-10-15 11:06:15 +02:00
joaquintides
acc7f0ce5c refactored table_arrays dummy groups handling 2022-10-15 11:05:51 +02:00
joaquintides
1532e301d1 micro-optimized non-SIMD group15::match_impl 2022-10-15 10:51:28 +02:00
joaquintides
e663812f24 editorial 2022-10-15 10:18:47 +02:00
Christian Mazakas
9da61e9050 Add post_move_tests 2022-10-14 13:37:26 -07:00
Christian Mazakas
1de8801c08 Add scary_tests 2022-10-14 13:37:26 -07:00
Christian Mazakas
e16537d244 Add helper header to include map types based on FOA vs FCA 2022-10-14 13:37:26 -07:00
Christian Mazakas
14c190223c Add scoped_allocator tests 2022-10-14 13:37:26 -07:00
Christian Mazakas
e3c91ad812 Add erase_if tests 2022-10-14 13:37:26 -07:00
Christian Mazakas
454cb24cc8 Ease test requiremets for erase_if, require copyability now of supplied predicate 2022-10-14 13:37:26 -07:00
Christian Mazakas
5e24f6ef22 Add reserve_tests 2022-10-14 13:37:26 -07:00
Christian Mazakas
d02d4094e6 Add merge_tests 2022-10-14 13:37:26 -07:00
joaquintides
9a03d1e904 added design and implementation notes 2022-10-14 20:00:24 +02:00
joaquintides
3683b43242 [skip CI] editorial 2022-10-14 13:52:37 +02:00
joaquintides
fc5c8c3669 removed unused typedef 2022-10-14 13:40:56 +02:00
joaquintides
df32d79e8a shut down VS warning 2022-10-14 13:30:49 +02:00
joaquintides
aefb5dd66a fixed unordered_flat_map::map_types::move 2022-10-14 10:40:07 +02:00
joaquintides
f85e04ef31 stylistic 2022-10-14 10:30:53 +02:00
joaquintides
8c58ffe546 made sure BOOST_[UN]LIKELY is passed a boolean everywhere 2022-10-14 10:16:47 +02:00
Christian Mazakas
d538f6184c Add equivalent_keys_tests 2022-10-13 11:59:44 -07:00
Christian Mazakas
7339f4264a Undo bad commits to Jamfile, gitignore 2022-10-13 11:58:20 -07:00
Christian Mazakas
87674d000b Update map_types to strip const from key, value parameters so that init_type is more efficient and extract() returns a const reference unconditionally 2022-10-13 11:39:18 -07:00
Christian Mazakas
6227ae49a7 Update find_impl() to ignore warnings about unsigned-signed casting when KeyEqual returns an unsinged integral type 2022-10-13 10:23:36 -07:00
Christian Mazakas
c39ed8a5cf Add simple_tests 2022-10-12 15:19:11 -07:00
Christian Mazakas
d4f7939aae Add incomplete_test 2022-10-12 14:30:07 -07:00
Christian Mazakas
fc7b5573c1 Add link_test 2022-10-12 14:05:25 -07:00
Christian Mazakas
1c14bc1215 Use explicit cast for when KeyEqual returns a size_t type 2022-10-12 13:39:43 -07:00
Christian Mazakas
4399e8b360 Add noexcept tests 2022-10-12 13:39:23 -07:00
Christian Mazakas
3f9bd00f01 Add compile_map tests 2022-10-12 13:37:12 -07:00
Christian Mazakas
05b3025c0e Fix regression in how the table_iterator defines its reference type 2022-10-12 08:58:32 -07:00
joaquintides
becd166e66 implemented erase_if 2022-10-12 15:34:05 +02:00
joaquintides
006f62047b reverted 334dcb91ac 2022-10-12 12:46:47 +02:00
joaquintides
334dcb91ac removed unused typedef 2022-10-12 11:20:37 +02:00
joaquintides
df7792040c implemented merge 2022-10-12 11:18:05 +02:00
joaquintides
57ea45cb8f overloaded for_all_elements 2022-10-12 10:31:52 +02:00
Christian Mazakas
4a8d687778 Add compile_set tests with stub for merge() 2022-10-11 15:21:10 -07:00
Christian Mazakas
ccd40d0c44 Update fancy pointer's implementation of pointer_to to support all types by using boost::addressof() 2022-10-11 15:21:10 -07:00
joaquintides
35118b5a71 reverted 2022-10-11 20:35:59 +02:00
joaquintides
858737fd88 s/move/forward in brace-init insert 2022-10-11 17:55:55 +02:00
joaquintides
648fb7b99d reverted two prior 2022-10-11 17:30:23 +02:00
joaquintides
59c84cb744 dropped BOOST_FORCEINLINE in brace-init insert 2022-10-11 17:20:22 +02:00
joaquintides
becd6078b3 temporarily used value_type&& for brace-init insert 2022-10-11 17:10:39 +02:00
joaquintides
e163aa465c reverted c7836659d1 2022-10-11 11:51:16 +02:00
joaquintides
3b1f635926 reverted c4cc805063 2022-10-11 11:50:17 +02:00
joaquintides
7abd7bb36d reverted 2022-10-11 11:48:46 +02:00
joaquintides
545ad4f7ad temporarily s/init_type/value_type in brace-init insert 2022-10-11 10:54:01 +02:00
joaquintides
c42d86ac0d reverted 2022-10-11 10:52:51 +02:00
joaquintides
316eeea983 dropped BOOST_FORCEINLINE in insert 2022-10-11 10:46:07 +02:00
joaquintides
f2afbe9f85 silenced unused capture warning 2022-10-11 09:09:20 +02:00
Christian Mazakas
e9a94cb62a Force inlining for find() member functions in the flat containers 2022-10-10 15:47:00 -07:00
Christian Mazakas
91f5925c41 Replace naked throw statements with boost::throw_exception() 2022-10-10 15:43:38 -07:00
Christian Mazakas
0bdfa3c39e Add forwarding tests 2022-10-10 14:18:11 -07:00
Christian Mazakas
09f0b7c0a8 Add swap_tests 2022-10-10 14:18:11 -07:00
Christian Mazakas
72bca09429 Remove extraneous usage of typename 2022-10-10 14:18:11 -07:00
Christian Mazakas
58b78f8ff0 Add transparent_tests 2022-10-10 14:18:11 -07:00
Christian Mazakas
1ff2dc4042 Add contains_tests 2022-10-10 14:18:11 -07:00
Christian Mazakas
05f9668597 Refactor transparent type traits into their own header so they can be shared with FOA impl 2022-10-10 14:18:11 -07:00
joaquintides
c7836659d1 activated alt impl of nosize_unchecked_emplace_at 2022-10-10 21:45:53 +02:00
joaquintides
c4cc805063 embed xmx code directly into xmx_mix 2022-10-10 21:06:33 +02:00
joaquintides
9e2bf3681f embedded hash into mixing policies 2022-10-10 20:51:47 +02:00
joaquintides
77f265a678 reverted 2022-10-10 20:19:39 +02:00
joaquintides
6bda467942 temporarily disabled mix_policy 2022-10-10 19:52:14 +02:00
joaquintides
1fa2e84774 reverted 7caab66011 and f776ffa008 2022-10-10 19:24:14 +02:00
joaquintides
7caab66011 removed inline suggestion from hash_for 2022-10-10 19:01:55 +02:00
joaquintides
69aff6f776 restored 16f86b0770 2022-10-10 18:55:03 +02:00
joaquintides
505a08cf95 temporarily reverted 16f86b0770 2022-10-10 18:34:45 +02:00
joaquintides
f776ffa008 removed temporary const ref in emplace_impl 2022-10-10 18:02:57 +02:00
joaquintides
a4c38c02c8 fixed empty_value index 2022-10-10 11:13:32 +02:00
joaquintides
889a81f034 stylistic 2022-10-10 09:36:12 +02:00
joaquintides
ad96ea632e stylistic 2022-10-10 09:34:10 +02:00
joaquintides
2955a966cf shut down unavoidable VS warning 2022-10-10 09:29:41 +02:00
joaquintides
3fbaf21b8c dropped hash_traits in favor of individual traits 2022-10-09 11:23:15 +02:00
joaquintides
32a7ed74e8 added missing const qualifier 2022-10-08 12:39:36 +02:00
joaquintides
3913fce638 dropped foa_mixer in favor of internal mix policy governed by hash_traits 2022-10-08 11:47:00 +02:00
joaquintides
16f86b0770 relied on implicit conversion for second overload of value_from 2022-10-08 10:18:20 +02:00
Christian Mazakas
2907083b73 Fixup implementation of equality operator 2022-10-07 15:31:16 -07:00
Christian Mazakas
1fa823d815 Fix erroneous usage of boost::is_convertible instead of std::is_convertible 2022-10-07 14:59:15 -07:00
Christian Mazakas
6e8e2112ba Rearrange SFINAE to appease msvc-14.0 in erase() member function template 2022-10-07 14:51:40 -07:00
Christian Mazakas
9560d10771 Fix shadowing warning in early gcc 2022-10-07 14:19:32 -07:00
Christian Mazakas
e543818e3e Add equality_tests 2022-10-07 14:15:32 -07:00
Christian Mazakas
e0bb258b39 Add load_factor_tests 2022-10-07 10:56:47 -07:00
Christian Mazakas
d3ef0b9a4f Add rehash tests 2022-10-07 10:56:35 -07:00
Christian Mazakas
86d623a0f4 Pull mlf into detail::foa namespace for testing 2022-10-07 10:55:52 -07:00
Christian Mazakas
b964fa777c Add at_tests 2022-10-07 10:16:57 -07:00
joaquintides
cde017f791 added missing typename 2022-10-07 19:02:25 +02:00
joaquintides
d1982a664b stylistic 2022-10-07 18:56:41 +02:00
joaquintides
7e479d62dc added foa_mixer.hpp 2022-10-07 18:56:16 +02:00
joaquintides
6be32f3ba4 reverted 74c2ae627a and explicitly silenced VS warning 2022-10-07 16:38:19 +02:00
joaquintides
049a1ec8f6 reverted b3754b10c8 and 5fc929b829 and s/{}/() in arrays initialization 2022-10-07 16:32:57 +02:00
joaquintides
b3754b10c8 extended 5fc929b829 to member arrays 2022-10-07 13:50:02 +02:00
joaquintides
7441be730e removed spurious #include 2022-10-07 13:47:54 +02:00
joaquintides
38f9cb750a s/value_type/init_type 2022-10-07 12:17:16 +02:00
joaquintides
8a9aab57c0 s/std::move/type_policy::move in a couple of places 2022-10-07 12:15:24 +02:00
joaquintides
b61ec3a65a removed moved_type import (not used explicitly) 2022-10-07 12:10:14 +02:00
joaquintides
74c2ae627a avoided VS constant conditional expression warning 2022-10-07 11:34:13 +02:00
joaquintides
74ca1e50f3 return one lambda expression back in place (related to f1eb5d2106) 2022-10-07 11:27:54 +02:00
joaquintides
5fc929b829 initialized ml at ctor body (GCC 4.8/4.9 complains otherwise) 2022-10-07 11:23:05 +02:00
joaquintides
3aaf895514 restricted erase generic arg as per C++23 requirements
(hopefully fixes test errors in VS2015)
2022-10-07 11:19:20 +02:00
joaquintides
2057ccaeb5 stylistic 2022-10-07 10:44:28 +02:00
Christian Mazakas
dc7b8f3ff2 Remove extraneous overloads of key_from 2022-10-06 12:04:21 -07:00
Christian Mazakas
2b7e9d826d Fix warning in msvc-14.3 with C++20 about multiple implicit conversions being applied 2022-10-06 12:03:59 -07:00
joaquintides
c57470e0d3 SFINAED out third key_from overload and fixed insert accepted arg types 2022-10-06 20:02:03 +02:00
Christian Mazakas
6b1379a992 Update SFINAE to handle the case of the init_type and moved_type being the same 2022-10-06 10:45:49 -07:00
Christian Mazakas
f1eb5d2106 Workaround visibility bug in gcc-6 by un-nesting lambdas 2022-10-06 09:56:12 -07:00
Christian Mazakas
ad248ab76a Fix maybe-uninitialized warning in emplace_tests by explicitly initializing all data members of emplace_value 2022-10-06 09:55:26 -07:00
Christian Mazakas
f4888c7940 Enable C++11 builds 2022-10-06 09:55:26 -07:00
joaquintides
d02b12c9a1 redesigned init_type/value_type machinery 2022-10-06 17:50:30 +02:00
Christian Mazakas
2cf9d5ac4c Add extra value_type() construction in range-based iterator insertion so implicitly convertible types are supported, i.e. test::proxy 2022-10-05 14:56:49 -07:00
Christian Mazakas
f3803fc071 Add emplace_tests 2022-10-05 13:31:10 -07:00
Christian Mazakas
a3c6235f3a Add insert_hint_tests 2022-10-05 13:30:59 -07:00
Christian Mazakas
7501eefd87 Updated unordered flat container to use declval instead of allocator_traits as old versions of clang don't have is_always_equal 2022-10-05 13:29:48 -07:00
Christian Mazakas
2134116cbc Update test jamfile to use a build_foa command 2022-10-05 13:24:54 -07:00
joaquintides
b86143de46 made one overload of insert generic so that value_type is accepted 2022-10-05 20:38:51 +02:00
joaquintides
7c8045aab5 fixed init_type machinery 2022-10-05 18:46:38 +02:00
joaquintides
c15bd0092d introduced init_type/value_type 2022-10-05 18:09:57 +02:00
joaquintides
d233d83811 allow 100% fillup for small capacities 2022-10-05 14:49:42 +02:00
joaquintides
df0c375541 s/std::allocator_traits/boost::allocator_traits 2022-10-05 13:58:31 +02:00
joaquintides
886b1b4ded refactored table_arrays to solve alignment issues without an extra data member 2022-10-05 13:54:28 +02:00
joaquintides
48816135df refactored move assignment to silence warnings 2022-10-05 10:05:10 +02:00
joaquintides
4d0f698937 stylistic 2022-10-05 09:34:21 +02:00
Christian Mazakas
fdbc79d2a8 Silence -Werror=terminate warning in move assignment 2022-10-04 14:52:38 -07:00
Christian Mazakas
1a89b0aa14 Add missing size swap() call to move-assign operator for foa::table 2022-10-04 14:52:18 -07:00
Christian Mazakas
8e9b7cf259 Add move semantics to FOA containers 2022-10-04 14:51:45 -07:00
Christian Mazakas
bf6643844b Add foa_move_tests 2022-10-04 14:51:03 -07:00
Christian Mazakas
e9c3ed1531 Remove unnecessary self-alias checks in copy-assignment operators 2022-10-04 14:49:40 -07:00
Christian Mazakas
7dfcdc6da8 Split move_tests into post_move_tests so testing with the new FOA containers is feasible 2022-10-04 14:38:31 -07:00
Christian Mazakas
9ad7096851 Add missing assign_test cases 2022-10-04 11:48:09 -07:00
Christian Mazakas
4cdfb2537a Implement erase(), get erase_tests passing 2022-10-04 11:48:09 -07:00
Christian Mazakas
9280e13697 Add erase_tests 2022-10-04 11:48:09 -07:00
Christian Mazakas
21872edf83 Disable FOA tests for C++98 2022-10-04 11:48:09 -07:00
joaquintides
b7e021ffc6 silenced VS warning C4714 2022-10-04 18:47:23 +02:00
joaquintides
e69bb3aece unnamed unused parameters 2022-10-04 13:46:27 +02:00
joaquintides
06512a00e1 refactored bdfe294e61 and expanded to move assign and swap 2022-10-04 11:24:21 +02:00
Christian Mazakas
bdfe294e61 Add temporary polyfill for foa table's assignment operator so that the definition of the allocator copy-assignment operator isn't required 2022-10-03 14:47:41 -07:00
Christian Mazakas
ddb9f370af Update load_factor() impl to handle the case when capacity() is zero 2022-10-03 14:46:45 -07:00
Christian Mazakas
b0c0384401 Fix small typo in increment() function to silence VS warnings 2022-10-03 14:46:19 -07:00
Christian Mazakas
bf6e381ff2 Add expliicit destructors, copy assignment operators 2022-10-03 14:45:42 -07:00
Christian Mazakas
d5fcc77579 Add assign_tests 2022-10-03 14:45:02 -07:00
Christian Mazakas
b0097982af Remove config checks, just rotely disable tests for unsupported C++ versions 2022-10-03 12:17:46 -07:00
joaquintides
2e3a8a0fc0 avoided VS warning C4706 2022-10-03 21:05:48 +02:00
joaquintides
357eed44a1 replaced homegrown ebo_base with boost::empty_value 2022-10-03 19:36:53 +02:00
joaquintides
2ae70cd05c Merge branch 'feature/foa_rc' of https://github.com/boostorg/unordered into feature/foa_rc 2022-10-03 18:50:15 +02:00
joaquintides
d370ae1095 stopped relying on __STDCPP_DEFAULT_NEW_ALIGNMENT__ for now 2022-10-03 18:49:24 +02:00
Christian Mazakas
5c48ad9a79 Update test Jamfile to use cxx14_constexpr as a requirement for targets so msvc gets run 2022-10-03 08:08:02 -07:00
joaquintides
621b5b4ec1 shut down bogus VS warning 2022-10-02 11:14:19 +02:00
joaquintides
4dbc83ccbf documented VS specific bit 2022-10-02 11:13:49 +02:00
joaquintides
398a64b5e0 shut down unavoidable GCC shadowing warnings 2022-10-02 11:13:04 +02:00
joaquintides
b926dbbbe9 eliminated shadowed declaration 2022-10-01 19:37:16 +02:00
joaquintides
b244b33402 EBO-optimized table 2022-10-01 19:34:33 +02:00
joaquintides
f2e4b25615 silenced conversion warning 2022-10-01 17:33:55 +02:00
joaquintides
29f2f1db2c added missing BOOST_RETHROWs 2022-10-01 12:58:37 +02:00
joaquintides
cec09e1c61 fixed alignment issues apparent 32bit builds 2022-10-01 12:44:33 +02:00
joaquintides
36a42116e8 supported unaligned metadata access where potentially happening,
plus fixed some superfluous alignas specifiers
2022-09-30 17:06:31 +02:00
joaquintides
d9dcaf8ba1 tried different formulation of prior 2022-09-30 16:17:40 +02:00
joaquintides
984cf13afd reintroduced 6110a0827c with a slightly different syntax
(prior caused ICEs on GCC11)
2022-09-30 16:15:11 +02:00
joaquintides
ac41bf6e86 temporarily reverted 6110a0827c 2022-09-30 16:09:14 +02:00
joaquintides
5f21e3964e temporarily omitted _mm_loadu_si128 2022-09-30 13:57:49 +02:00
joaquintides
364cd86191 temporarily omitted alignas specifier 2022-09-30 13:52:25 +02:00
joaquintides
b1449ca502 added unaligned load of __m128i 2022-09-30 12:27:10 +02:00
Christian Mazakas
6110a0827c Fix default initialiation warning for clang-3.7, clang-3.8 2022-09-29 13:57:16 -07:00
Christian Mazakas
71b64139da Add copy_tests 2022-09-29 13:46:03 -07:00
Christian Mazakas
3582ac91d7 Silence conversion warning in foa 2022-09-29 13:45:51 -07:00
Christian Mazakas
30997bd9ef Add constructor_tests 2022-09-29 12:50:56 -07:00
Christian Mazakas
cb673135d2 Use static_cast to silence conversion warnings 2022-09-29 11:40:13 -07:00
Christian Mazakas
6ac1cf1a5f Add find_tests 2022-09-29 11:19:17 -07:00
Christian Mazakas
8f29a32a33 Simplify range-based insert() so it doesn't eagerly rehash so that insert_tests pass 2022-09-29 11:18:59 -07:00
Christian Mazakas
ac3520791e Clean up insert_tests 2022-09-29 11:17:22 -07:00
Christian Mazakas
faa6e91ed2 Fix conversion warning in reserve() 2022-09-29 11:16:58 -07:00
joaquintides
86956b0be1 added non-SIMD support 2022-09-29 19:24:15 +02:00
joaquintides
fdc39982f3 fixed trivial error in #ifdefd-out code 2022-09-29 10:49:27 +02:00
Christian Mazakas
c37cfacb44 Finally get insert_tests passing for flat map/set 2022-09-28 13:49:38 -07:00
Christian Mazakas
3af53a6598 Flesh out unordered_flat_map for insert_tests 2022-09-28 13:49:17 -07:00
Christian Mazakas
19c500de27 Silence conversion warning in foa table's emplace_impl() 2022-09-28 13:48:49 -07:00
Christian Mazakas
855d538ea3 Fix typo in foa table's empty() implementation 2022-09-28 13:48:21 -07:00
Christian Mazakas
6b1ef16e38 Add unordered_flat_set 2022-09-28 13:47:51 -07:00
Christian Mazakas
1577da25cc Add proper flat_map header + forwarding header 2022-09-28 13:47:00 -07:00
joaquintides
c44695eb37 reverted 2022-09-28 20:48:30 +02:00
joaquintides
63fdf67568 un-inlined pow2_quadratic_prober memfuns to see it impacts performance 2022-09-28 20:19:08 +02:00
joaquintides
80cb7281ba reverted 2022-09-28 20:08:41 +02:00
joaquintides
cefe5965be micro-optimized table_iterator ctor to see if it impacts performance 2022-09-28 19:52:22 +02:00
joaquintides
2a9f47ea2c reverted 2022-09-28 19:23:39 +02:00
joaquintides
85324f9a43 made microchange in find_impl to see if it impacts performance 2022-09-28 19:13:26 +02:00
joaquintides
2e776ad155 fixed clear 2022-09-28 17:53:58 +02:00
joaquintides
f6544f69ca fixed macro usage 2022-09-28 17:26:12 +02:00
joaquintides
c61222403e fixed using placement 2022-09-28 17:24:44 +02:00
joaquintides
c487f24611 honored select_on_container_copy_construction 2022-09-28 13:55:44 +02:00
joaquintides
8dcd40c8f3 harmonized adjust_hash interface 2022-09-28 13:46:25 +02:00
joaquintides
0ea2cb5a7a refactored dummy_groups to avoid explicit array initialization 2022-09-28 11:47:23 +02:00
joaquintides
5a4a2f3ffd added Neon support 2022-09-28 11:21:44 +02:00
joaquintides
5293b328b7 made emplace_impl rehashing more robust 2022-09-28 10:05:45 +02:00
joaquintides
2889aab226 made dependency on size_policy minimum size explicit 2022-09-28 09:54:44 +02:00
joaquintides
7a1a25991f removed unnecessary check in max_load 2022-09-28 09:45:55 +02:00
joaquintides
43f8e5e933 avoided being too smart in new_arrays's memory initialization 2022-09-28 09:42:37 +02:00
joaquintides
f4940d9344 avoided ugly casts in table_iterator::increment 2022-09-28 09:40:05 +02:00
joaquintides
701cdff982 refactored dummy_groups 2022-09-28 09:36:52 +02:00
Christian Mazakas
450c915284 Get insert_tests passing under sanitizers 2022-09-27 14:25:57 -07:00
Christian Mazakas
892e437428 Restructure insert_tests invocations 2022-09-27 10:34:04 -07:00
Christian Mazakas
8905157c1e Update uint64 benchmarks to profile the new container, its internal table and the rc15 release candidate 2022-09-27 10:30:39 -07:00
Christian Mazakas
2eb57995dd Add initial find() impl for benchmarks 2022-09-27 10:30:14 -07:00
Christian Mazakas
b64b88eb65 Add intial erase() impl for benchmarks 2022-09-27 10:28:50 -07:00
Christian Mazakas
3da4b6411c Add rvalue overload of insert() for flat_map 2022-09-27 10:28:10 -07:00
Christian Mazakas
e115634812 Fix bug in equal_range() for unordered_flat_map 2022-09-27 10:27:41 -07:00
Christian Mazakas
fc0f354df4 Switch from leading underscore to trailing underscore for shadowed variables 2022-09-27 08:19:01 -07:00
Christian Mazakas
ba5cbd5ca6 Add simple initial draft of unordered_flat_map 2022-09-26 15:18:13 -07:00
Christian Mazakas
505b060637 Update insert_tests to handle new open-addressing table implementation 2022-09-26 15:17:54 -07:00
Christian Mazakas
12b9bd0a6d Fix warnings in internal foa table about float/size_t conversions 2022-09-26 15:17:21 -07:00
Christian Mazakas
e8715ffb96 Update internal foa table implementation to use to_address when Allocators use fancy pointers 2022-09-26 15:16:52 -07:00
Christian Mazakas
5d34b137a3 Fix shadowing warnings in foa.hpp 2022-09-26 11:40:47 -07:00
Christian Mazakas
ad352a6703 Fix cast warning in mark_overflow() 2022-09-26 10:27:22 -07:00
Christian Mazakas
7d69d18473 Initial commit of foa.hpp 2022-09-26 10:12:05 -07:00
joaquintides
668abe4b0a Merge pull request #146 from cmazakas/feature/rehash-doc-updates
Rehash Doc Updates
2022-09-15 19:33:54 +02:00
Christian Mazakas
5dcccfda3b Update docs for rehash/reserve for unordered_multimap 2022-09-15 07:59:53 -07:00
Christian Mazakas
56b271850a Update docs for rehash/reserve for unordered_multiset 2022-09-15 07:59:53 -07:00
Christian Mazakas
d338e94267 Update docs for rehash/reserve for unordered_set 2022-09-15 07:59:53 -07:00
Christian Mazakas
42abfe3c7d Update docs for rehash/reserve for unordered_map 2022-09-15 07:59:53 -07:00
joaquintides
6ef6540378 Merge pull request #144 from cmazakas/feature/rehashing-conformity
Rehashing Conformity
2022-09-13 23:53:15 +02:00
Christian Mazakas
9a9b8e0a7b Update rehashing implementation to better reflect STL conformance 2022-09-13 12:33:21 -07:00
Christian Mazakas
5ad86f559f Clean up implementation of recalculate_max_load() to avoid std::floor/std::ceil 2022-09-13 12:33:21 -07:00
Christian Mazakas
a8b0e19a33 Update rehashing tests to better stress test them for conformity with libc++ and other STL implementations 2022-09-13 12:33:21 -07:00
joaquintides
2b61fbb8df Merge pull request #145 from cmazakas/bugfix/noexcept-move-assign
Fix move assign noexcept violation/perf regression
2022-09-13 20:46:38 +02:00
Christian Mazakas
dea6ce164c Remove erroneous unconditional call to reserve() from move_assign() when pocma is false 2022-09-12 13:16:45 -07:00
Christian Mazakas
9ebb705e75 Update noexcept_tests to cover both values of POCMA and to also test move-assigning into larger and smaller hash tables 2022-09-12 13:16:45 -07:00
Christian Mazakas
010dfa52e3 Merge pull request #143 from cmazakas/feature/no-alloc-default-construction
Update internal table to no longer allocate on default constructions and when the bucket count is 0
2022-08-31 09:21:13 -07:00
Christian Mazakas
db9d9d1f77 Update implementation to support a default-constructible table and grouped_bucket_array 2022-08-30 15:20:31 -07:00
Christian Mazakas
6f342bf119 Set default_bucket_count to zero 2022-08-30 15:20:31 -07:00
Christian Mazakas
48765e82e0 Update tests to account for a default-constructed container having no buckets 2022-08-30 15:20:31 -07:00
Peter Dimov
f141cd1dea Merge pull request #141 from cmazakas/fix/appveyor-timeout
Split 64-bit mingw appveyor job into two to help prevent timeouts
2022-08-20 11:21:40 +03:00
Christian Mazakas
6258856d2b Split 64-bit mingw appveyor job into two to help prevent timeouts 2022-08-19 13:31:02 -07:00
Peter Dimov
c93ea188f7 Merge pull request #142 from sdarwin/droneconfig
drone.jsonnet update
2022-08-19 23:15:26 +03:00
sdarwin
329eb419f5 drone.jsonnet update 2022-08-19 10:58:56 -06:00
Peter Dimov
e83c42ca26 Merge pull request #140 from boostorg/bugfix/valid-post-move
Fix use-after-move segfault
2022-08-19 00:54:07 +03:00
Christian Mazakas
f9eae4153f Update code to be valid when the internal buckets_ data member is moved-from 2022-08-18 09:04:53 -07:00
Christian Mazakas
7b41f4783f Update value type used by test allocators in move_tests so that the STL containers can be swapped in 2022-08-17 14:12:29 -07:00
Christian Mazakas
7227cfc68a Add post-move tests to verify the container is valid after a move 2022-08-17 14:12:29 -07:00
61 changed files with 6781 additions and 493 deletions

View File

@@ -42,7 +42,12 @@ environment:
- FLAVOR: Visual Studio 2017
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
B2_CXXSTD: 14,17,latest
B2_CXXSTD: 14,17
B2_TOOLSET: msvc-14.1
- FLAVOR: Visual Studio 2017
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
B2_CXXSTD: latest
B2_TOOLSET: msvc-14.1
- FLAVOR: cygwin (32-bit)
@@ -63,7 +68,7 @@ environment:
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022
ADDPATH: C:\cygwin64\bin;
B2_ADDRESS_MODEL: 64
B2_CXXSTD: 03,11
B2_CXXSTD: 03
B2_TOOLSET: gcc
B2_FLAGS: "include=libs/unordered/test/unordered include=libs/unordered/test/exception"
@@ -71,21 +76,51 @@ environment:
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022
ADDPATH: C:\cygwin64\bin;
B2_ADDRESS_MODEL: 64
B2_CXXSTD: 14,1z
B2_CXXSTD: 11
B2_TOOLSET: gcc
B2_FLAGS: "include=libs/unordered/test/unordered include=libs/unordered/test/exception"
- FLAVOR: cygwin (64-bit, latest)
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022
ADDPATH: C:\cygwin64\bin;
B2_ADDRESS_MODEL: 64
B2_CXXSTD: 14
B2_TOOLSET: gcc
B2_FLAGS: "include=libs/unordered/test/unordered include=libs/unordered/test/exception"
- FLAVOR: cygwin (64-bit, latest)
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022
ADDPATH: C:\cygwin64\bin;
B2_ADDRESS_MODEL: 64
B2_CXXSTD: 1z
B2_TOOLSET: gcc
B2_FLAGS: "include=libs/unordered/test/unordered include=libs/unordered/test/exception"
- FLAVOR: mingw-w64, 32 bit
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
ADDPATH: C:\mingw-w64\i686-8.1.0-posix-dwarf-rt_v6-rev0\mingw32\bin;
B2_CXXSTD: 03,11,14,17,2a
B2_CXXSTD: 03,11,14
B2_TOOLSET: gcc
B2_ADDRESS_MODEL: 32
- FLAVOR: mingw-w64, 32 bit
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
ADDPATH: C:\mingw-w64\i686-8.1.0-posix-dwarf-rt_v6-rev0\mingw32\bin;
B2_CXXSTD: 17,2a
B2_TOOLSET: gcc
B2_ADDRESS_MODEL: 32
- FLAVOR: mingw-w64, 64 bit
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
ADDPATH: C:\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\bin;
B2_CXXSTD: 03,11,14,17,2a
B2_CXXSTD: 03,11,14
B2_TOOLSET: gcc
B2_ADDRESS_MODEL: 64
- FLAVOR: mingw-w64, 64 bit
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
ADDPATH: C:\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\bin;
B2_CXXSTD: 17,2a
B2_TOOLSET: gcc
B2_ADDRESS_MODEL: 64

View File

@@ -32,6 +32,7 @@ local linux_pipeline(name, image, environment, packages = "", sources = [], arch
commands:
[
'set -e',
'uname -a',
'wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add -',
] +
(if sources != [] then [ ('apt-add-repository "' + source + '"') for source in sources ] else []) +
@@ -63,6 +64,7 @@ local macos_pipeline(name, environment, xcode_version = "12.2", osx_version = "c
environment: environment + { "DEVELOPER_DIR": "/Applications/Xcode-" + xcode_version + ".app/Contents/Developer" },
commands:
[
'uname -a',
'export LIBRARY=' + library,
'./.drone/drone.sh',
]
@@ -89,6 +91,7 @@ local windows_pipeline(name, image, environment, arch = "amd64") =
environment: environment,
commands:
[
'echo $env:DRONE_STAGE_MACHINE',
'cmd /C .drone\\\\drone.bat ' + library,
]
}
@@ -168,8 +171,9 @@ local windows_pipeline(name, image, environment, arch = "amd64") =
),
macos_pipeline(
"MacOS 10.15 Xcode 12.2 ASAN",
"MacOS 12.4 Xcode 13.4.1 ASAN",
{ TOOLSET: 'clang', COMPILER: 'clang++', CXXSTD: '03,11,14,1z' } + asan,
xcode_version = "13.4.1", osx_version = "monterey",
),
windows_pipeline(

View File

@@ -5,6 +5,7 @@
# https://www.boost.org/LICENSE_1_0.txt
set -ex
export PATH=~/.local/bin:/usr/local/bin:$PATH
DRONE_BUILD_DIR=$(pwd)

View File

@@ -1566,7 +1566,9 @@ Effects:;; Changes the container's maximum load factor, using `z` as a hint.
void rehash(size_type n);
```
Changes the number of buckets so that there at least `n` buckets, and so that the load factor is less than the maximum load factor.
Changes the number of buckets so that there are at least `n` buckets, and so that the load factor is less than or equal to the maximum load factor. When applicable, this will either grow or shrink the `bucket_count()` associated with the container.
When `size() == 0`, `rehash(0)` will deallocate the underlying buckets array.
Invalidates iterators, and changes the order of elements. Pointers and references to elements are not invalidated.
@@ -1580,6 +1582,10 @@ Throws:;; The function has no effect if an exception is thrown, unless it is thr
void reserve(size_type n);
```
Equivalent to `a.rehash(ceil(n / a.max_load_factor()))`, or `a.rehash(1)` if `n > 0` and `a.max_load_factor() == std::numeric_limits<float>::infinity()`.
Similar to `rehash`, this function can be used to grow or shrink the number of buckets in the container.
Invalidates iterators, and changes the order of elements. Pointers and references to elements are not invalidated.
[horizontal]

View File

@@ -1345,7 +1345,9 @@ Effects:;; Changes the container's maximum load factor, using `z` as a hint.
void rehash(size_type n);
```
Changes the number of buckets so that there at least `n` buckets, and so that the load factor is less than the maximum load factor.
Changes the number of buckets so that there are at least `n` buckets, and so that the load factor is less than or equal to the maximum load factor. When applicable, this will either grow or shrink the `bucket_count()` associated with the container.
When `size() == 0`, `rehash(0)` will deallocate the underlying buckets array.
Invalidates iterators, and changes the order of elements. Pointers and references to elements are not invalidated.
@@ -1359,6 +1361,10 @@ Throws:;; The function has no effect if an exception is thrown, unless it is thr
void reserve(size_type n);
```
Equivalent to `a.rehash(ceil(n / a.max_load_factor()))`, or `a.rehash(1)` if `n > 0` and `a.max_load_factor() == std::numeric_limits<float>::infinity()`.
Similar to `rehash`, this function can be used to grow or shrink the number of buckets in the container.
Invalidates iterators, and changes the order of elements. Pointers and references to elements are not invalidated.
[horizontal]

View File

@@ -1306,7 +1306,9 @@ Effects:;; Changes the container's maximum load factor, using `z` as a hint.
void rehash(size_type n);
```
Changes the number of buckets so that there at least `n` buckets, and so that the load factor is less than the maximum load factor.
Changes the number of buckets so that there are at least `n` buckets, and so that the load factor is less than or equal to the maximum load factor. When applicable, this will either grow or shrink the `bucket_count()` associated with the container.
When `size() == 0`, `rehash(0)` will deallocate the underlying buckets array.
Invalidates iterators, and changes the order of elements. Pointers and references to elements are not invalidated.
@@ -1320,11 +1322,16 @@ Throws:;; The function has no effect if an exception is thrown, unless it is thr
void reserve(size_type n);
```
Equivalent to `a.rehash(ceil(n / a.max_load_factor()))`, or `a.rehash(1)` if `n > 0` and `a.max_load_factor() == std::numeric_limits<float>::infinity()`.
Similar to `rehash`, this function can be used to grow or shrink the number of buckets in the container.
Invalidates iterators, and changes the order of elements. Pointers and references to elements are not invalidated.
[horizontal]
Throws:;; The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function.
---
=== Equality Comparisons

View File

@@ -1329,7 +1329,9 @@ Effects:;; Changes the container's maximum load factor, using `z` as a hint.
void rehash(size_type n);
```
Changes the number of buckets so that there at least `n` buckets, and so that the load factor is less than the maximum load factor.
Changes the number of buckets so that there are at least `n` buckets, and so that the load factor is less than or equal to the maximum load factor. When applicable, this will either grow or shrink the `bucket_count()` associated with the container.
When `size() == 0`, `rehash(0)` will deallocate the underlying buckets array.
Invalidates iterators, and changes the order of elements. Pointers and references to elements are not invalidated.
@@ -1343,11 +1345,16 @@ Throws:;; The function has no effect if an exception is thrown, unless it is thr
void reserve(size_type n);
```
Equivalent to `a.rehash(ceil(n / a.max_load_factor()))`, or `a.rehash(1)` if `n > 0` and `a.max_load_factor() == std::numeric_limits<float>::infinity()`.
Similar to `rehash`, this function can be used to grow or shrink the number of buckets in the container.
Invalidates iterators, and changes the order of elements. Pointers and references to elements are not invalidated.
[horizontal]
Throws:;; The function has no effect if an exception is thrown, unless it is thrown by the container's hash function or comparison function.
=== Equality Comparisons
==== operator==

View File

@@ -494,11 +494,33 @@ namespace boost {
group_pointer groups;
public:
static std::size_t bucket_count_for(std::size_t num_buckets)
{
if (num_buckets == 0) {
return 0;
}
return size_policy::size(size_policy::size_index(num_buckets));
}
grouped_bucket_array()
: empty_value<node_allocator_type>(
empty_init_t(), node_allocator_type()),
size_index_(0), size_(0), buckets(), groups()
{
}
grouped_bucket_array(size_type n, const Allocator& al)
: empty_value<node_allocator_type>(empty_init_t(), al),
size_index_(size_policy::size_index(n)),
size_(size_policy::size(size_index_)), buckets(), groups()
size_index_(0),
size_(0), buckets(), groups()
{
if (n == 0) {
return;
}
size_index_ = size_policy::size_index(n);
size_ = size_policy::size(size_index_);
bucket_allocator_type bucket_alloc = this->get_bucket_allocator();
group_allocator_type group_alloc = this->get_group_allocator();
@@ -646,7 +668,7 @@ namespace boost {
size_type bucket_count() const { return size_; }
iterator begin() const { return ++at(size_); }
iterator begin() const { return size_ == 0 ? end() : ++at(size_); }
iterator end() const
{
@@ -660,6 +682,10 @@ namespace boost {
local_iterator begin(size_type n) const
{
if (size_ == 0) {
return this->end(n);
}
return local_iterator(
(buckets + static_cast<difference_type>(n))->next);
}
@@ -670,12 +696,16 @@ namespace boost {
iterator at(size_type n) const
{
std::size_t const N = group::N;
if (size_ > 0) {
std::size_t const N = group::N;
iterator pbg(buckets + static_cast<difference_type>(n),
groups + static_cast<difference_type>(n / N));
iterator pbg(buckets + static_cast<difference_type>(n),
groups + static_cast<difference_type>(n / N));
return pbg;
return pbg;
} else {
return this->end();
}
}
span<Bucket> raw()

File diff suppressed because it is too large Load Diff

View File

@@ -47,6 +47,7 @@
#include <boost/type_traits/make_void.hpp>
#include <boost/type_traits/remove_const.hpp>
#include <boost/unordered/detail/fca.hpp>
#include <boost/unordered/detail/type_traits.hpp>
#include <boost/unordered/detail/fwd.hpp>
#include <boost/utility/addressof.hpp>
#include <boost/utility/enable_if.hpp>
@@ -200,7 +201,7 @@ namespace boost {
template <typename Types> struct table;
static const float minimum_max_load_factor = 1e-3f;
static const std::size_t default_bucket_count = 11;
static const std::size_t default_bucket_count = 0;
struct move_tag
{
@@ -618,39 +619,6 @@ namespace boost {
#endif
////////////////////////////////////////////////////////////////////////////
// Type checkers used for the transparent member functions added by C++20 and up
template <class, class = void> struct is_transparent : public false_type
{
};
template <class T>
struct is_transparent<T,
typename boost::make_void<typename T::is_transparent>::type>
: public true_type
{
};
template <class, class A, class B> struct are_transparent
{
static bool const value =
is_transparent<A>::value && is_transparent<B>::value;
};
template <class Key, class UnorderedMap> struct transparent_non_iterable
{
typedef typename UnorderedMap::hasher hash;
typedef typename UnorderedMap::key_equal key_equal;
typedef typename UnorderedMap::iterator iterator;
typedef typename UnorderedMap::const_iterator const_iterator;
static bool const value =
are_transparent<Key, hash, key_equal>::value &&
!boost::is_convertible<Key, iterator>::value &&
!boost::is_convertible<Key, const_iterator>::value;
};
////////////////////////////////////////////////////////////////////////////
// Explicitly call a destructor
@@ -2054,12 +2022,14 @@ namespace boost {
std::size_t bucket_size(std::size_t index) const
{
bucket_iterator itb = buckets_.at(index);
node_pointer n = itb->next;
std::size_t count = 0;
while (n) {
++count;
n = n->next;
if (size_ > 0) {
bucket_iterator itb = buckets_.at(index);
node_pointer n = itb->next;
while (n) {
++count;
n = n->next;
}
}
return count;
}
@@ -2069,13 +2039,18 @@ namespace boost {
void recalculate_max_load()
{
using namespace std;
// From 6.3.1/13:
// Only resize when size >= mlf_ * count
max_load_ = boost::unordered::detail::double_to_size(
floor(static_cast<double>(mlf_) *
static_cast<double>(buckets_.bucket_count())));
std::size_t const bc = buckets_.bucket_count();
// it's important we do the `bc == 0` check here because the `mlf_`
// can be specified to be infinity. The operation `n * INF` is `INF`
// for all `n > 0` but NaN for `n == 0`.
//
max_load_ =
bc == 0 ? 0
: boost::unordered::detail::double_to_size(
static_cast<double>(mlf_) * static_cast<double>(bc));
}
void max_load_factor(float z)
@@ -2088,6 +2063,12 @@ namespace boost {
////////////////////////////////////////////////////////////////////////
// Constructors
table()
: functions(hasher(), key_equal()), size_(0), mlf_(1.0f),
max_load_(0)
{
}
table(std::size_t num_buckets, hasher const& hf, key_equal const& eq,
node_allocator_type const& a)
: functions(hf, eq), size_(0), mlf_(1.0f), max_load_(0),
@@ -2359,7 +2340,6 @@ namespace boost {
template <typename UniqueType>
void move_assign(table& x, UniqueType is_unique, false_type)
{
reserve(x.size_);
if (node_alloc() == x.node_alloc()) {
move_assign_equal_alloc(x);
} else {
@@ -2388,7 +2368,9 @@ namespace boost {
{
mlf_ = x.mlf_;
recalculate_max_load();
this->reserve_for_insert(x.size_);
if (x.size_ > 0) {
this->reserve_for_insert(x.size_);
}
this->clear_impl();
}
BOOST_CATCH(...)
@@ -2420,11 +2402,14 @@ namespace boost {
node_pointer find_node_impl(
Key const& x, bucket_iterator itb) const
{
key_equal const& pred = this->key_eq();
node_pointer p = itb->next;
for (; p; p = p->next) {
if (pred(x, extractor::extract(p->value()))) {
break;
node_pointer p = node_pointer();
if (itb != buckets_.end()) {
key_equal const& pred = this->key_eq();
p = itb->next;
for (; p; p = p->next) {
if (pred(x, extractor::extract(p->value()))) {
break;
}
}
}
return p;
@@ -2453,11 +2438,13 @@ namespace boost {
inline iterator transparent_find(
Key const& k, Hash const& h, Pred const& pred) const
{
std::size_t const key_hash = h(k);
bucket_iterator itb = buckets_.at(buckets_.position(key_hash));
for (node_pointer p = itb->next; p; p = p->next) {
if (BOOST_LIKELY(pred(k, extractor::extract(p->value())))) {
return iterator(p, itb);
if (size_ > 0) {
std::size_t const key_hash = h(k);
bucket_iterator itb = buckets_.at(buckets_.position(key_hash));
for (node_pointer p = itb->next; p; p = p->next) {
if (BOOST_LIKELY(pred(k, extractor::extract(p->value())))) {
return iterator(p, itb);
}
}
}
@@ -2467,11 +2454,13 @@ namespace boost {
template <class Key>
node_pointer* find_prev(Key const& key, bucket_iterator itb)
{
key_equal pred = this->key_eq();
for (node_pointer* pp = boost::addressof(itb->next); *pp;
pp = boost::addressof((*pp)->next)) {
if (pred(key, extractor::extract((*pp)->value()))) {
return pp;
if (size_ > 0) {
key_equal pred = this->key_eq();
for (node_pointer* pp = boost::addressof(itb->next); *pp;
pp = boost::addressof((*pp)->next)) {
if (pred(key, extractor::extract((*pp)->value()))) {
return pp;
}
}
}
typedef node_pointer* node_pointer_pointer;
@@ -2503,6 +2492,17 @@ namespace boost {
new_buckets.insert_node(itnewb, p);
}
static std::size_t min_buckets(std::size_t num_elements, float mlf)
{
std::size_t num_buckets = static_cast<std::size_t>(
std::ceil(static_cast<float>(num_elements) / mlf));
if (num_buckets == 0 && num_elements > 0) { // mlf == inf
num_buckets = 1;
}
return num_buckets;
}
void rehash(std::size_t);
void reserve(std::size_t);
void reserve_for_insert(std::size_t);
@@ -3411,22 +3411,18 @@ namespace boost {
template <typename Types>
inline void table<Types>::rehash(std::size_t num_buckets)
{
std::size_t bc = (std::max)(num_buckets,
static_cast<std::size_t>(1.0f + static_cast<float>(size_) / mlf_));
num_buckets = (std::max)(
min_buckets(size_, mlf_), buckets_.bucket_count_for(num_buckets));
if (bc <= buckets_.bucket_count()) {
return;
if (num_buckets != this->bucket_count()) {
this->rehash_impl(num_buckets);
}
this->rehash_impl(bc);
}
template <class Types>
inline void table<Types>::reserve(std::size_t num_elements)
{
std::size_t const num_buckets = static_cast<std::size_t>(
std::ceil(static_cast<float>(num_elements) / mlf_));
std::size_t num_buckets = min_buckets(num_elements, mlf_);
this->rehash(num_buckets);
}

View File

@@ -0,0 +1,59 @@
// Copyright (C) 2022 Christian Mazakas
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_UNORDERED_DETAIL_TYPE_TRAITS_HPP
#define BOOST_UNORDERED_DETAIL_TYPE_TRAITS_HPP
#include <boost/config.hpp>
#if defined(BOOST_HAS_PRAGMA_ONCE)
#pragma once
#endif
#include <boost/type_traits/integral_constant.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/type_traits/make_void.hpp>
namespace boost {
namespace unordered {
namespace detail {
////////////////////////////////////////////////////////////////////////////
// Type checkers used for the transparent member functions added by C++20
// and up
template <class, class = void>
struct is_transparent : public boost::false_type
{
};
template <class T>
struct is_transparent<T,
typename boost::make_void<typename T::is_transparent>::type>
: public boost::true_type
{
};
template <class, class A, class B> struct are_transparent
{
static bool const value =
is_transparent<A>::value && is_transparent<B>::value;
};
template <class Key, class UnorderedMap> struct transparent_non_iterable
{
typedef typename UnorderedMap::hasher hash;
typedef typename UnorderedMap::key_equal key_equal;
typedef typename UnorderedMap::iterator iterator;
typedef typename UnorderedMap::const_iterator const_iterator;
static bool const value =
are_transparent<Key, hash, key_equal>::value &&
!boost::is_convertible<Key, iterator>::value &&
!boost::is_convertible<Key, const_iterator>::value;
};
} // namespace detail
} // namespace unordered
} // namespace boost
#endif // BOOST_UNORDERED_DETAIL_TYPE_TRAITS_HPP

View File

@@ -0,0 +1,75 @@
/* 32b/64b xmx mix function.
*
* Copyright 2022 Peter Dimov.
* Copyright 2022 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See https://www.boost.org/libs/unordered for library home page.
*/
#ifndef BOOST_UNORDERED_DETAIL_XMX_HPP
#define BOOST_UNORDERED_DETAIL_XMX_HPP
#include <boost/cstdint.hpp>
#include <climits>
#include <cstddef>
namespace boost{
namespace unordered{
namespace detail{
/* Bit mixer for improvement of statistical properties of hash functions.
* The implementation is different on 64bit and 32bit architectures:
*
* - 64bit: same as xmx function in
* http://jonkagstrom.com/bit-mixer-construction/index.html
* - 32bit: generated by Hash Function Prospector
* (https://github.com/skeeto/hash-prospector) and selected as the
* best overall performer in benchmarks of Boost.Unordered flat containers.
* Score assigned by Hash Prospector: 333.7934929677524
*/
#if defined(SIZE_MAX)
#if ((((SIZE_MAX >> 16) >> 16) >> 16) >> 15) != 0
#define BOOST_UNORDERED_64B_ARCHITECTURE /* >64 bits assumed as 64 bits */
#endif
#elif defined(UINTPTR_MAX) /* used as proxy for std::size_t */
#if ((((UINTPTR_MAX >> 16) >> 16) >> 16) >> 15) != 0
#define BOOST_UNORDERED_64B_ARCHITECTURE
#endif
#endif
static inline std::size_t xmx(std::size_t x)noexcept
{
#if defined(BOOST_UNORDERED_64B_ARCHITECTURE)
boost::uint64_t z=(boost::uint64_t)x;
z^=z>>23;
z*=0xff51afd7ed558ccdull;
z^=z>>23;
return (std::size_t)z;
#else /* 32 bits assumed */
x^=x>>18;
x*=0x56b5aaadu;
x^=x>>16;
return x;
#endif
}
#ifdef BOOST_UNORDERED_64B_ARCHITECTURE
#undef BOOST_UNORDERED_64B_ARCHITECTURE
#endif
} /* namespace detail */
} /* namespace unordered */
} /* namespace boost */
#endif

View File

@@ -0,0 +1,44 @@
/* Hash function characterization.
*
* Copyright 2022 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See https://www.boost.org/libs/unordered for library home page.
*/
#ifndef BOOST_UNORDERED_HASH_TRAITS_HPP
#define BOOST_UNORDERED_HASH_TRAITS_HPP
#include <boost/type_traits/make_void.hpp>
#include <type_traits>
namespace boost{
namespace unordered{
namespace detail{
template<typename Hash,typename=void>
struct hash_is_avalanching_impl:std::false_type{};
template<typename Hash>
struct hash_is_avalanching_impl<Hash,void_t<typename Hash::is_avalanching>>:
std::true_type{};
} /* namespace detail */
/* Each trait can be partially specialized by users for concrete hash functions
* when actual characterization differs from default.
*/
/* Derived from std::true_type if the type Hash::is_avalanching is present,
* derived from std::false_type otherwise.
*/
template<typename Hash>
struct hash_is_avalanching:detail::hash_is_avalanching_impl<Hash>::type{};
} /* namespace unordered */
} /* namespace boost */
#endif

View File

@@ -0,0 +1,619 @@
// Copyright (C) 2022 Christian Mazakas
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_UNORDERED_UNORDERED_FLAT_MAP_HPP_INCLUDED
#define BOOST_UNORDERED_UNORDERED_FLAT_MAP_HPP_INCLUDED
#include <boost/config.hpp>
#if defined(BOOST_HAS_PRAGMA_ONCE)
#pragma once
#endif
#include <boost/unordered/detail/foa.hpp>
#include <boost/unordered/detail/type_traits.hpp>
#include <boost/unordered/unordered_flat_map_fwd.hpp>
#include <boost/core/allocator_access.hpp>
#include <boost/functional/hash.hpp>
#include <boost/throw_exception.hpp>
#include <initializer_list>
#include <iterator>
#include <stdexcept>
#include <type_traits>
#include <utility>
namespace boost {
namespace unordered {
#if defined(BOOST_MSVC)
#pragma warning(push)
#pragma warning(disable : 4714) /* marked as __forceinline not inlined */
#endif
template <class Key, class T, class Hash, class KeyEqual, class Allocator>
class unordered_flat_map
{
struct map_types
{
using key_type = Key;
using raw_key_type = typename std::remove_const<Key>::type;
using raw_mapped_type = typename std::remove_const<T>::type;
using init_type = std::pair<raw_key_type, raw_mapped_type>;
using moved_type = std::pair<raw_key_type&&, raw_mapped_type&&>;
using value_type = std::pair<Key const, T>;
template <class K, class V>
static raw_key_type const& extract(std::pair<K, V> const& kv)
{
return kv.first;
}
static moved_type move(value_type& x)
{
// TODO: we probably need to launder here
return {std::move(const_cast<raw_key_type&>(x.first)),
std::move(const_cast<raw_mapped_type&>(x.second))};
}
};
using table_type = detail::foa::table<map_types, Hash, KeyEqual,
typename boost::allocator_rebind<Allocator,
typename map_types::value_type>::type>;
table_type table_;
template <class K, class V, class H, class KE, class A, class Pred>
typename unordered_flat_map<K, V, H, KE, A>::size_type friend erase_if(
unordered_flat_map<K, V, H, KE, A>& set, Pred pred);
public:
using key_type = Key;
using mapped_type = T;
using value_type = typename map_types::value_type;
using init_type = typename map_types::init_type;
using size_type = std::size_t;
using difference_type = std::ptrdiff_t;
using hasher = Hash;
using key_equal = KeyEqual;
using allocator_type = Allocator;
using reference = value_type&;
using const_reference = value_type const&;
using pointer = typename boost::allocator_pointer<allocator_type>::type;
using const_pointer =
typename boost::allocator_const_pointer<allocator_type>::type;
using iterator = typename table_type::iterator;
using const_iterator = typename table_type::const_iterator;
unordered_flat_map() : unordered_flat_map(0) {}
explicit unordered_flat_map(size_type n, hasher const& h = hasher(),
key_equal const& pred = key_equal(),
allocator_type const& a = allocator_type())
: table_(n, h, pred, a)
{
}
unordered_flat_map(size_type n, allocator_type const& a)
: unordered_flat_map(n, hasher(), key_equal(), a)
{
}
unordered_flat_map(size_type n, hasher const& h, allocator_type const& a)
: unordered_flat_map(n, h, key_equal(), a)
{
}
explicit unordered_flat_map(allocator_type const& a)
: unordered_flat_map(0, a)
{
}
template <class Iterator>
unordered_flat_map(Iterator first, Iterator last, size_type n = 0,
hasher const& h = hasher(), key_equal const& pred = key_equal(),
allocator_type const& a = allocator_type())
: unordered_flat_map(n, h, pred, a)
{
this->insert(first, last);
}
template <class Iterator>
unordered_flat_map(
Iterator first, Iterator last, size_type n, allocator_type const& a)
: unordered_flat_map(first, last, n, hasher(), key_equal(), a)
{
}
template <class Iterator>
unordered_flat_map(Iterator first, Iterator last, size_type n,
hasher const& h, allocator_type const& a)
: unordered_flat_map(first, last, n, h, key_equal(), a)
{
}
unordered_flat_map(unordered_flat_map const& other) : table_(other.table_)
{
}
unordered_flat_map(
unordered_flat_map const& other, allocator_type const& a)
: table_(other.table_, a)
{
}
unordered_flat_map(unordered_flat_map&& other)
noexcept(std::is_nothrow_move_constructible<hasher>::value&&
std::is_nothrow_move_constructible<key_equal>::value&&
std::is_nothrow_move_constructible<allocator_type>::value)
: table_(std::move(other.table_))
{
}
unordered_flat_map(unordered_flat_map&& other, allocator_type const& al)
: table_(std::move(other.table_), al)
{
}
unordered_flat_map(std::initializer_list<value_type> ilist,
size_type n = 0, hasher const& h = hasher(),
key_equal const& pred = key_equal(),
allocator_type const& a = allocator_type())
: unordered_flat_map(ilist.begin(), ilist.end(), n, h, pred, a)
{
}
unordered_flat_map(std::initializer_list<value_type> init, size_type n,
allocator_type const& a)
: unordered_flat_map(init, n, hasher(), key_equal(), a)
{
}
unordered_flat_map(std::initializer_list<value_type> init, size_type n,
hasher const& h, allocator_type const& a)
: unordered_flat_map(init, n, h, key_equal(), a)
{
}
~unordered_flat_map() = default;
unordered_flat_map& operator=(unordered_flat_map const& other)
{
table_ = other.table_;
return *this;
}
unordered_flat_map& operator=(unordered_flat_map&& other) noexcept(
noexcept(std::declval<table_type&>() = std::declval<table_type&&>()))
{
table_ = std::move(other.table_);
return *this;
}
allocator_type get_allocator() const noexcept
{
return table_.get_allocator();
}
/// Iterators
///
iterator begin() noexcept { return table_.begin(); }
const_iterator begin() const noexcept { return table_.begin(); }
const_iterator cbegin() const noexcept { return table_.cbegin(); }
iterator end() noexcept { return table_.end(); }
const_iterator end() const noexcept { return table_.end(); }
const_iterator cend() const noexcept { return table_.cend(); }
/// Capacity
///
BOOST_ATTRIBUTE_NODISCARD bool empty() const noexcept
{
return table_.empty();
}
size_type size() const noexcept { return table_.size(); }
size_type max_size() const noexcept { return table_.max_size(); }
/// Modifiers
///
void clear() noexcept { table_.clear(); }
template <class Ty>
BOOST_FORCEINLINE auto insert(Ty&& value)
-> decltype(table_.insert(std::forward<Ty>(value)))
{
return table_.insert(std::forward<Ty>(value));
}
BOOST_FORCEINLINE std::pair<iterator, bool> insert(init_type&& value)
{
return table_.insert(std::move(value));
}
template <class Ty>
BOOST_FORCEINLINE auto insert(const_iterator, Ty&& value)
-> decltype(table_.insert(std::forward<Ty>(value)).first)
{
return table_.insert(std::forward<Ty>(value)).first;
}
BOOST_FORCEINLINE iterator insert(const_iterator, init_type&& value)
{
return table_.insert(std::move(value)).first;
}
template <class InputIterator>
BOOST_FORCEINLINE void insert(InputIterator first, InputIterator last)
{
for (auto pos = first; pos != last; ++pos) {
table_.emplace(*pos);
}
}
void insert(std::initializer_list<value_type> ilist)
{
this->insert(ilist.begin(), ilist.end());
}
template <class M>
std::pair<iterator, bool> insert_or_assign(key_type const& key, M&& obj)
{
auto iter_bool_pair = table_.try_emplace(key, std::forward<M>(obj));
if (iter_bool_pair.second) {
return iter_bool_pair;
}
iter_bool_pair.first->second = std::forward<M>(obj);
return iter_bool_pair;
}
template <class M>
std::pair<iterator, bool> insert_or_assign(key_type&& key, M&& obj)
{
auto iter_bool_pair =
table_.try_emplace(std::move(key), std::forward<M>(obj));
if (iter_bool_pair.second) {
return iter_bool_pair;
}
iter_bool_pair.first->second = std::forward<M>(obj);
return iter_bool_pair;
}
template <class M>
iterator insert_or_assign(const_iterator, key_type const& key, M&& obj)
{
return this->insert_or_assign(key, std::forward<M>(obj)).first;
}
template <class M>
iterator insert_or_assign(const_iterator, key_type&& key, M&& obj)
{
return this->insert_or_assign(std::move(key), std::forward<M>(obj))
.first;
}
template <class... Args>
BOOST_FORCEINLINE std::pair<iterator, bool> emplace(Args&&... args)
{
return table_.emplace(std::forward<Args>(args)...);
}
template <class... Args>
BOOST_FORCEINLINE iterator emplace_hint(const_iterator, Args&&... args)
{
return table_.emplace(std::forward<Args>(args)...).first;
}
template <class... Args>
BOOST_FORCEINLINE std::pair<iterator, bool> try_emplace(
key_type const& key, Args&&... args)
{
return table_.try_emplace(key, std::forward<Args>(args)...);
}
template <class... Args>
BOOST_FORCEINLINE std::pair<iterator, bool> try_emplace(
key_type&& key, Args&&... args)
{
return table_.try_emplace(std::move(key), std::forward<Args>(args)...);
}
template <class... Args>
BOOST_FORCEINLINE iterator try_emplace(
const_iterator, key_type const& key, Args&&... args)
{
return table_.try_emplace(key, std::forward<Args>(args)...).first;
}
template <class... Args>
BOOST_FORCEINLINE iterator try_emplace(
const_iterator, key_type&& key, Args&&... args)
{
return table_.try_emplace(std::move(key), std::forward<Args>(args)...)
.first;
}
BOOST_FORCEINLINE void erase(iterator pos) { table_.erase(pos); }
BOOST_FORCEINLINE void erase(const_iterator pos)
{
return table_.erase(pos);
}
iterator erase(const_iterator first, const_iterator last)
{
while (first != last) {
this->erase(first++);
}
return iterator{detail::foa::const_iterator_cast_tag{}, last};
}
BOOST_FORCEINLINE size_type erase(key_type const& key)
{
return table_.erase(key);
}
template <class K>
BOOST_FORCEINLINE typename std::enable_if<
detail::transparent_non_iterable<K, unordered_flat_map>::value,
size_type>::type
erase(K const& key)
{
return table_.erase(key);
}
void swap(unordered_flat_map& rhs) noexcept(
noexcept(std::declval<table_type&>().swap(std::declval<table_type&>())))
{
table_.swap(rhs.table_);
}
template <class H2, class P2>
void merge(
unordered_flat_map<key_type, mapped_type, H2, P2, allocator_type>&
source)
{
table_.merge(source.table_);
}
template <class H2, class P2>
void merge(
unordered_flat_map<key_type, mapped_type, H2, P2, allocator_type>&&
source)
{
table_.merge(std::move(source.table_));
}
/// Lookup
///
mapped_type& at(key_type const& key)
{
auto pos = table_.find(key);
if (pos != table_.end()) {
return pos->second;
}
// TODO: someday refactor this to conditionally serialize the key and
// include it in the error message
//
boost::throw_exception(
std::out_of_range("key was not found in unordered_flat_map"));
}
mapped_type const& at(key_type const& key) const
{
auto pos = table_.find(key);
if (pos != table_.end()) {
return pos->second;
}
boost::throw_exception(
std::out_of_range("key was not found in unordered_flat_map"));
}
mapped_type& operator[](key_type const& key)
{
return table_.try_emplace(key).first->second;
}
mapped_type& operator[](key_type&& key)
{
return table_.try_emplace(std::move(key)).first->second;
}
size_type count(key_type const& key) const
{
auto pos = table_.find(key);
return pos != table_.end() ? 1 : 0;
}
template <class K>
typename std::enable_if<
detail::are_transparent<K, hasher, key_equal>::value, size_type>::type
count(K const& key) const
{
auto pos = table_.find(key);
return pos != table_.end() ? 1 : 0;
}
BOOST_FORCEINLINE iterator find(key_type const& key)
{
return table_.find(key);
}
BOOST_FORCEINLINE const_iterator find(key_type const& key) const
{
return table_.find(key);
}
template <class K>
BOOST_FORCEINLINE typename std::enable_if<
boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
iterator>::type
find(K const& key)
{
return table_.find(key);
}
template <class K>
BOOST_FORCEINLINE typename std::enable_if<
boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
const_iterator>::type
find(K const& key) const
{
return table_.find(key);
}
bool contains(key_type const& key) const
{
return this->find(key) != this->end();
}
template <class K>
typename std::enable_if<
boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
bool>::type
contains(K const& key) const
{
return this->find(key) != this->end();
}
std::pair<iterator, iterator> equal_range(key_type const& key)
{
auto pos = table_.find(key);
if (pos == table_.end()) {
return {pos, pos};
}
auto next = pos;
++next;
return {pos, next};
}
std::pair<const_iterator, const_iterator> equal_range(
key_type const& key) const
{
auto pos = table_.find(key);
if (pos == table_.end()) {
return {pos, pos};
}
auto next = pos;
++next;
return {pos, next};
}
template <class K>
typename std::enable_if<
detail::are_transparent<K, hasher, key_equal>::value,
std::pair<iterator, iterator> >::type
equal_range(K const& key)
{
auto pos = table_.find(key);
if (pos == table_.end()) {
return {pos, pos};
}
auto next = pos;
++next;
return {pos, next};
}
template <class K>
typename std::enable_if<
detail::are_transparent<K, hasher, key_equal>::value,
std::pair<const_iterator, const_iterator> >::type
equal_range(K const& key) const
{
auto pos = table_.find(key);
if (pos == table_.end()) {
return {pos, pos};
}
auto next = pos;
++next;
return {pos, next};
}
/// Hash Policy
///
size_type bucket_count() const noexcept { return table_.capacity(); }
float load_factor() const noexcept { return table_.load_factor(); }
float max_load_factor() const noexcept
{
return table_.max_load_factor();
}
void max_load_factor(float) {}
void rehash(size_type n) { table_.rehash(n); }
void reserve(size_type n) { table_.reserve(n); }
/// Observers
///
hasher hash_function() const { return table_.hash_function(); }
key_equal key_eq() const { return table_.key_eq(); }
};
template <class Key, class T, class Hash, class KeyEqual, class Allocator>
bool operator==(
unordered_flat_map<Key, T, Hash, KeyEqual, Allocator> const& lhs,
unordered_flat_map<Key, T, Hash, KeyEqual, Allocator> const& rhs)
{
if (&lhs == &rhs) {
return true;
}
return (lhs.size() == rhs.size()) && ([&] {
for (auto const& kvp : lhs) {
auto pos = rhs.find(kvp.first);
if ((pos == rhs.end()) || (*pos != kvp)) {
return false;
}
}
return true;
})();
}
template <class Key, class T, class Hash, class KeyEqual, class Allocator>
bool operator!=(
unordered_flat_map<Key, T, Hash, KeyEqual, Allocator> const& lhs,
unordered_flat_map<Key, T, Hash, KeyEqual, Allocator> const& rhs)
{
return !(lhs == rhs);
}
template <class Key, class T, class Hash, class KeyEqual, class Allocator>
void swap(unordered_flat_map<Key, T, Hash, KeyEqual, Allocator>& lhs,
unordered_flat_map<Key, T, Hash, KeyEqual, Allocator>& rhs)
noexcept(noexcept(lhs.swap(rhs)))
{
lhs.swap(rhs);
}
template <class Key, class T, class Hash, class KeyEqual, class Allocator,
class Pred>
typename unordered_flat_map<Key, T, Hash, KeyEqual, Allocator>::size_type
erase_if(
unordered_flat_map<Key, T, Hash, KeyEqual, Allocator>& map, Pred pred)
{
return erase_if(map.table_, pred);
}
#if defined(BOOST_MSVC)
#pragma warning(pop) /* C4714 */
#endif
} // namespace unordered
} // namespace boost
#endif

View File

@@ -0,0 +1,49 @@
// Copyright (C) 2022 Christian Mazakas
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_UNORDERED_FLAT_MAP_FWD_HPP_INCLUDED
#define BOOST_UNORDERED_FLAT_MAP_FWD_HPP_INCLUDED
#include <boost/config.hpp>
#if defined(BOOST_HAS_PRAGMA_ONCE)
#pragma once
#endif
#include <boost/functional/hash_fwd.hpp>
#include <boost/unordered/detail/fwd.hpp>
#include <functional>
#include <memory>
namespace boost {
namespace unordered {
template <class Key, class T, class Hash = boost::hash<Key>,
class KeyEqual = std::equal_to<Key>,
class Allocator = std::allocator<std::pair<const Key, T> > >
class unordered_flat_map;
template <class Key, class T, class Hash, class KeyEqual, class Allocator>
bool operator==(
unordered_flat_map<Key, T, Hash, KeyEqual, Allocator> const& lhs,
unordered_flat_map<Key, T, Hash, KeyEqual, Allocator> const& rhs);
template <class Key, class T, class Hash, class KeyEqual, class Allocator>
bool operator!=(
unordered_flat_map<Key, T, Hash, KeyEqual, Allocator> const& lhs,
unordered_flat_map<Key, T, Hash, KeyEqual, Allocator> const& rhs);
template <class Key, class T, class Hash, class KeyEqual, class Allocator>
void swap(unordered_flat_map<Key, T, Hash, KeyEqual, Allocator>& lhs,
unordered_flat_map<Key, T, Hash, KeyEqual, Allocator>& rhs)
noexcept(noexcept(lhs.swap(rhs)));
} // namespace unordered
using boost::unordered::unordered_flat_map;
using boost::unordered::swap;
using boost::unordered::operator==;
using boost::unordered::operator!=;
} // namespace boost
#endif

View File

@@ -0,0 +1,494 @@
// Copyright (C) 2022 Christian Mazakas
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_UNORDERED_UNORDERED_FLAT_SET_HPP_INCLUDED
#define BOOST_UNORDERED_UNORDERED_FLAT_SET_HPP_INCLUDED
#include <boost/config.hpp>
#if defined(BOOST_HAS_PRAGMA_ONCE)
#pragma once
#endif
#include <boost/unordered/detail/foa.hpp>
#include <boost/unordered/detail/type_traits.hpp>
#include <boost/unordered/unordered_flat_set_fwd.hpp>
#include <boost/core/allocator_access.hpp>
#include <boost/functional/hash.hpp>
#include <initializer_list>
#include <iterator>
#include <type_traits>
#include <utility>
namespace boost {
namespace unordered {
#if defined(BOOST_MSVC)
#pragma warning(push)
#pragma warning(disable : 4714) /* marked as __forceinline not inlined */
#endif
template <class Key, class Hash, class KeyEqual, class Allocator>
class unordered_flat_set
{
struct set_types
{
using key_type = Key;
using init_type = Key;
using value_type = Key;
static Key const& extract(value_type const& key) { return key; }
static Key&& move(value_type& x) { return std::move(x); }
};
using table_type = detail::foa::table<set_types, Hash, KeyEqual,
typename boost::allocator_rebind<Allocator,
typename set_types::value_type>::type>;
table_type table_;
template <class K, class H, class KE, class A, class Pred>
typename unordered_flat_set<K, H, KE, A>::size_type friend erase_if(
unordered_flat_set<K, H, KE, A>& set, Pred pred);
public:
using key_type = Key;
using value_type = typename set_types::value_type;
using init_type = typename set_types::init_type;
using size_type = std::size_t;
using difference_type = std::ptrdiff_t;
using hasher = Hash;
using key_equal = KeyEqual;
using allocator_type = Allocator;
using reference = value_type&;
using const_reference = value_type const&;
using pointer = typename boost::allocator_pointer<allocator_type>::type;
using const_pointer =
typename boost::allocator_const_pointer<allocator_type>::type;
using iterator = typename table_type::iterator;
using const_iterator = typename table_type::const_iterator;
unordered_flat_set() : unordered_flat_set(0) {}
explicit unordered_flat_set(size_type n, hasher const& h = hasher(),
key_equal const& pred = key_equal(),
allocator_type const& a = allocator_type())
: table_(n, h, pred, a)
{
}
unordered_flat_set(size_type n, allocator_type const& a)
: unordered_flat_set(n, hasher(), key_equal(), a)
{
}
unordered_flat_set(size_type n, hasher const& h, allocator_type const& a)
: unordered_flat_set(n, h, key_equal(), a)
{
}
explicit unordered_flat_set(allocator_type const& a)
: unordered_flat_set(0, a)
{
}
template <class Iterator>
unordered_flat_set(Iterator first, Iterator last, size_type n = 0,
hasher const& h = hasher(), key_equal const& pred = key_equal(),
allocator_type const& a = allocator_type())
: unordered_flat_set(n, h, pred, a)
{
this->insert(first, last);
}
template <class InputIt>
unordered_flat_set(
InputIt first, InputIt last, size_type n, allocator_type const& a)
: unordered_flat_set(first, last, n, hasher(), key_equal(), a)
{
}
template <class Iterator>
unordered_flat_set(Iterator first, Iterator last, size_type n,
hasher const& h, allocator_type const& a)
: unordered_flat_set(first, last, n, h, key_equal(), a)
{
}
unordered_flat_set(unordered_flat_set const& other) : table_(other.table_)
{
}
unordered_flat_set(
unordered_flat_set const& other, allocator_type const& a)
: table_(other.table_, a)
{
}
unordered_flat_set(unordered_flat_set&& other)
noexcept(std::is_nothrow_move_constructible<hasher>::value&&
std::is_nothrow_move_constructible<key_equal>::value&&
std::is_nothrow_move_constructible<allocator_type>::value)
: table_(std::move(other.table_))
{
}
unordered_flat_set(unordered_flat_set&& other, allocator_type const& al)
: table_(std::move(other.table_), al)
{
}
unordered_flat_set(std::initializer_list<value_type> ilist,
size_type n = 0, hasher const& h = hasher(),
key_equal const& pred = key_equal(),
allocator_type const& a = allocator_type())
: unordered_flat_set(ilist.begin(), ilist.end(), n, h, pred, a)
{
}
unordered_flat_set(std::initializer_list<value_type> init, size_type n,
allocator_type const& a)
: unordered_flat_set(init, n, hasher(), key_equal(), a)
{
}
unordered_flat_set(std::initializer_list<value_type> init, size_type n,
hasher const& h, allocator_type const& a)
: unordered_flat_set(init, n, h, key_equal(), a)
{
}
~unordered_flat_set() = default;
unordered_flat_set& operator=(unordered_flat_set const& other)
{
table_ = other.table_;
return *this;
}
unordered_flat_set& operator=(unordered_flat_set&& other) noexcept(
noexcept(std::declval<table_type&>() = std::declval<table_type&&>()))
{
table_ = std::move(other.table_);
return *this;
}
allocator_type get_allocator() const noexcept
{
return table_.get_allocator();
}
/// Iterators
///
iterator begin() noexcept { return table_.begin(); }
const_iterator begin() const noexcept { return table_.begin(); }
const_iterator cbegin() const noexcept { return table_.cbegin(); }
iterator end() noexcept { return table_.end(); }
const_iterator end() const noexcept { return table_.end(); }
const_iterator cend() const noexcept { return table_.cend(); }
/// Capacity
///
BOOST_ATTRIBUTE_NODISCARD bool empty() const noexcept
{
return table_.empty();
}
size_type size() const noexcept { return table_.size(); }
size_type max_size() const noexcept { return table_.max_size(); }
/// Modifiers
///
void clear() noexcept { table_.clear(); }
BOOST_FORCEINLINE std::pair<iterator, bool> insert(
value_type const& value)
{
return table_.insert(value);
}
BOOST_FORCEINLINE std::pair<iterator, bool> insert(value_type&& value)
{
return table_.insert(std::move(value));
}
BOOST_FORCEINLINE iterator insert(const_iterator, value_type const& value)
{
return table_.insert(value).first;
}
BOOST_FORCEINLINE iterator insert(const_iterator, value_type&& value)
{
return table_.insert(std::move(value)).first;
}
template <class InputIterator>
void insert(InputIterator first, InputIterator last)
{
for (auto pos = first; pos != last; ++pos) {
table_.emplace(*pos);
}
}
void insert(std::initializer_list<value_type> ilist)
{
this->insert(ilist.begin(), ilist.end());
}
template <class... Args>
BOOST_FORCEINLINE std::pair<iterator, bool> emplace(Args&&... args)
{
return table_.emplace(std::forward<Args>(args)...);
}
template <class... Args>
BOOST_FORCEINLINE iterator emplace_hint(const_iterator, Args&&... args)
{
return table_.emplace(std::forward<Args>(args)...).first;
}
BOOST_FORCEINLINE void erase(const_iterator pos)
{
return table_.erase(pos);
}
iterator erase(const_iterator first, const_iterator last)
{
while (first != last) {
this->erase(first++);
}
return iterator{detail::foa::const_iterator_cast_tag{}, last};
}
BOOST_FORCEINLINE size_type erase(key_type const& key)
{
return table_.erase(key);
}
template <class K>
BOOST_FORCEINLINE typename std::enable_if<
detail::transparent_non_iterable<K, unordered_flat_set>::value,
size_type>::type
erase(K const& key)
{
return table_.erase(key);
}
void swap(unordered_flat_set& rhs) noexcept(
noexcept(std::declval<table_type&>().swap(std::declval<table_type&>())))
{
table_.swap(rhs.table_);
}
template <class H2, class P2>
void merge(unordered_flat_set<key_type, H2, P2, allocator_type>& source)
{
table_.merge(source.table_);
}
template <class H2, class P2>
void merge(unordered_flat_set<key_type, H2, P2, allocator_type>&& source)
{
table_.merge(std::move(source.table_));
}
/// Lookup
///
size_type count(key_type const& key) const
{
auto pos = table_.find(key);
return pos != table_.end() ? 1 : 0;
}
template <class K>
typename std::enable_if<
detail::are_transparent<K, hasher, key_equal>::value, size_type>::type
count(K const& key) const
{
auto pos = table_.find(key);
return pos != table_.end() ? 1 : 0;
}
BOOST_FORCEINLINE iterator find(key_type const& key)
{
return table_.find(key);
}
BOOST_FORCEINLINE const_iterator find(key_type const& key) const
{
return table_.find(key);
}
template <class K>
BOOST_FORCEINLINE typename std::enable_if<
boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
iterator>::type
find(K const& key)
{
return table_.find(key);
}
template <class K>
BOOST_FORCEINLINE typename std::enable_if<
boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
const_iterator>::type
find(K const& key) const
{
return table_.find(key);
}
bool contains(key_type const& key) const
{
return this->find(key) != this->end();
}
template <class K>
typename std::enable_if<
boost::unordered::detail::are_transparent<K, hasher, key_equal>::value,
bool>::type
contains(K const& key) const
{
return this->find(key) != this->end();
}
std::pair<iterator, iterator> equal_range(key_type const& key)
{
auto pos = table_.find(key);
if (pos == table_.end()) {
return {pos, pos};
}
auto next = pos;
++next;
return {pos, next};
}
std::pair<const_iterator, const_iterator> equal_range(
key_type const& key) const
{
auto pos = table_.find(key);
if (pos == table_.end()) {
return {pos, pos};
}
auto next = pos;
++next;
return {pos, next};
}
template <class K>
typename std::enable_if<
detail::are_transparent<K, hasher, key_equal>::value,
std::pair<iterator, iterator> >::type
equal_range(K const& key)
{
auto pos = table_.find(key);
if (pos == table_.end()) {
return {pos, pos};
}
auto next = pos;
++next;
return {pos, next};
}
template <class K>
typename std::enable_if<
detail::are_transparent<K, hasher, key_equal>::value,
std::pair<const_iterator, const_iterator> >::type
equal_range(K const& key) const
{
auto pos = table_.find(key);
if (pos == table_.end()) {
return {pos, pos};
}
auto next = pos;
++next;
return {pos, next};
}
/// Hash Policy
///
size_type bucket_count() const noexcept { return table_.capacity(); }
float load_factor() const noexcept { return table_.load_factor(); }
float max_load_factor() const noexcept
{
return table_.max_load_factor();
}
void max_load_factor(float) {}
void rehash(size_type n) { table_.rehash(n); }
void reserve(size_type n) { table_.reserve(n); }
/// Observers
///
hasher hash_function() const { return table_.hash_function(); }
key_equal key_eq() const { return table_.key_eq(); }
};
template <class Key, class Hash, class KeyEqual, class Allocator>
bool operator==(
unordered_flat_set<Key, Hash, KeyEqual, Allocator> const& lhs,
unordered_flat_set<Key, Hash, KeyEqual, Allocator> const& rhs)
{
if (&lhs == &rhs) {
return true;
}
return (lhs.size() == rhs.size()) && ([&] {
for (auto const& key : lhs) {
auto pos = rhs.find(key);
if ((pos == rhs.end()) || (key != *pos)) {
return false;
}
}
return true;
})();
}
template <class Key, class Hash, class KeyEqual, class Allocator>
bool operator!=(
unordered_flat_set<Key, Hash, KeyEqual, Allocator> const& lhs,
unordered_flat_set<Key, Hash, KeyEqual, Allocator> const& rhs)
{
return !(lhs == rhs);
}
template <class Key, class Hash, class KeyEqual, class Allocator>
void swap(unordered_flat_set<Key, Hash, KeyEqual, Allocator>& lhs,
unordered_flat_set<Key, Hash, KeyEqual, Allocator>& rhs)
noexcept(noexcept(lhs.swap(rhs)))
{
lhs.swap(rhs);
}
template <class Key, class Hash, class KeyEqual, class Allocator,
class Pred>
typename unordered_flat_set<Key, Hash, KeyEqual, Allocator>::size_type
erase_if(unordered_flat_set<Key, Hash, KeyEqual, Allocator>& set, Pred pred)
{
return erase_if(set.table_, pred);
}
#if defined(BOOST_MSVC)
#pragma warning(pop) /* C4714 */
#endif
} // namespace unordered
} // namespace boost
#endif

View File

@@ -0,0 +1,49 @@
// Copyright (C) 2022 Christian Mazakas
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_UNORDERED_FLAT_SET_FWD_HPP_INCLUDED
#define BOOST_UNORDERED_FLAT_SET_FWD_HPP_INCLUDED
#include <boost/config.hpp>
#if defined(BOOST_HAS_PRAGMA_ONCE)
#pragma once
#endif
#include <boost/functional/hash_fwd.hpp>
#include <boost/unordered/detail/fwd.hpp>
#include <functional>
#include <memory>
namespace boost {
namespace unordered {
template <class Key, class Hash = boost::hash<Key>,
class KeyEqual = std::equal_to<Key>,
class Allocator = std::allocator<Key> >
class unordered_flat_set;
template <class Key, class Hash, class KeyEqual, class Allocator>
bool operator==(
unordered_flat_set<Key, Hash, KeyEqual, Allocator> const& lhs,
unordered_flat_set<Key, Hash, KeyEqual, Allocator> const& rhs);
template <class Key, class Hash, class KeyEqual, class Allocator>
bool operator!=(
unordered_flat_set<Key, Hash, KeyEqual, Allocator> const& lhs,
unordered_flat_set<Key, Hash, KeyEqual, Allocator> const& rhs);
template <class Key, class Hash, class KeyEqual, class Allocator>
void swap(unordered_flat_set<Key, Hash, KeyEqual, Allocator>& lhs,
unordered_flat_set<Key, Hash, KeyEqual, Allocator>& rhs)
noexcept(noexcept(lhs.swap(rhs)));
} // namespace unordered
using boost::unordered::unordered_flat_set;
using boost::unordered::swap;
using boost::unordered::operator==;
using boost::unordered::operator!=;
} // namespace boost
#endif

View File

@@ -1664,8 +1664,6 @@ namespace boost {
template <class K, class T, class H, class P, class A>
unordered_map<K, T, H, P, A>::unordered_map()
: table_(boost::unordered::detail::default_bucket_count, hasher(),
key_equal(), allocator_type())
{
}
@@ -2069,6 +2067,10 @@ namespace boost {
template <class K, class T, class H, class P, class A>
float unordered_map<K, T, H, P, A>::load_factor() const BOOST_NOEXCEPT
{
if (table_.size_ == 0) {
return 0.0f;
}
BOOST_ASSERT(table_.bucket_count() != 0);
return static_cast<float>(table_.size_) /
static_cast<float>(table_.bucket_count());
@@ -2143,8 +2145,6 @@ namespace boost {
template <class K, class T, class H, class P, class A>
unordered_multimap<K, T, H, P, A>::unordered_multimap()
: table_(boost::unordered::detail::default_bucket_count, hasher(),
key_equal(), allocator_type())
{
}
@@ -2506,6 +2506,10 @@ namespace boost {
template <class K, class T, class H, class P, class A>
float unordered_multimap<K, T, H, P, A>::load_factor() const BOOST_NOEXCEPT
{
if (table_.size_ == 0) {
return 0.0f;
}
BOOST_ASSERT(table_.bucket_count() != 0);
return static_cast<float>(table_.size_) /
static_cast<float>(table_.bucket_count());

View File

@@ -1266,8 +1266,6 @@ namespace boost {
////////////////////////////////////////////////////////////////////////////
template <class T, class H, class P, class A>
unordered_set<T, H, P, A>::unordered_set()
: table_(boost::unordered::detail::default_bucket_count, hasher(),
key_equal(), allocator_type())
{
}
@@ -1586,6 +1584,10 @@ namespace boost {
template <class T, class H, class P, class A>
float unordered_set<T, H, P, A>::load_factor() const BOOST_NOEXCEPT
{
if (table_.size_ == 0) {
return 0.0f;
}
BOOST_ASSERT(table_.bucket_count() != 0);
return static_cast<float>(table_.size_) /
static_cast<float>(table_.bucket_count());
@@ -1660,8 +1662,6 @@ namespace boost {
template <class T, class H, class P, class A>
unordered_multiset<T, H, P, A>::unordered_multiset()
: table_(boost::unordered::detail::default_bucket_count, hasher(),
key_equal(), allocator_type())
{
}
@@ -1986,6 +1986,10 @@ namespace boost {
template <class T, class H, class P, class A>
float unordered_multiset<T, H, P, A>::load_factor() const BOOST_NOEXCEPT
{
if (table_.size_ == 0) {
return 0.0f;
}
BOOST_ASSERT(table_.bucket_count() != 0);
return static_cast<float>(table_.size_) /
static_cast<float>(table_.bucket_count());

View File

@@ -47,6 +47,7 @@ run unordered/equivalent_keys_tests.cpp ;
run unordered/constructor_tests.cpp ;
run unordered/copy_tests.cpp ;
run unordered/move_tests.cpp ;
run unordered/post_move_tests.cpp ;
run unordered/assign_tests.cpp ;
run unordered/insert_tests.cpp ;
run unordered/insert_stable_tests.cpp ;
@@ -95,3 +96,55 @@ run exception/swap_exception_tests.cpp : : : <define>BOOST_UNORDERED_SWAP_METHOD
run exception/merge_exception_tests.cpp ;
run quick.cpp ;
import ../../config/checks/config : requires ;
CPP11 = [ requires cxx11_constexpr cxx11_noexcept cxx11_decltype cxx11_alignas ] ;
rule build_foa ( name )
{
run unordered/$(name).cpp : : : $(CPP11) <define>BOOST_UNORDERED_FOA_TESTS : foa_$(name) ;
}
build_foa fwd_set_test ;
build_foa fwd_map_test ;
build_foa compile_set ;
build_foa compile_map ;
build_foa noexcept_tests ;
run unordered/link_test_1.cpp unordered/link_test_2.cpp : : : $(CPP11) <define>BOOST_UNORDERED_FOA_TESTS : foa_link_test ;
build_foa incomplete_test ;
build_foa simple_tests ;
build_foa equivalent_keys_tests ;
build_foa constructor_tests ;
build_foa copy_tests ;
build_foa move_tests ;
build_foa post_move_tests ;
build_foa assign_tests ;
build_foa insert_tests ;
build_foa insert_hint_tests ;
build_foa emplace_tests ;
build_foa erase_tests ;
build_foa merge_tests ;
build_foa find_tests ;
build_foa at_tests ;
build_foa load_factor_tests ;
build_foa rehash_tests ;
build_foa equality_tests ;
build_foa swap_tests ;
run unordered/scoped_allocator.cpp : : : $(CPP11) <toolset>msvc-14.0:<build>no <define>BOOST_UNORDERED_FOA_TESTS : foa_scoped_allocator ;
build_foa transparent_tests ;
build_foa reserve_tests ;
build_foa contains_tests ;
build_foa erase_if ;
build_foa scary_tests ;
build_foa init_type_insert_tests ;
run exception/constructor_exception_tests.cpp : : : $(CPP11) <define>BOOST_UNORDERED_FOA_TESTS : foa_constructor_exception_tests ;
run exception/copy_exception_tests.cpp : : : $(CPP11) <define>BOOST_UNORDERED_FOA_TESTS : foa_copy_exception_tests ;
run exception/assign_exception_tests.cpp : : : $(CPP11) <define>BOOST_UNORDERED_FOA_TESTS : foa_assign_exception_tests ;
run exception/move_assign_exception_tests.cpp : : : $(CPP11) <define>BOOST_UNORDERED_FOA_TESTS : foa_move_assign_exception_tests ;
run exception/insert_exception_tests.cpp : : : $(CPP11) <define>BOOST_UNORDERED_FOA_TESTS : foa_insert_exception_tests ;
run exception/erase_exception_tests.cpp : : : $(CPP11) <define>BOOST_UNORDERED_FOA_TESTS : foa_erase_exception_tests ;
run exception/rehash_exception_tests.cpp : : : $(CPP11) <define>BOOST_UNORDERED_FOA_TESTS : foa_rehash_exception_tests ;
run exception/swap_exception_tests.cpp : : : $(CPP11) <define>BOOST_UNORDERED_FOA_TESTS : foa_swap_exception_tests ;
run exception/merge_exception_tests.cpp : : : $(CPP11) <define>BOOST_UNORDERED_FOA_TESTS : foa_merge_exception_tests ;

View File

@@ -1,17 +1,33 @@
// Copyright 2006-2009 Daniel James.
// Copyright 2022 Christian Mazakas.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// clang-format off
#include "../helpers/prefix.hpp"
#include <boost/unordered_map.hpp>
#include <boost/unordered_set.hpp>
#include "../helpers/postfix.hpp"
// clang-format on
#include "../helpers/unordered.hpp"
#include "../objects/exception.hpp"
#ifdef BOOST_UNORDERED_FOA_TESTS
typedef boost::unordered_flat_set<test::exception::object,
test::exception::hash, test::exception::equal_to,
test::exception::allocator<test::exception::object> >
test_set;
typedef boost::unordered_flat_map<test::exception::object,
test::exception::object, test::exception::hash, test::exception::equal_to,
test::exception::allocator2<test::exception::object> >
test_map;
typedef boost::unordered_flat_set<
std::pair<test::exception::object, test::exception::object>,
test::exception::hash, test::exception::equal_to,
test::exception::allocator<test::exception::object> >
test_pair_set;
#define CONTAINER_SEQ (test_set)(test_map)
#define CONTAINER_PAIR_SEQ (test_pair_set)(test_map)
#else
typedef boost::unordered_set<test::exception::object, test::exception::hash,
test::exception::equal_to,
test::exception::allocator<test::exception::object> >
@@ -42,3 +58,5 @@ typedef boost::unordered_multiset<
#define CONTAINER_SEQ (test_set)(test_multiset)(test_map)(test_multimap)
#define CONTAINER_PAIR_SEQ \
(test_pair_set)(test_pair_multiset)(test_map)(test_multimap)
#endif

View File

@@ -1,5 +1,6 @@
// Copyright 2006-2009 Daniel James.
// Copyright 2022 Christian Mazakas.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "./containers.hpp"
@@ -95,7 +96,7 @@ void insert_rehash_exception_test(
T*, Inserter insert, test::random_generator gen)
{
for (int i = 0; i < 5; ++i) {
T x;
T x(1);
rehash_prep(x);
test::random_values<T> v2(5, gen);
@@ -221,16 +222,41 @@ struct emplace_lvalue_pos_type
} emplace_lvalue_pos;
// Run the exception tests in various combinations.
using test::default_generator;
using test::limited_range;
using test::generate_collisions;
#ifdef BOOST_UNORDERED_FOA_TESTS
test_set* test_set_;
test_map* test_map_;
// clang-format off
UNORDERED_TEST(insert_exception_test,
((test_set_)(test_map_))
((insert_lvalue)(insert_lvalue_begin)(insert_lvalue_end)
(insert_lvalue_pos)(insert_single_item_range)
(emplace_lvalue)(emplace_lvalue_begin)(emplace_lvalue_end)
(emplace_lvalue_pos)
)
((default_generator)(limited_range)(generate_collisions))
)
UNORDERED_TEST(insert_rehash_exception_test,
((test_set_)(test_map_))
((insert_lvalue)(insert_lvalue_begin)(insert_lvalue_end)
(insert_lvalue_pos)(insert_single_item_range)
(emplace_lvalue)(emplace_lvalue_begin)(emplace_lvalue_end)
(emplace_lvalue_pos)
)
((default_generator)(limited_range)(generate_collisions))
)
// clang-format on
#else
test_set* test_set_;
test_multiset* test_multiset_;
test_map* test_map_;
test_multimap* test_multimap_;
using test::default_generator;
using test::limited_range;
using test::generate_collisions;
// clang-format off
UNORDERED_TEST(insert_exception_test,
((test_set_)(test_multiset_)(test_map_)(test_multimap_))
@@ -252,6 +278,7 @@ UNORDERED_TEST(insert_rehash_exception_test,
((default_generator)(limited_range)(generate_collisions))
)
// clang-format on
#endif
// Repeat insert tests with pairs
@@ -259,8 +286,13 @@ struct pair_emplace_type : inserter_base
{
template <typename T, typename Iterator> void operator()(T& x, Iterator it)
{
#ifdef BOOST_UNORDERED_FOA_TESTS
x.emplace(std::piecewise_construct, std::make_tuple(it->first),
std::make_tuple(it->second));
#else
x.emplace(boost::unordered::piecewise_construct,
boost::make_tuple(it->first), boost::make_tuple(it->second));
#endif
}
} pair_emplace;
@@ -268,12 +300,34 @@ struct pair_emplace2_type : inserter_base
{
template <typename T, typename Iterator> void operator()(T& x, Iterator it)
{
#ifdef BOOST_UNORDERED_FOA_TESTS
x.emplace_hint(x.begin(), std::piecewise_construct,
std::make_tuple(it->first),
std::make_tuple(it->second.tag1_, it->second.tag2_));
#else
x.emplace_hint(x.begin(), boost::unordered::piecewise_construct,
boost::make_tuple(it->first),
boost::make_tuple(it->second.tag1_, it->second.tag2_));
#endif
}
} pair_emplace2;
#ifdef BOOST_UNORDERED_FOA_TESTS
test_pair_set* test_pair_set_;
// clang-format off
UNORDERED_TEST(insert_exception_test,
((test_pair_set_)(test_map_))
((pair_emplace)(pair_emplace2))
((default_generator)(limited_range)(generate_collisions))
)
UNORDERED_TEST(insert_rehash_exception_test,
((test_pair_set_)(test_map_))
((pair_emplace)(pair_emplace2))
((default_generator)(limited_range)(generate_collisions))
)
// clang-format on
#else
test_pair_set* test_pair_set_;
test_pair_multiset* test_pair_multiset_;
@@ -289,6 +343,7 @@ UNORDERED_TEST(insert_rehash_exception_test,
((default_generator)(limited_range)(generate_collisions))
)
// clang-format on
#endif
// Test inserting using operator[]
@@ -393,7 +448,7 @@ template <typename T>
void insert_range_rehash_exception_test(T*, test::random_generator gen)
{
for (int i = 0; i < 5; ++i) {
T x;
T x(1);
rehash_prep(x);
test::random_values<T> v2(5, gen);
@@ -401,6 +456,19 @@ void insert_range_rehash_exception_test(T*, test::random_generator gen)
}
}
#ifdef BOOST_UNORDERED_FOA_TESTS
// clang-format off
UNORDERED_TEST(insert_range_exception_test,
((test_set_)(test_map_))
((default_generator)(limited_range)(generate_collisions))
)
UNORDERED_TEST(insert_range_rehash_exception_test,
((test_set_)(test_map_))
((default_generator)(limited_range)(generate_collisions))
)
// clang-format on
#else
// clang-format off
UNORDERED_TEST(insert_range_exception_test,
((test_set_)(test_multiset_)(test_map_)(test_multimap_))
@@ -412,5 +480,6 @@ UNORDERED_TEST(insert_range_rehash_exception_test,
((default_generator)(limited_range)(generate_collisions))
)
// clang-format on
#endif
RUN_TESTS()

View File

@@ -1,5 +1,6 @@
// Copyright 2017-2018 Daniel James.
// Copyright 2022 Christian Mazakas.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -52,6 +53,53 @@ void merge_exception_test(T1 const*, T2 const*, std::size_t count12, int tag12,
EXCEPTION_LOOP(merge_exception_test(x, y))
}
using test::default_generator;
using test::generate_collisions;
using test::limited_range;
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_set<test::exception::object, test::exception::hash,
test::exception::equal_to,
test::exception::allocator<test::exception::object> >* test_set_;
boost::unordered_flat_map<test::exception::object, test::exception::object,
test::exception::hash, test::exception::equal_to,
test::exception::allocator2<test::exception::object> >* test_map_;
// clang-format off
UNORDERED_MULTI_TEST(set_merge, merge_exception_test,
((test_set_))
((test_set_))
((0x0000)(0x6400)(0x0064)(0x0a64)(0x3232))
((0x0000)(0x0001)(0x0102))
((default_generator)(limited_range))
((default_generator)(limited_range))
)
UNORDERED_MULTI_TEST(map_merge, merge_exception_test,
((test_map_))
((test_map_))
((0x0000)(0x6400)(0x0064)(0x0a64)(0x3232))
((0x0101)(0x0200)(0x0201))
((default_generator)(limited_range))
((default_generator)(limited_range))
)
// Run fewer generate_collisions tests, as they're slow.
UNORDERED_MULTI_TEST(set_merge_collisions, merge_exception_test,
((test_set_))
((test_set_))
((0x0a0a))
((0x0202)(0x0100)(0x0201))
((generate_collisions))
((generate_collisions))
)
UNORDERED_MULTI_TEST(map_merge_collisions, merge_exception_test,
((test_map_))
((test_map_))
((0x0a0a))
((0x0000)(0x0002)(0x0102))
((generate_collisions))
((generate_collisions))
)
#else
boost::unordered_set<test::exception::object, test::exception::hash,
test::exception::equal_to,
test::exception::allocator<test::exception::object> >* test_set_;
@@ -65,10 +113,6 @@ boost::unordered_multimap<test::exception::object, test::exception::object,
test::exception::hash, test::exception::equal_to,
test::exception::allocator2<test::exception::object> >* test_multimap_;
using test::default_generator;
using test::generate_collisions;
using test::limited_range;
// clang-format off
UNORDERED_MULTI_TEST(set_merge, merge_exception_test,
((test_set_)(test_multiset_))
@@ -104,5 +148,6 @@ UNORDERED_MULTI_TEST(map_merge_collisions, merge_exception_test,
((generate_collisions))
)
// clang-format on
#endif
RUN_TESTS_QUIET()

View File

@@ -1,10 +1,15 @@
// Copyright 2006-2009 Daniel James.
// Copyright 2022 Christian Mazakas.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "./containers.hpp"
#if defined(BOOST_UNORDERED_FOA_TESTS)
#define BOOST_UNORDERED_FOA_WEAK_GUARANTEE_SWAP_EXCEPTIONS_TESTS
#endif
#include "../helpers/invariants.hpp"
#include "../helpers/random_values.hpp"
#include "../helpers/tracker.hpp"

View File

@@ -1,5 +1,6 @@
// Copyright 2006-2009 Daniel James.
// Copyright 2022 Christian Mazakas.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -53,11 +54,22 @@ namespace test {
if (test::has_unique_keys<X>::value && count != 1)
BOOST_ERROR("Non-unique key.");
#if !defined(BOOST_UNORDERED_FOA_WEAK_GUARANTEE_SWAP_EXCEPTIONS_TESTS)
// we conditionally compile this check because our FOA implementation only
// exhibits the weak guarantee when swapping throws
//
// in this case, the hasher may be changed before the predicate and the
// arrays are swapped in which case, we can can find an element by
// iteration but unfortunately, it's in the wrong slot according to the
// new hash function so count(key) can wind up returning nothing when
// there really is something
if (x1.count(key) != count) {
BOOST_ERROR("Incorrect output of count.");
std::cerr << x1.count(key) << "," << count << "\n";
}
#endif
#ifndef BOOST_UNORDERED_FOA_TESTS
// Check that the keys are in the correct bucket and are
// adjacent in the bucket.
typename X::size_type bucket = x1.bucket(key);
@@ -86,6 +98,7 @@ namespace test {
}
}
}
#endif
};
// Check that size matches up.
@@ -104,6 +117,7 @@ namespace test {
if (fabs(x1.load_factor() - load_factor) > x1.load_factor() / 64)
BOOST_ERROR("x1.load_factor() doesn't match actual load_factor.");
#ifndef BOOST_UNORDERED_FOA_TESTS
// Check that size in the buckets matches up.
typename X::size_type bucket_size = 0;
@@ -120,6 +134,7 @@ namespace test {
BOOST_ERROR("x1.size() doesn't match bucket size.");
std::cout << x1.size() << "/" << bucket_size << std::endl;
}
#endif
}
}

View File

@@ -0,0 +1,22 @@
// Copyright 2022 Christian Mazakas
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#if !defined(BOOST_UNORDERED_TEST_HELPERS_UNORDERED_HEADER)
#define BOOST_UNORDERED_TEST_HELPERS_UNORDERED_HEADER
// clang-format off
#include "prefix.hpp"
#ifdef BOOST_UNORDERED_FOA_TESTS
#include <boost/unordered/unordered_flat_set.hpp>
#include <boost/unordered/unordered_flat_map.hpp>
#include <boost/unordered/detail/implementation.hpp>
#else
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#endif
#include "postfix.hpp"
// clang-format on
#endif

View File

@@ -11,6 +11,7 @@
#if !defined(BOOST_UNORDERED_OBJECTS_MINIMAL_HEADER)
#define BOOST_UNORDERED_OBJECTS_MINIMAL_HEADER
#include <boost/core/addressof.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/core/pointer_traits.hpp>
#include <boost/move/move.hpp>
@@ -320,7 +321,7 @@ namespace test {
bool operator!() const { return !ptr_; }
static ptr pointer_to(T& p) {
return ptr(&p);
return ptr(boost::addressof(p));
}
// I'm not using the safe bool idiom because the containers should be

View File

@@ -1,14 +1,10 @@
// Copyright 2006-2009 Daniel James.
// Copyright 2022 Christian Mazakas.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// clang-format off
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
// clang-format on
#include "../helpers/unordered.hpp"
#include "../helpers/test.hpp"
#include "../objects/test.hpp"
@@ -45,6 +41,7 @@ namespace assign_tests {
BOOST_TEST(x.empty());
BOOST_TEST(test::equivalent(x.hash_function(), hf));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::detail::tracker.count_allocations == 0);
}
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "assign_tests1.2\n";
@@ -94,6 +91,7 @@ namespace assign_tests {
BOOST_TEST(test::equivalent(x1.key_eq(), eq1));
BOOST_TEST(test::equivalent(x2.hash_function(), hf1));
BOOST_TEST(test::equivalent(x2.key_eq(), eq1));
BOOST_TEST(test::detail::tracker.count_allocations == 0);
test::check_container(x1, x2);
}
@@ -199,6 +197,54 @@ namespace assign_tests {
}
}
using test::default_generator;
using test::generate_collisions;
using test::limited_range;
template <typename T> bool is_propagate(T*)
{
return T::allocator_type::is_propagate_on_assign;
}
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_map<test::object, test::object, test::hash,
test::equal_to, std::allocator<test::object> >* test_map_std_alloc;
boost::unordered_flat_set<test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_set;
boost::unordered_flat_map<test::object, test::object, test::hash,
test::equal_to, test::allocator2<test::object> >* test_map;
boost::unordered_flat_set<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::propagate_assign> >*
test_set_prop_assign;
boost::unordered_flat_map<test::object, test::object, test::hash,
test::equal_to,
test::cxx11_allocator<test::object, test::propagate_assign> >*
test_map_prop_assign;
boost::unordered_flat_set<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_assign> >*
test_set_no_prop_assign;
boost::unordered_flat_map<test::object, test::object, test::hash,
test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_assign> >*
test_map_no_prop_assign;
UNORDERED_AUTO_TEST (check_traits) {
BOOST_TEST(!is_propagate(test_set));
BOOST_TEST(is_propagate(test_set_prop_assign));
BOOST_TEST(!is_propagate(test_set_no_prop_assign));
}
UNORDERED_TEST(assign_tests1,
((test_map_std_alloc)(test_set)(test_map)(test_set_prop_assign)(test_map_prop_assign)(test_set_no_prop_assign)(test_map_no_prop_assign))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(assign_tests2,
((test_set)(test_map)(test_set_prop_assign)(test_map_prop_assign)(test_set_no_prop_assign)(test_map_no_prop_assign))(
(default_generator)(generate_collisions)(limited_range)))
#else
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
std::allocator<test::object> >* test_map_std_alloc;
@@ -239,15 +285,6 @@ namespace assign_tests {
test::cxx11_allocator<test::object, test::no_propagate_assign> >*
test_multimap_no_prop_assign;
using test::default_generator;
using test::generate_collisions;
using test::limited_range;
template <typename T> bool is_propagate(T*)
{
return T::allocator_type::is_propagate_on_assign;
}
UNORDERED_AUTO_TEST (check_traits) {
BOOST_TEST(!is_propagate(test_set));
BOOST_TEST(is_propagate(test_set_prop_assign));
@@ -269,13 +306,18 @@ namespace assign_tests {
test_set_no_prop_assign)(test_multiset_no_prop_assign)(
test_map_no_prop_assign)(test_multimap_no_prop_assign))(
(default_generator)(generate_collisions)(limited_range)))
#endif
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
UNORDERED_AUTO_TEST (assign_default_initializer_list) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Initializer List Tests\n";
std::initializer_list<std::pair<int const, int> > init;
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_map<int, int> x1;
#else
boost::unordered_map<int, int> x1;
#endif
x1[25] = 3;
x1[16] = 10;
BOOST_TEST(!x1.empty());
@@ -289,7 +331,11 @@ namespace assign_tests {
UNORDERED_AUTO_TEST (assign_initializer_list) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Initializer List Tests\n";
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_set<int> x;
#else
boost::unordered_set<int> x;
#endif
x.insert(10);
x.insert(20);
x = {1, 2, -10};

View File

@@ -1,13 +1,10 @@
// Copyright 2007-2009 Daniel James.
// Copyright 2022 Christian Mazakas.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// clang-format off
#include "../helpers/prefix.hpp"
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
// clang-format on
#include "../helpers/unordered.hpp"
#include "../helpers/test.hpp"
#include <string>
@@ -17,8 +14,13 @@ namespace at_tests {
UNORDERED_AUTO_TEST (at_tests) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Create Map" << std::endl;
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_map<std::string, int> x;
boost::unordered_flat_map<std::string, int> const& x_const(x);
#else
boost::unordered_map<std::string, int> x;
boost::unordered_map<std::string, int> const& x_const(x);
#endif
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Check empty container" << std::endl;

View File

@@ -1,23 +1,41 @@
// Copyright 2006-2009 Daniel James.
// Copyright 2022 Christian Mazakas.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// This test creates the containers with members that meet their minimum
// requirements. Makes sure everything compiles and is defined correctly.
// clang-format off
#include "../helpers/prefix.hpp"
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
// clang-format on
#include "../helpers/unordered.hpp"
#include "../helpers/test.hpp"
#include "../objects/minimal.hpp"
#include "./compile_tests.hpp"
// Explicit instantiation to catch compile-time errors
#ifdef BOOST_UNORDERED_FOA_TESTS
// emulates what was already done for previous tests but without leaking to
// the detail namespace
//
template <typename K, typename T, typename H, typename P, typename A>
class instantiate_flat_map
{
typedef boost::unordered_flat_map<K, T, H, P, A> container;
container x;
};
template class instantiate_flat_map<int, int, boost::hash<int>,
std::equal_to<int>, test::minimal::allocator<int> >;
template class instantiate_flat_map<test::minimal::assignable const,
test::minimal::default_assignable const,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<int> >;
#else
#define INSTANTIATE(type) \
template class boost::unordered::detail::instantiate_##type
@@ -35,6 +53,7 @@ INSTANTIATE(multimap)<test::minimal::assignable, test::minimal::assignable,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<int> >;
#endif
UNORDERED_AUTO_TEST (test0) {
test::minimal::constructor_param x;
@@ -45,6 +64,19 @@ UNORDERED_AUTO_TEST (test0) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_map.\n";
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_map<int, int> int_map;
boost::unordered_flat_map<int, int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<std::pair<int const, int> > >
int_map2;
boost::unordered_flat_map<test::minimal::assignable,
test::minimal::assignable, test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<value_type> >
map;
#else
boost::unordered_map<int, int> int_map;
boost::unordered_map<int, int, boost::hash<int>, std::equal_to<int>,
@@ -56,11 +88,13 @@ UNORDERED_AUTO_TEST (test0) {
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<value_type> >
map;
#endif
container_test(int_map, std::pair<int const, int>(0, 0));
container_test(int_map2, std::pair<int const, int>(0, 0));
container_test(map, value);
#ifndef BOOST_UNORDERED_FOA_TESTS
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multimap.\n";
boost::unordered_multimap<int, int> int_multimap;
@@ -78,6 +112,7 @@ UNORDERED_AUTO_TEST (test0) {
container_test(int_multimap, std::pair<int const, int>(0, 0));
container_test(int_multimap2, std::pair<int const, int>(0, 0));
container_test(multimap, value);
#endif
}
UNORDERED_AUTO_TEST (equality_tests) {
@@ -85,6 +120,22 @@ UNORDERED_AUTO_TEST (equality_tests) {
test::minimal::copy_constructible_equality_comparable>
value_type;
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_map<int, int> int_map;
boost::unordered_flat_map<int, int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<std::pair<int const, int> > >
int_map2;
boost::unordered_flat_map<
test::minimal::copy_constructible_equality_comparable,
test::minimal::copy_constructible_equality_comparable,
test::minimal::hash<test::minimal::copy_constructible_equality_comparable>,
test::minimal::equal_to<
test::minimal::copy_constructible_equality_comparable>,
test::minimal::allocator<value_type> >
map;
#else
boost::unordered_map<int, int> int_map;
boost::unordered_map<int, int, boost::hash<int>, std::equal_to<int>,
@@ -98,11 +149,13 @@ UNORDERED_AUTO_TEST (equality_tests) {
test::minimal::copy_constructible_equality_comparable>,
test::minimal::allocator<value_type> >
map;
#endif
equality_test(int_map);
equality_test(int_map2);
equality_test(map);
#ifndef BOOST_UNORDERED_FOA_TESTS
boost::unordered_multimap<int, int> int_multimap;
boost::unordered_multimap<int, int, boost::hash<int>, std::equal_to<int>,
@@ -121,6 +174,7 @@ UNORDERED_AUTO_TEST (equality_tests) {
equality_test(int_multimap);
equality_test(int_multimap2);
equality_test(multimap);
#endif
}
UNORDERED_AUTO_TEST (test1) {
@@ -131,11 +185,19 @@ UNORDERED_AUTO_TEST (test1) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_map.\n";
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_map<int, int> map;
boost::unordered_flat_map<int, int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<std::pair<int const, int> > >
map2;
#else
boost::unordered_map<int, int> map;
boost::unordered_map<int, int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<std::pair<int const, int> > >
map2;
#endif
unordered_unique_test(map, map_value);
unordered_map_test(map, value, value);
@@ -147,6 +209,7 @@ UNORDERED_AUTO_TEST (test1) {
unordered_copyable_test(map2, value, map_value, hash, equal_to);
unordered_map_functions(map2, value, value);
#ifndef BOOST_UNORDERED_FOA_TESTS
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multimap.\n";
boost::unordered_multimap<int, int> multimap;
@@ -162,6 +225,7 @@ UNORDERED_AUTO_TEST (test1) {
unordered_equivalent_test(multimap2, map_value);
unordered_map_test(multimap2, value, value);
unordered_copyable_test(multimap2, value, map_value, hash, equal_to);
#endif
}
UNORDERED_AUTO_TEST (test2) {
@@ -178,28 +242,46 @@ UNORDERED_AUTO_TEST (test2) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_map.\n";
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_map<test::minimal::assignable,
test::minimal::assignable, test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<map_value_type> >
map;
#else
boost::unordered_map<test::minimal::assignable, test::minimal::assignable,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<map_value_type> >
map;
#endif
unordered_unique_test(map, map_value);
unordered_map_test(map, assignable, assignable);
unordered_copyable_test(map, assignable, map_value, hash, equal_to);
unordered_map_member_test(map, map_value);
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_map<test::minimal::assignable,
test::minimal::default_assignable,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<map_value_type> >
map2;
#else
boost::unordered_map<test::minimal::assignable,
test::minimal::default_assignable,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<map_value_type> >
map2;
#endif
test::minimal::default_assignable default_assignable;
unordered_map_functions(map2, assignable, default_assignable);
#ifndef BOOST_UNORDERED_FOA_TESTS
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multimap.\n";
boost::unordered_multimap<test::minimal::assignable,
@@ -212,6 +294,7 @@ UNORDERED_AUTO_TEST (test2) {
unordered_map_test(multimap, assignable, assignable);
unordered_copyable_test(multimap, assignable, map_value, hash, equal_to);
unordered_map_member_test(multimap, map_value);
#endif
}
// Test for ambiguity when using key convertible from iterator
@@ -232,6 +315,11 @@ std::size_t hash_value(lwg2059_key x)
bool operator==(lwg2059_key x, lwg2059_key y) { return x.value == y.value; }
UNORDERED_AUTO_TEST (lwg2059) {
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_map<lwg2059_key, int> x;
x.emplace(lwg2059_key(10), 5);
x.erase(x.begin());
#else
{
boost::unordered_map<lwg2059_key, int> x;
x.emplace(lwg2059_key(10), 5);
@@ -243,6 +331,7 @@ UNORDERED_AUTO_TEST (lwg2059) {
x.emplace(lwg2059_key(10), 5);
x.erase(x.begin());
}
#endif
}
RUN_TESTS()

View File

@@ -1,16 +1,13 @@
// Copyright 2006-2009 Daniel James.
// Copyright 2022 Christian Mazakas.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// This test creates the containers with members that meet their minimum
// requirements. Makes sure everything compiles and is defined correctly.
// clang-format off
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include "../helpers/postfix.hpp"
// clang-format on
#include "../helpers/unordered.hpp"
#include "../helpers/test.hpp"
#include "../objects/minimal.hpp"
@@ -18,6 +15,28 @@
// Explicit instantiation to catch compile-time errors
#ifdef BOOST_UNORDERED_FOA_TESTS
// emulates what was already done for previous tests but without leaking to
// the detail namespace
//
template <typename T, typename H, typename P, typename A>
class instantiate_flat_set
{
typedef boost::unordered_flat_set<T, H, P, A> container;
container x;
};
template class instantiate_flat_set<int, boost::hash<int>, std::equal_to<int>,
test::minimal::allocator<int> >;
template class instantiate_flat_set<test::minimal::assignable const,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<int> >;
#else
#define INSTANTIATE(type) \
template class boost::unordered::detail::instantiate_##type
@@ -35,6 +54,21 @@ INSTANTIATE(multiset)<test::minimal::assignable,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<int> >;
#endif
UNORDERED_AUTO_TEST (type_traits) {
#ifdef BOOST_UNORDERED_FOA_TESTS
typedef boost::unordered_flat_set<int> set_type;
#else
typedef boost::unordered_set<int> set_type;
#endif
typedef set_type::iterator iterator;
BOOST_STATIC_ASSERT(boost::is_same<int const&,
std::iterator_traits<iterator>::reference>::value);
}
UNORDERED_AUTO_TEST (test0) {
test::minimal::constructor_param x;
@@ -42,6 +76,19 @@ UNORDERED_AUTO_TEST (test0) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_set.\n";
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_set<int> int_set;
boost::unordered_flat_set<int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<int> >
int_set2;
boost::unordered_flat_set<test::minimal::assignable,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<test::minimal::assignable> >
set;
#else
boost::unordered_set<int> int_set;
boost::unordered_set<int, boost::hash<int>, std::equal_to<int>,
@@ -53,11 +100,13 @@ UNORDERED_AUTO_TEST (test0) {
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<test::minimal::assignable> >
set;
#endif
container_test(int_set, 0);
container_test(int_set2, 0);
container_test(set, assignable);
#ifndef BOOST_UNORDERED_FOA_TESTS
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multiset.\n";
boost::unordered_multiset<int> int_multiset;
@@ -75,11 +124,27 @@ UNORDERED_AUTO_TEST (test0) {
container_test(int_multiset, 0);
container_test(int_multiset2, 0);
container_test(multiset, assignable);
#endif
}
UNORDERED_AUTO_TEST (equality_tests) {
typedef test::minimal::copy_constructible_equality_comparable value_type;
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_set<int> int_set;
boost::unordered_flat_set<int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<int> >
int_set2;
boost::unordered_flat_set<
test::minimal::copy_constructible_equality_comparable,
test::minimal::hash<test::minimal::copy_constructible_equality_comparable>,
test::minimal::equal_to<
test::minimal::copy_constructible_equality_comparable>,
test::minimal::allocator<value_type> >
set;
#else
boost::unordered_set<int> int_set;
boost::unordered_set<int, boost::hash<int>, std::equal_to<int>,
@@ -92,11 +157,13 @@ UNORDERED_AUTO_TEST (equality_tests) {
test::minimal::copy_constructible_equality_comparable>,
test::minimal::allocator<value_type> >
set;
#endif
equality_test(int_set);
equality_test(int_set2);
equality_test(set);
#ifndef BOOST_UNORDERED_FOA_TESTS
boost::unordered_multiset<int> int_multiset;
boost::unordered_multiset<int, boost::hash<int>, std::equal_to<int>,
@@ -114,6 +181,7 @@ UNORDERED_AUTO_TEST (equality_tests) {
equality_test(int_multiset);
equality_test(int_multiset2);
equality_test(multiset);
#endif
}
UNORDERED_AUTO_TEST (test1) {
@@ -122,12 +190,19 @@ UNORDERED_AUTO_TEST (test1) {
int value = 0;
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_set." << std::endl;
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_set<int> set;
boost::unordered_flat_set<int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<int> >
set2;
#else
boost::unordered_set<int> set;
boost::unordered_set<int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<int> >
set2;
#endif
unordered_unique_test(set, value);
unordered_set_test(set, value);
@@ -137,6 +212,7 @@ UNORDERED_AUTO_TEST (test1) {
unordered_set_test(set2, value);
unordered_copyable_test(set2, value, value, hash, equal_to);
#ifndef BOOST_UNORDERED_FOA_TESTS
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multiset." << std::endl;
boost::unordered_multiset<int> multiset;
@@ -152,6 +228,7 @@ UNORDERED_AUTO_TEST (test1) {
unordered_equivalent_test(multiset2, value);
unordered_set_test(multiset2, value);
unordered_copyable_test(multiset2, value, value, hash, equal_to);
#endif
}
UNORDERED_AUTO_TEST (test2) {
@@ -163,18 +240,26 @@ UNORDERED_AUTO_TEST (test2) {
test::minimal::equal_to<test::minimal::assignable> equal_to(x);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_set.\n";
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_set<test::minimal::assignable,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<test::minimal::assignable> >
set;
#else
boost::unordered_set<test::minimal::assignable,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<test::minimal::assignable> >
set;
#endif
unordered_unique_test(set, assignable);
unordered_set_test(set, assignable);
unordered_copyable_test(set, assignable, assignable, hash, equal_to);
unordered_set_member_test(set, assignable);
#ifndef BOOST_UNORDERED_FOA_TESTS
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multiset.\n";
boost::unordered_multiset<test::minimal::assignable,
@@ -187,6 +272,7 @@ UNORDERED_AUTO_TEST (test2) {
unordered_set_test(multiset, assignable);
unordered_copyable_test(multiset, assignable, assignable, hash, equal_to);
unordered_set_member_test(multiset, assignable);
#endif
}
UNORDERED_AUTO_TEST (movable1_tests) {
@@ -197,17 +283,25 @@ UNORDERED_AUTO_TEST (movable1_tests) {
test::minimal::equal_to<test::minimal::movable1> equal_to(x);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_set.\n";
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_set<test::minimal::movable1,
test::minimal::hash<test::minimal::movable1>,
test::minimal::equal_to<test::minimal::movable1>,
test::minimal::allocator<test::minimal::movable1> >
set;
#else
boost::unordered_set<test::minimal::movable1,
test::minimal::hash<test::minimal::movable1>,
test::minimal::equal_to<test::minimal::movable1>,
test::minimal::allocator<test::minimal::movable1> >
set;
#endif
// unordered_unique_test(set, movable1);
unordered_set_test(set, movable1);
unordered_movable_test(set, movable1, movable1, hash, equal_to);
#ifndef BOOST_UNORDERED_FOA_TESTS
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multiset.\n";
boost::unordered_multiset<test::minimal::movable1,
@@ -219,6 +313,7 @@ UNORDERED_AUTO_TEST (movable1_tests) {
// unordered_equivalent_test(multiset, movable1);
unordered_set_test(multiset, movable1);
unordered_movable_test(multiset, movable1, movable1, hash, equal_to);
#endif
}
UNORDERED_AUTO_TEST (movable2_tests) {
@@ -229,17 +324,25 @@ UNORDERED_AUTO_TEST (movable2_tests) {
test::minimal::equal_to<test::minimal::movable2> equal_to(x);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_set.\n";
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_set<test::minimal::movable2,
test::minimal::hash<test::minimal::movable2>,
test::minimal::equal_to<test::minimal::movable2>,
test::minimal::allocator<test::minimal::movable2> >
set;
#else
boost::unordered_set<test::minimal::movable2,
test::minimal::hash<test::minimal::movable2>,
test::minimal::equal_to<test::minimal::movable2>,
test::minimal::allocator<test::minimal::movable2> >
set;
#endif
// unordered_unique_test(set, movable2);
unordered_set_test(set, movable2);
unordered_movable_test(set, movable2, movable2, hash, equal_to);
#ifndef BOOST_UNORDERED_FOA_TESTS
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multiset.\n";
boost::unordered_multiset<test::minimal::movable2,
@@ -251,6 +354,7 @@ UNORDERED_AUTO_TEST (movable2_tests) {
// unordered_equivalent_test(multiset, movable2);
unordered_set_test(multiset, movable2);
unordered_movable_test(multiset, movable2, movable2, hash, equal_to);
#endif
}
UNORDERED_AUTO_TEST (destructible_tests) {
@@ -261,14 +365,21 @@ UNORDERED_AUTO_TEST (destructible_tests) {
test::minimal::equal_to<test::minimal::destructible> equal_to(x);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_set.\n";
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_set<test::minimal::destructible,
test::minimal::hash<test::minimal::destructible>,
test::minimal::equal_to<test::minimal::destructible> >
set;
#else
boost::unordered_set<test::minimal::destructible,
test::minimal::hash<test::minimal::destructible>,
test::minimal::equal_to<test::minimal::destructible> >
set;
#endif
unordered_destructible_test(set);
#ifndef BOOST_UNORDERED_FOA_TESTS
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multiset.\n";
boost::unordered_multiset<test::minimal::destructible,
@@ -277,6 +388,7 @@ UNORDERED_AUTO_TEST (destructible_tests) {
multiset;
unordered_destructible_test(multiset);
#endif
}
// Test for ambiguity when using key convertible from iterator
@@ -297,6 +409,11 @@ std::size_t hash_value(lwg2059_key x)
bool operator==(lwg2059_key x, lwg2059_key y) { return x.value == y.value; }
UNORDERED_AUTO_TEST (lwg2059) {
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_set<lwg2059_key> x;
x.emplace(lwg2059_key(10));
x.erase(x.begin());
#else
{
boost::unordered_set<lwg2059_key> x;
x.emplace(lwg2059_key(10));
@@ -308,6 +425,7 @@ UNORDERED_AUTO_TEST (lwg2059) {
x.emplace(lwg2059_key(10));
x.erase(x.begin());
}
#endif
}
RUN_TESTS()

View File

@@ -1,5 +1,6 @@
// Copyright 2005-2009 Daniel James.
// Copyright 2022 Christian Mazakas.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -70,9 +71,19 @@ template <class X, class T> void container_test(X& r, T const&)
typedef typename X::reference reference;
typedef typename X::const_reference const_reference;
#ifndef BOOST_UNORDERED_FOA_TESTS
typedef typename X::node_type node_type;
#endif
typedef typename X::allocator_type allocator_type;
typedef typename X::pointer pointer;
typedef typename X::const_pointer const_pointer;
BOOST_STATIC_ASSERT((boost::is_same<pointer,
typename boost::allocator_pointer<allocator_type>::type>::value));
BOOST_STATIC_ASSERT((boost::is_same<const_pointer,
typename boost::allocator_const_pointer<allocator_type>::type>::value));
// value_type
@@ -97,8 +108,10 @@ template <class X, class T> void container_test(X& r, T const&)
// node_type
#ifndef BOOST_UNORDERED_FOA_TESTS
BOOST_STATIC_ASSERT((
boost::is_same<allocator_type, typename node_type::allocator_type>::value));
#endif
// difference_type
@@ -167,6 +180,7 @@ template <class X, class T> void container_test(X& r, T const&)
sink(X(rvalue(a_const), m));
X c3(rvalue(a_const), m);
#ifndef BOOST_UNORDERED_FOA_TESTS
// node_type
implicit_construct<node_type const>();
@@ -193,6 +207,7 @@ template <class X, class T> void container_test(X& r, T const&)
test::check_return_type<bool>::equals(n_const.empty());
TEST_NOEXCEPT_EXPR(!n_const);
TEST_NOEXCEPT_EXPR(n_const.empty());
#endif
// Avoid unused variable warnings:
@@ -262,24 +277,30 @@ template <class X, class Key> void unordered_set_test(X& r, Key const&)
typedef typename X::iterator iterator;
typedef typename X::const_iterator const_iterator;
#ifndef BOOST_UNORDERED_FOA_TESTS
typedef typename X::local_iterator local_iterator;
typedef typename X::const_local_iterator const_local_iterator;
#endif
typedef typename std::iterator_traits<iterator>::pointer iterator_pointer;
typedef typename std::iterator_traits<const_iterator>::pointer
const_iterator_pointer;
#ifndef BOOST_UNORDERED_FOA_TESTS
typedef typename std::iterator_traits<local_iterator>::pointer
local_iterator_pointer;
typedef typename std::iterator_traits<const_local_iterator>::pointer
const_local_iterator_pointer;
#endif
BOOST_STATIC_ASSERT(
(boost::is_same<value_type const*, iterator_pointer>::value));
BOOST_STATIC_ASSERT(
(boost::is_same<value_type const*, const_iterator_pointer>::value));
#ifndef BOOST_UNORDERED_FOA_TESTS
BOOST_STATIC_ASSERT(
(boost::is_same<value_type const*, local_iterator_pointer>::value));
BOOST_STATIC_ASSERT(
(boost::is_same<value_type const*, const_local_iterator_pointer>::value));
#endif
// pointer_traits<iterator>
@@ -299,6 +320,8 @@ template <class X, class Key> void unordered_set_test(X& r, Key const&)
BOOST_STATIC_ASSERT((boost::is_same<std::ptrdiff_t,
typename boost::pointer_traits<const_iterator>::difference_type>::value));
(void) r;
#ifndef BOOST_UNORDERED_FOA_TESTS
// pointer_traits<local_iterator>
BOOST_STATIC_ASSERT((boost::is_same<local_iterator,
@@ -330,6 +353,7 @@ template <class X, class Key> void unordered_set_test(X& r, Key const&)
r.emplace(boost::move(k_lvalue));
node_type n1 = r.extract(r.begin());
test::check_return_type<value_type>::equals_ref(n1.value());
#endif
}
template <class X, class Key, class T>
@@ -345,23 +369,29 @@ void unordered_map_test(X& r, Key const& k, T const& v)
typedef typename X::iterator iterator;
typedef typename X::const_iterator const_iterator;
#ifndef BOOST_UNORDERED_FOA_TESTS
typedef typename X::local_iterator local_iterator;
typedef typename X::const_local_iterator const_local_iterator;
#endif
typedef typename std::iterator_traits<iterator>::pointer iterator_pointer;
typedef typename std::iterator_traits<const_iterator>::pointer
const_iterator_pointer;
#ifndef BOOST_UNORDERED_FOA_TESTS
typedef typename std::iterator_traits<local_iterator>::pointer
local_iterator_pointer;
typedef typename std::iterator_traits<const_local_iterator>::pointer
const_local_iterator_pointer;
#endif
BOOST_STATIC_ASSERT((boost::is_same<value_type*, iterator_pointer>::value));
BOOST_STATIC_ASSERT(
(boost::is_same<value_type const*, const_iterator_pointer>::value));
#ifndef BOOST_UNORDERED_FOA_TESTS
BOOST_STATIC_ASSERT(
(boost::is_same<value_type*, local_iterator_pointer>::value));
BOOST_STATIC_ASSERT(
(boost::is_same<value_type const*, const_local_iterator_pointer>::value));
#endif
// pointer_traits<iterator>
@@ -381,6 +411,7 @@ void unordered_map_test(X& r, Key const& k, T const& v)
BOOST_STATIC_ASSERT((boost::is_same<std::ptrdiff_t,
typename boost::pointer_traits<const_iterator>::difference_type>::value));
#ifndef BOOST_UNORDERED_FOA_TESTS
// pointer_traits<local_iterator>
BOOST_STATIC_ASSERT((boost::is_same<local_iterator,
@@ -409,6 +440,7 @@ void unordered_map_test(X& r, Key const& k, T const& v)
BOOST_STATIC_ASSERT((boost::is_same<T, node_mapped_type>::value));
// Superfluous,but just to make sure.
BOOST_STATIC_ASSERT((!boost::is_const<node_key_type>::value));
#endif
// Calling functions
@@ -427,8 +459,12 @@ void unordered_map_test(X& r, Key const& k, T const& v)
r.emplace(k_lvalue, v_lvalue);
r.emplace(rvalue(k), rvalue(v));
#ifdef BOOST_UNORDERED_FOA_TESTS
r.emplace(std::piecewise_construct, std::make_tuple(k), std::make_tuple(v));
#else
r.emplace(boost::unordered::piecewise_construct, boost::make_tuple(k),
boost::make_tuple(v));
#endif
// Emplace with hint
@@ -436,9 +472,15 @@ void unordered_map_test(X& r, Key const& k, T const& v)
r.emplace_hint(r.begin(), k_lvalue, v_lvalue);
r.emplace_hint(r.begin(), rvalue(k), rvalue(v));
#ifdef BOOST_UNORDERED_FOA_TESTS
r.emplace_hint(r.begin(), std::piecewise_construct, std::make_tuple(k),
std::make_tuple(v));
#else
r.emplace_hint(r.begin(), boost::unordered::piecewise_construct,
boost::make_tuple(k), boost::make_tuple(v));
#endif
#ifndef BOOST_UNORDERED_FOA_TESTS
// Extract
test::check_return_type<node_type>::equals(r.extract(r.begin()));
@@ -461,6 +503,7 @@ void unordered_map_test(X& r, Key const& k, T const& v)
node_type n = r.extract(r.begin());
test::check_return_type<node_key_type>::equals_ref(n.key());
test::check_return_type<node_mapped_type>::equals_ref(n.mapped());
#endif
}
template <class X> void equality_test(X& r)
@@ -479,6 +522,7 @@ template <class X, class T> void unordered_unique_test(X& r, T const& t)
test::check_return_type<std::pair<iterator, bool> >::equals(r.insert(t));
test::check_return_type<std::pair<iterator, bool> >::equals(r.emplace(t));
#ifndef BOOST_UNORDERED_FOA_TESTS
typedef typename X::node_type node_type;
typedef typename X::insert_return_type insert_return_type;
@@ -503,6 +547,7 @@ template <class X, class T> void unordered_unique_test(X& r, T const& t)
test::check_return_type<iterator>::equals(insert_return.position);
test::check_return_type<node_type>::equals_ref(insert_return.node);
boost::swap(insert_return, insert_return2);
#endif
}
template <class X, class T> void unordered_equivalent_test(X& r, T const& t)
@@ -554,6 +599,7 @@ void unordered_test(X& x, Key& k, Hash& hf, Pred& eq)
typedef typename X::iterator iterator;
typedef typename X::const_iterator const_iterator;
#ifndef BOOST_UNORDERED_FOA_TESTS
typedef typename X::local_iterator local_iterator;
typedef typename X::const_local_iterator const_local_iterator;
@@ -590,6 +636,7 @@ void unordered_test(X& x, Key& k, Hash& hf, Pred& eq)
const_local_iterator_pointer;
typedef typename std::iterator_traits<const_local_iterator>::reference
const_local_iterator_reference;
#endif
typedef typename X::allocator_type allocator_type;
BOOST_STATIC_ASSERT((boost::is_same<Key, key_type>::value));
@@ -602,6 +649,7 @@ void unordered_test(X& x, Key& k, Hash& hf, Pred& eq)
BOOST_STATIC_ASSERT((boost::is_same<Pred, key_equal>::value));
test::check_return_type<bool>::convertible(eq(k, k));
#ifndef BOOST_UNORDERED_FOA_TESTS
boost::function_requires<boost::InputIteratorConcept<local_iterator> >();
BOOST_STATIC_ASSERT(
(boost::is_same<local_iterator_category, iterator_category>::value));
@@ -622,6 +670,7 @@ void unordered_test(X& x, Key& k, Hash& hf, Pred& eq)
const_iterator_pointer>::value));
BOOST_STATIC_ASSERT((boost::is_same<const_local_iterator_reference,
const_iterator_reference>::value));
#endif
X a;
allocator_type m = a.get_allocator();
@@ -667,6 +716,7 @@ void unordered_test(X& x, Key& k, Hash& hf, Pred& eq)
test::check_return_type<std::pair<const_iterator, const_iterator> >::equals(
b.equal_range(k));
test::check_return_type<size_type>::equals(b.bucket_count());
#ifndef BOOST_UNORDERED_FOA_TESTS
test::check_return_type<size_type>::equals(b.max_bucket_count());
test::check_return_type<size_type>::equals(b.bucket(k));
test::check_return_type<size_type>::equals(b.bucket_size(0));
@@ -680,6 +730,7 @@ void unordered_test(X& x, Key& k, Hash& hf, Pred& eq)
test::check_return_type<const_local_iterator>::equals(b.cbegin(0));
test::check_return_type<const_local_iterator>::equals(a.cend(0));
test::check_return_type<const_local_iterator>::equals(b.cend(0));
#endif
test::check_return_type<float>::equals(b.load_factor());
test::check_return_type<float>::equals(b.max_load_factor());
@@ -792,7 +843,11 @@ void unordered_copyable_test(X& x, Key& k, T& t, Hash& hf, Pred& eq)
X a10;
a10.insert(t);
q = a10.cbegin();
#ifdef BOOST_UNORDERED_FOA_TESTS
BOOST_STATIC_ASSERT(std::is_same<void, decltype(a10.erase(q))>::value);
#else
test::check_return_type<iterator>::equals(a10.erase(q));
#endif
// Avoid unused variable warnings:
@@ -807,10 +862,12 @@ void unordered_copyable_test(X& x, Key& k, T& t, Hash& hf, Pred& eq)
sink(a7a);
sink(a9a);
#ifndef BOOST_UNORDERED_FOA_TESTS
typedef typename X::node_type node_type;
typedef typename X::allocator_type allocator_type;
node_type const n_const = a.extract(a.begin());
test::check_return_type<allocator_type>::equals(n_const.get_allocator());
#endif
}
template <class X, class Key, class T, class Hash, class Pred>
@@ -879,7 +936,11 @@ void unordered_movable_test(X& x, Key& k, T& /* t */, Hash& hf, Pred& eq)
T v5(v);
a10.insert(boost::move(v5));
q = a10.cbegin();
#ifdef BOOST_UNORDERED_FOA_TESTS
BOOST_STATIC_ASSERT(std::is_same<void, decltype(a10.erase(q))>::value);
#else
test::check_return_type<iterator>::equals(a10.erase(q));
#endif
// Avoid unused variable warnings:

View File

@@ -1,14 +1,10 @@
// Copyright 2006-2010 Daniel James.
// Copyright (C) 2022 Christian Mazakas
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// clang-format off
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
// clang-format on
#include "../helpers/unordered.hpp"
#include "../helpers/test.hpp"
#include "../objects/test.hpp"
@@ -35,6 +31,7 @@ namespace constructor_tests {
T x(0, hf, eq);
BOOST_TEST(x.empty());
BOOST_TEST_EQ(x.bucket_count(), 0u);
BOOST_TEST(test::equivalent(x.hash_function(), hf));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
@@ -73,6 +70,7 @@ namespace constructor_tests {
T x;
BOOST_TEST(x.empty());
BOOST_TEST_EQ(x.bucket_count(), 0u);
BOOST_TEST(test::equivalent(x.hash_function(), hf));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
@@ -140,6 +138,7 @@ namespace constructor_tests {
T x(0, hf, eq, al);
BOOST_TEST(x.empty());
BOOST_TEST_EQ(x.bucket_count(), 0u);
BOOST_TEST(test::equivalent(x.hash_function(), hf));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
@@ -166,6 +165,7 @@ namespace constructor_tests {
T x(al);
BOOST_TEST(x.empty());
BOOST_TEST_EQ(x.bucket_count(), 0u);
BOOST_TEST(test::equivalent(x.hash_function(), hf));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
@@ -325,6 +325,7 @@ namespace constructor_tests {
T x(list);
BOOST_TEST(x.empty());
BOOST_TEST_EQ(x.bucket_count(), 0u);
BOOST_TEST(test::equivalent(x.hash_function(), hf));
BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al));
@@ -380,6 +381,104 @@ namespace constructor_tests {
#endif
}
template <class T>
void no_alloc_default_construct_test(T*, test::random_generator)
{
UNORDERED_SUB_TEST("Construct 1")
{
T x;
BOOST_TEST_EQ(x.bucket_count(), 0u);
BOOST_TEST_EQ(test::detail::tracker.count_allocations, 0u);
}
UNORDERED_SUB_TEST("Construct 2")
{
{
T x(0);
BOOST_TEST_EQ(x.bucket_count(), 0u);
BOOST_TEST_EQ(test::detail::tracker.count_allocations, 0u);
}
{
T x(1);
BOOST_TEST_GT(x.bucket_count(), 0u);
BOOST_TEST_GT(test::detail::tracker.count_allocations, 0u);
}
}
UNORDERED_SUB_TEST("Construct 3")
{
test::random_values<T> v;
T x(v.begin(), v.end());
BOOST_TEST_EQ(x.bucket_count(), 0u);
BOOST_TEST_EQ(test::detail::tracker.count_allocations, 0u);
}
UNORDERED_SUB_TEST("Construct 4")
{
{
test::random_values<T> v;
T x(v.begin(), v.end(), 0);
BOOST_TEST_EQ(x.bucket_count(), 0u);
BOOST_TEST_EQ(test::detail::tracker.count_allocations, 0u);
}
{
test::random_values<T> v;
T x(v.begin(), v.end(), 1);
BOOST_TEST_GT(x.bucket_count(), 0u);
BOOST_TEST_GT(test::detail::tracker.count_allocations, 0u);
}
}
UNORDERED_SUB_TEST("Construct 5")
{
typename T::allocator_type al;
{
T x(al);
BOOST_TEST_EQ(x.bucket_count(), 0u);
BOOST_TEST_EQ(test::detail::tracker.count_allocations, 0u);
}
}
UNORDERED_SUB_TEST("Construct 6")
{
typename T::allocator_type al;
T x(0, al);
BOOST_TEST_EQ(x.bucket_count(), 0u);
BOOST_TEST_EQ(test::detail::tracker.count_allocations, 0u);
}
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
UNORDERED_SUB_TEST("Initializer list 1")
{
std::initializer_list<typename T::value_type> list;
T x(list);
BOOST_TEST_EQ(x.bucket_count(), 0u);
BOOST_TEST_EQ(test::detail::tracker.count_allocations, 0u);
}
UNORDERED_SUB_TEST("Initializer list 2")
{
{
std::initializer_list<typename T::value_type> list;
T x(list, 0);
BOOST_TEST_EQ(x.bucket_count(), 0u);
BOOST_TEST_EQ(test::detail::tracker.count_allocations, 0u);
}
{
std::initializer_list<typename T::value_type> list;
T x(list, 1);
BOOST_TEST_GT(x.bucket_count(), 0u);
BOOST_TEST_GT(test::detail::tracker.count_allocations, 0u);
}
}
#endif
}
template <class T>
void map_constructor_test(T*, test::random_generator const& generator)
{
@@ -394,6 +493,35 @@ namespace constructor_tests {
test::check_equivalent_keys(x);
}
using test::default_generator;
using test::generate_collisions;
using test::limited_range;
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_map<test::object, test::object, test::hash,
test::equal_to, std::allocator<test::object> >* test_map_std_alloc;
boost::unordered_flat_set<test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_set;
boost::unordered_flat_map<test::object, test::object, test::hash,
test::equal_to, test::allocator2<test::object> >* test_map;
UNORDERED_TEST(constructor_tests1,
((test_map_std_alloc)(test_set)(test_map))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(constructor_tests2,
((test_set)(test_map))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(map_constructor_test,
((test_map_std_alloc)(test_map))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(no_alloc_default_construct_test,
((test_set)(test_map))(
(default_generator)(generate_collisions)(limited_range)))
#else
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
std::allocator<test::object> >* test_map_std_alloc;
@@ -406,10 +534,6 @@ namespace constructor_tests {
boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to, test::allocator1<test::object> >* test_multimap;
using test::default_generator;
using test::generate_collisions;
using test::limited_range;
UNORDERED_TEST(constructor_tests1,
((test_map_std_alloc)(test_set)(test_multiset)(test_map)(test_multimap))(
(default_generator)(generate_collisions)(limited_range)))
@@ -422,11 +546,20 @@ namespace constructor_tests {
((test_map_std_alloc)(test_map)(test_multimap))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(no_alloc_default_construct_test,
((test_set)(test_multiset)(test_map)(test_multimap))(
(default_generator)(generate_collisions)(limited_range)))
#endif
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
UNORDERED_AUTO_TEST (test_default_initializer_list) {
std::initializer_list<int> init;
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_set<int> x1 = init;
#else
boost::unordered_set<int> x1 = init;
#endif
BOOST_TEST(x1.empty());
}
@@ -435,7 +568,12 @@ namespace constructor_tests {
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
UNORDERED_AUTO_TEST (test_initializer_list) {
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_set<int> x1 = {2, 10, 45, -5};
#else
boost::unordered_set<int> x1 = {2, 10, 45, -5};
#endif
BOOST_TEST(x1.find(10) != x1.end());
BOOST_TEST(x1.find(46) == x1.end());
}

View File

@@ -1,13 +1,8 @@
// Copyright 2021 Christian Mazakas.
// Copyright 2021-2022 Christian Mazakas.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// clang-format off
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
// clang-format on
#include "../helpers/unordered.hpp"
#include "../helpers/test.hpp"
@@ -129,6 +124,20 @@ template <class UnorderedMap> void test_map_non_transparent_contains()
void test_map()
{
#ifdef BOOST_UNORDERED_FOA_TESTS
typedef boost::unordered_flat_map<key, int, transparent_hasher,
transparent_key_equal>
transparent_map;
typedef boost::unordered_flat_map<key, int, transparent_hasher, key_equal>
non_transparent_map1;
typedef boost::unordered_flat_map<key, int, hasher, transparent_key_equal>
non_transparent_map2;
typedef boost::unordered_flat_map<key, int, hasher, key_equal>
non_transparent_map3;
#else
typedef boost::unordered_map<key, int, transparent_hasher,
transparent_key_equal>
transparent_map;
@@ -141,6 +150,7 @@ void test_map()
typedef boost::unordered_map<key, int, hasher, key_equal>
non_transparent_map3;
#endif
test_map_transparent_contains<transparent_map>();
test_map_non_transparent_contains<non_transparent_map1>();
@@ -148,6 +158,7 @@ void test_map()
test_map_non_transparent_contains<non_transparent_map3>();
}
#ifndef BOOST_UNORDERED_FOA_TESTS
void test_multimap()
{
typedef boost::unordered_multimap<key, int, transparent_hasher,
@@ -168,6 +179,7 @@ void test_multimap()
test_map_non_transparent_contains<non_transparent_multimap2>();
test_map_non_transparent_contains<non_transparent_multimap3>();
}
#endif
template <class UnorderedSet> void test_set_transparent_contains()
{
@@ -231,6 +243,18 @@ template <class UnorderedSet> void test_set_non_transparent_contains()
void test_set()
{
#ifdef BOOST_UNORDERED_FOA_TESTS
typedef boost::unordered_flat_set<key, transparent_hasher,
transparent_key_equal>
transparent_set;
typedef boost::unordered_flat_set<key, transparent_hasher, key_equal>
non_transparent_set1;
typedef boost::unordered_flat_set<key, hasher, transparent_key_equal>
non_transparent_set2;
typedef boost::unordered_flat_set<key, hasher, key_equal>
non_transparent_set3;
#else
typedef boost::unordered_set<key, transparent_hasher, transparent_key_equal>
transparent_set;
@@ -239,6 +263,7 @@ void test_set()
typedef boost::unordered_set<key, hasher, transparent_key_equal>
non_transparent_set2;
typedef boost::unordered_set<key, hasher, key_equal> non_transparent_set3;
#endif
test_set_transparent_contains<transparent_set>();
test_set_non_transparent_contains<non_transparent_set1>();
@@ -246,6 +271,7 @@ void test_set()
test_set_non_transparent_contains<non_transparent_set3>();
}
#ifndef BOOST_UNORDERED_FOA_TESTS
void test_multiset()
{
typedef boost::unordered_multiset<key, transparent_hasher,
@@ -264,11 +290,15 @@ void test_multiset()
test_set_non_transparent_contains<non_transparent_multiset2>();
test_set_non_transparent_contains<non_transparent_multiset3>();
}
#endif
UNORDERED_AUTO_TEST (contains_) { // avoid -Wshadow warning with `bool contains`
test_map();
test_multimap();
test_set();
#ifndef BOOST_UNORDERED_FOA_TESTS
test_multimap();
test_multiset();
#endif
}
RUN_TESTS()

View File

@@ -1,14 +1,10 @@
// Copyright 2006-2009 Daniel James.
// Copyright (C) 2022 Christian Mazakas
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// clang-format off
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
// clang-format on
#include "../helpers/unordered.hpp"
#include "../helpers/test.hpp"
#include "../objects/test.hpp"
@@ -43,6 +39,23 @@ namespace copy_tests {
BOOST_TEST(x.max_load_factor() == y.max_load_factor());
BOOST_TEST(test::selected_count(y.get_allocator()) ==
(allocator_type::is_select_on_copy));
BOOST_TEST(test::detail::tracker.count_allocations == 0);
test::check_equivalent_keys(y);
}
{
test::check_instances check_;
T x(0);
T y(x);
BOOST_TEST(y.empty());
BOOST_TEST(test::equivalent(y.hash_function(), hf));
BOOST_TEST(test::equivalent(y.key_eq(), eq));
BOOST_TEST(test::equivalent(y.get_allocator(), al));
BOOST_TEST(x.max_load_factor() == y.max_load_factor());
BOOST_TEST(test::selected_count(y.get_allocator()) ==
(allocator_type::is_select_on_copy));
BOOST_TEST(test::detail::tracker.count_allocations == 0);
test::check_equivalent_keys(y);
}
@@ -91,6 +104,22 @@ namespace copy_tests {
typedef typename T::allocator_type allocator_type;
{
test::check_instances check_;
T x(0, hf, eq, al);
T y(x);
BOOST_TEST(y.empty());
BOOST_TEST(test::equivalent(y.hash_function(), hf));
BOOST_TEST(test::equivalent(y.key_eq(), eq));
BOOST_TEST(test::equivalent(y.get_allocator(), al));
BOOST_TEST(x.max_load_factor() == y.max_load_factor());
BOOST_TEST(test::selected_count(y.get_allocator()) ==
(allocator_type::is_select_on_copy));
BOOST_TEST(test::detail::tracker.count_allocations == 0);
test::check_equivalent_keys(y);
}
{
test::check_instances check_;
@@ -106,6 +135,21 @@ namespace copy_tests {
test::check_equivalent_keys(y);
}
{
test::check_instances check_;
T x(0, hf, eq, al);
T y(x, al2);
BOOST_TEST(y.empty());
BOOST_TEST(test::equivalent(y.hash_function(), hf));
BOOST_TEST(test::equivalent(y.key_eq(), eq));
BOOST_TEST(test::equivalent(y.get_allocator(), al2));
BOOST_TEST(x.max_load_factor() == y.max_load_factor());
BOOST_TEST(test::selected_count(y.get_allocator()) == 0);
BOOST_TEST(test::detail::tracker.count_allocations == 0);
test::check_equivalent_keys(y);
}
{
test::check_instances check_;
@@ -120,6 +164,22 @@ namespace copy_tests {
test::check_equivalent_keys(y);
}
{
test::check_instances check_;
test::random_values<T> v;
T x(v.begin(), v.end(), 0, hf, eq, al);
T y(x);
test::unordered_equivalence_tester<T> equivalent(x);
BOOST_TEST(equivalent(y));
test::check_equivalent_keys(y);
BOOST_TEST(test::selected_count(y.get_allocator()) ==
(allocator_type::is_select_on_copy));
BOOST_TEST(test::equivalent(y.get_allocator(), al));
BOOST_TEST(test::detail::tracker.count_allocations == 0);
}
{
test::check_instances check_;
@@ -135,6 +195,21 @@ namespace copy_tests {
BOOST_TEST(test::equivalent(y.get_allocator(), al));
}
{
test::check_instances check_;
test::random_values<T> v;
T x(v.begin(), v.end(), 0, hf, eq, al);
T y(x, al2);
test::unordered_equivalence_tester<T> equivalent(x);
BOOST_TEST(equivalent(y));
test::check_equivalent_keys(y);
BOOST_TEST(test::selected_count(y.get_allocator()) == 0);
BOOST_TEST(test::equivalent(y.get_allocator(), al2));
BOOST_TEST(test::detail::tracker.count_allocations == 0);
}
{
test::check_instances check_;
@@ -150,6 +225,38 @@ namespace copy_tests {
}
}
using test::default_generator;
using test::generate_collisions;
using test::limited_range;
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_set<test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_set;
boost::unordered_flat_map<test::object, test::object, test::hash,
test::equal_to, test::allocator1<test::object> >* test_map;
boost::unordered_flat_set<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::select_copy> >*
test_set_select_copy;
boost::unordered_flat_map<test::object, test::object, test::hash,
test::equal_to, test::cxx11_allocator<test::object, test::select_copy> >*
test_map_select_copy;
boost::unordered_flat_set<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_select_copy> >*
test_set_no_select_copy;
boost::unordered_flat_map<test::object, test::object, test::hash,
test::equal_to, test::cxx11_allocator<test::object, test::no_select_copy> >*
test_map_no_select_copy;
UNORDERED_TEST(copy_construct_tests1,
((test_set)(test_map)(test_set_select_copy)(test_map_select_copy)(test_set_no_select_copy)(test_map_no_select_copy))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(copy_construct_tests2,
((test_set)(test_map)(test_set_select_copy)(test_map_select_copy)(test_set_no_select_copy)(test_map_no_select_copy))(
(default_generator)(generate_collisions)(limited_range)))
#else
boost::unordered_set<test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_set;
boost::unordered_multiset<test::object, test::hash, test::equal_to,
@@ -185,25 +292,14 @@ namespace copy_tests {
test::equal_to, test::cxx11_allocator<test::object, test::no_select_copy> >*
test_multimap_no_select_copy;
using test::default_generator;
using test::generate_collisions;
using test::limited_range;
UNORDERED_TEST(copy_construct_tests1,
((test_set)(test_multiset)(test_map)(test_multimap)(test_set_select_copy)(
test_multiset_select_copy)(test_map_select_copy)(
test_multimap_select_copy)(test_set_no_select_copy)(
test_multiset_no_select_copy)(test_map_no_select_copy)(
test_multimap_no_select_copy))(
((test_set)(test_multiset)(test_map)(test_multimap)(test_set_select_copy)(test_multiset_select_copy)(test_map_select_copy)(test_multimap_select_copy)(test_set_no_select_copy)(test_multiset_no_select_copy)(test_map_no_select_copy)(test_multimap_no_select_copy))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(copy_construct_tests2,
((test_set)(test_multiset)(test_map)(test_multimap)(test_set_select_copy)(
test_multiset_select_copy)(test_map_select_copy)(
test_multimap_select_copy)(test_set_no_select_copy)(
test_multiset_no_select_copy)(test_map_no_select_copy)(
test_multimap_no_select_copy))(
((test_set)(test_multiset)(test_map)(test_multimap)(test_set_select_copy)(test_multiset_select_copy)(test_map_select_copy)(test_multimap_select_copy)(test_set_no_select_copy)(test_multiset_no_select_copy)(test_map_no_select_copy)(test_multimap_no_select_copy))(
(default_generator)(generate_collisions)(limited_range)))
}
#endif
} // namespace copy_tests
RUN_TESTS()

View File

@@ -1,14 +1,10 @@
//
// Copyright 2016 Daniel James.
// Copyright 2022 Christian Mazakas.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// clang-format off
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
// clang-format on
#include "../helpers/unordered.hpp"
#include <boost/functional/hash/hash.hpp>
#include "../helpers/test.hpp"
@@ -46,47 +42,56 @@ namespace emplace_tests {
A8 a8;
A9 a9;
emplace_value(A0 const& b0, A1 const& b1) : arg_count(2), a0(b0), a1(b1) {}
emplace_value(A0 const& b0, A1 const& b1)
: arg_count(2), a0(b0), a1(b1), a2('\0'), a3(-1), a4(-1), a5(-1),
a6(-1), a7(-1), a8(-1), a9(-1)
{
}
emplace_value(A0 const& b0, A1 const& b1, A2 const& b2)
: arg_count(3), a0(b0), a1(b1), a2(b2)
: arg_count(3), a0(b0), a1(b1), a2(b2), a3(-1), a4(-1), a5(-1), a6(-1),
a7(-1), a8(-1), a9(-1)
{
}
emplace_value(A0 const& b0, A1 const& b1, A2 const& b2, A3 const& b3)
: arg_count(4), a0(b0), a1(b1), a2(b2), a3(b3)
: arg_count(4), a0(b0), a1(b1), a2(b2), a3(b3), a4(-1), a5(-1), a6(-1),
a7(-1), a8(-1), a9(-1)
{
}
emplace_value(
A0 const& b0, A1 const& b1, A2 const& b2, A3 const& b3, A4 const& b4)
: arg_count(5), a0(b0), a1(b1), a2(b2), a3(b3), a4(b4)
: arg_count(5), a0(b0), a1(b1), a2(b2), a3(b3), a4(b4), a5(-1), a6(-1),
a7(-1), a8(-1), a9(-1)
{
}
emplace_value(A0 const& b0, A1 const& b1, A2 const& b2, A3 const& b3,
A4 const& b4, A5 const& b5)
: arg_count(6), a0(b0), a1(b1), a2(b2), a3(b3), a4(b4), a5(b5)
: arg_count(6), a0(b0), a1(b1), a2(b2), a3(b3), a4(b4), a5(b5), a6(-1),
a7(-1), a8(-1), a9(-1)
{
}
emplace_value(A0 const& b0, A1 const& b1, A2 const& b2, A3 const& b3,
A4 const& b4, A5 const& b5, A6 const& b6)
: arg_count(7), a0(b0), a1(b1), a2(b2), a3(b3), a4(b4), a5(b5), a6(b6)
: arg_count(7), a0(b0), a1(b1), a2(b2), a3(b3), a4(b4), a5(b5), a6(b6),
a7(-1), a8(-1), a9(-1)
{
}
emplace_value(A0 const& b0, A1 const& b1, A2 const& b2, A3 const& b3,
A4 const& b4, A5 const& b5, A6 const& b6, A7 const& b7)
: arg_count(8), a0(b0), a1(b1), a2(b2), a3(b3), a4(b4), a5(b5), a6(b6),
a7(b7)
a7(b7), a8(-1), a9(-1)
{
}
emplace_value(A0 const& b0, A1 const& b1, A2 const& b2, A3 const& b3,
A4 const& b4, A5 const& b5, A6 const& b6, A7 const& b7, A8 const& b8)
: arg_count(9), a0(b0), a1(b1), a2(b2), a3(b3), a4(b4), a5(b5), a6(b6),
a7(b7), a8(b8)
a7(b7), a8(b8), a9(-1)
{
}
@@ -162,16 +167,29 @@ namespace emplace_tests {
return true;
}
#ifdef BOOST_UNORDERED_FOA_TESTS
emplace_value() = delete;
emplace_value(emplace_value const&) = default;
emplace_value(emplace_value&&) = default;
#else
private:
emplace_value();
emplace_value(emplace_value const&);
#endif
};
UNORDERED_AUTO_TEST (emplace_set) {
test::check_instances check_;
#ifdef BOOST_UNORDERED_FOA_TESTS
typedef boost::unordered_flat_set<emplace_value,
boost::hash<emplace_value> >
container;
#else
typedef boost::unordered_set<emplace_value, boost::hash<emplace_value> >
container;
#endif
typedef container::iterator iterator;
typedef std::pair<iterator, bool> return_type;
container x(10);
@@ -187,7 +205,15 @@ namespace emplace_tests {
BOOST_TEST(*r1.first == v1);
BOOST_TEST(r1.first == x.find(v1));
BOOST_TEST_EQ(check_.instances(), 2);
#ifdef BOOST_UNORDERED_FOA_TESTS
// 1 from v1
// 1 from constructing the value_type() so we can pluck the key
// 1 from move-constructing which invokes the counted_object base
// constructor
BOOST_TEST_EQ(check_.constructions(), 3);
#else
BOOST_TEST_EQ(check_.constructions(), 2);
#endif
// 3 args
@@ -198,7 +224,11 @@ namespace emplace_tests {
BOOST_TEST(*r1.first == v2);
BOOST_TEST(r1.first == x.find(v2));
BOOST_TEST_EQ(check_.instances(), 4);
#ifdef BOOST_UNORDERED_FOA_TESTS
BOOST_TEST_EQ(check_.constructions(), 6);
#else
BOOST_TEST_EQ(check_.constructions(), 4);
#endif
// 7 args with hint + duplicate
@@ -208,7 +238,11 @@ namespace emplace_tests {
BOOST_TEST(*i1 == v3);
BOOST_TEST(i1 == x.find(v3));
BOOST_TEST_EQ(check_.instances(), 6);
#ifdef BOOST_UNORDERED_FOA_TESTS
BOOST_TEST_EQ(check_.constructions(), 9);
#else
BOOST_TEST_EQ(check_.constructions(), 6);
#endif
r2 = x.emplace(25, "something", 'z', 4, 5, 6, 7);
BOOST_TEST_EQ(x.size(), 3u);
@@ -218,7 +252,11 @@ namespace emplace_tests {
// whether it can emplace, so there's an extra construction
// here.
BOOST_TEST_EQ(check_.instances(), 6);
#ifdef BOOST_UNORDERED_FOA_TESTS
BOOST_TEST_EQ(check_.constructions(), 10);
#else
BOOST_TEST_EQ(check_.constructions(), 7);
#endif
// 10 args + hint duplicate
@@ -230,7 +268,11 @@ namespace emplace_tests {
BOOST_TEST(*r1.first == v4);
BOOST_TEST(r1.first == x.find(v4));
BOOST_TEST_EQ(check_.instances(), 8);
#ifdef BOOST_UNORDERED_FOA_TESTS
BOOST_TEST_EQ(check_.constructions(), 13);
#else
BOOST_TEST_EQ(check_.constructions(), 9);
#endif
BOOST_TEST(
r1.first == x.emplace_hint(r1.first, 10, "", 'a', 4, 5, 6, 7, 8, 9, 10));
@@ -239,7 +281,11 @@ namespace emplace_tests {
BOOST_TEST(
r1.first == x.emplace_hint(x.end(), 10, "", 'a', 4, 5, 6, 7, 8, 9, 10));
BOOST_TEST_EQ(check_.instances(), 8);
#ifdef BOOST_UNORDERED_FOA_TESTS
BOOST_TEST_EQ(check_.constructions(), 16);
#else
BOOST_TEST_EQ(check_.constructions(), 12);
#endif
BOOST_TEST_EQ(x.size(), 4u);
BOOST_TEST(x.count(v1) == 1);
@@ -248,6 +294,7 @@ namespace emplace_tests {
BOOST_TEST(x.count(v4) == 1);
}
#ifndef BOOST_UNORDERED_FOA_TESTS
UNORDERED_AUTO_TEST (emplace_multiset) {
test::check_instances check_;
@@ -325,20 +372,79 @@ namespace emplace_tests {
BOOST_TEST_EQ(x.count(v2), 2u);
BOOST_TEST_EQ(x.count(v3), 2u);
}
#endif
UNORDERED_AUTO_TEST (emplace_map) {
test::check_instances check_;
#ifdef BOOST_UNORDERED_FOA_TESTS
typedef boost::unordered_flat_map<emplace_value, emplace_value,
boost::hash<emplace_value> >
container;
#else
typedef boost::unordered_map<emplace_value, emplace_value,
boost::hash<emplace_value> >
container;
#endif
typedef container::iterator iterator;
typedef std::pair<iterator, bool> return_type;
container x(10);
return_type r1, r2;
#ifdef BOOST_UNORDERED_FOA_TESTS
// 5/8 args + duplicate
emplace_value k1(5, "", 'b', 4, 5);
emplace_value m1(8, "xxx", 'z', 4, 5, 6, 7, 8);
r1 = x.emplace(std::piecewise_construct, std::make_tuple(5, "", 'b', 4, 5),
std::make_tuple(8, "xxx", 'z', 4, 5, 6, 7, 8));
BOOST_TEST_EQ(x.size(), 1u);
BOOST_TEST(r1.second);
BOOST_TEST(x.find(k1) == r1.first);
BOOST_TEST(x.find(k1)->second == m1);
BOOST_TEST_EQ(check_.instances(), 4);
BOOST_TEST_EQ(check_.constructions(), 6);
r2 = x.emplace(std::piecewise_construct, std::make_tuple(5, "", 'b', 4, 5),
std::make_tuple(8, "xxx", 'z', 4, 5, 6, 7, 8));
BOOST_TEST_EQ(x.size(), 1u);
BOOST_TEST(!r2.second);
BOOST_TEST(r1.first == r2.first);
BOOST_TEST(x.find(k1)->second == m1);
BOOST_TEST_EQ(check_.instances(), 4);
// constructions could possibly be 5 if the implementation only
// constructed the key.
BOOST_TEST_EQ(check_.constructions(), 8);
// 9/3 args + duplicates with hints, different mapped value.
emplace_value k2(9, "", 'b', 4, 5, 6, 7, 8, 9);
emplace_value m2(3, "aaa", 'm');
r1 = x.emplace(std::piecewise_construct,
std::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9),
std::make_tuple(3, "aaa", 'm'));
BOOST_TEST_EQ(x.size(), 2u);
BOOST_TEST(r1.second);
BOOST_TEST(r1.first->first.arg_count == 9);
BOOST_TEST(r1.first->second.arg_count == 3);
BOOST_TEST(x.find(k2) == r1.first);
BOOST_TEST(x.find(k2)->second == m2);
BOOST_TEST_EQ(check_.instances(), 8);
BOOST_TEST_EQ(check_.constructions(), 14);
BOOST_TEST(r1.first == x.emplace_hint(r1.first, std::piecewise_construct,
std::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9),
std::make_tuple(15, "jkjk")));
BOOST_TEST(r1.first == x.emplace_hint(r2.first, std::piecewise_construct,
std::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9),
std::make_tuple(275, "xxx", 'm', 6)));
BOOST_TEST(r1.first == x.emplace_hint(x.end(), std::piecewise_construct,
std::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9),
std::make_tuple(-10, "blah blah", '\0')));
BOOST_TEST_EQ(x.size(), 2u);
BOOST_TEST(x.find(k2)->second == m2);
BOOST_TEST_EQ(check_.instances(), 8);
BOOST_TEST_EQ(check_.constructions(), 20);
#else
// 5/8 args + duplicate
emplace_value k1(5, "", 'b', 4, 5);
emplace_value m1(8, "xxx", 'z', 4, 5, 6, 7, 8);
r1 = x.emplace(boost::unordered::piecewise_construct,
@@ -395,8 +501,10 @@ namespace emplace_tests {
BOOST_TEST(x.find(k2)->second == m2);
BOOST_TEST_EQ(check_.instances(), 8);
BOOST_TEST_EQ(check_.constructions(), 16);
#endif
}
#ifndef BOOST_UNORDERED_FOA_TESTS
UNORDERED_AUTO_TEST (emplace_multimap) {
test::check_instances check_;
@@ -461,11 +569,15 @@ namespace emplace_tests {
BOOST_TEST_EQ(check_.instances(), 20);
BOOST_TEST_EQ(check_.constructions(), 20);
}
#endif
UNORDERED_AUTO_TEST (try_emplace) {
test::check_instances check_;
#ifdef BOOST_UNORDERED_FOA_TESTS
typedef boost::unordered_flat_map<int, emplace_value> container;
#else
typedef boost::unordered_map<int, emplace_value> container;
#endif
typedef container::iterator iterator;
typedef std::pair<iterator, bool> return_type;
container x(10);

View File

@@ -1,14 +1,10 @@
// Copyright 2008-2009 Daniel James.
// Copyright 2022 Christian Mazakas.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// clang-format off
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
// clang-format on
#include "../helpers/unordered.hpp"
#include <boost/preprocessor/seq.hpp>
#include <list>
@@ -30,14 +26,27 @@ namespace equality_tests {
}
};
#define UNORDERED_EQUALITY_SET_TEST(seq1, op, seq2) \
#ifdef BOOST_UNORDERED_FOA_TESTS
using boost_unordered_set =
boost::unordered_flat_set<int, mod_compare, mod_compare>;
using boost_unordered_map =
boost::unordered_flat_map<int, int, mod_compare, mod_compare>;
#define UNORDERED_EQUALITY_MULTISET_TEST(seq1, op, seq2) \
{ \
boost::unordered_set<int, mod_compare, mod_compare> set1, set2; \
BOOST_PP_SEQ_FOR_EACH(UNORDERED_SET_INSERT, set1, seq1) \
BOOST_PP_SEQ_FOR_EACH(UNORDERED_SET_INSERT, set2, seq2) \
BOOST_TEST(set1 op set2); \
}
#define UNORDERED_EQUALITY_MULTIMAP_TEST(seq1, op, seq2) \
{ \
}
#else
typedef boost::unordered_set<int, mod_compare, mod_compare>
boost_unordered_set;
typedef boost::unordered_map<int, int, mod_compare, mod_compare>
boost_unordered_map;
#define UNORDERED_EQUALITY_MULTISET_TEST(seq1, op, seq2) \
{ \
boost::unordered_multiset<int, mod_compare, mod_compare> set1, set2; \
@@ -46,17 +55,26 @@ namespace equality_tests {
BOOST_TEST(set1 op set2); \
}
#define UNORDERED_EQUALITY_MAP_TEST(seq1, op, seq2) \
#define UNORDERED_EQUALITY_MULTIMAP_TEST(seq1, op, seq2) \
{ \
boost::unordered_map<int, int, mod_compare, mod_compare> map1, map2; \
boost::unordered_multimap<int, int, mod_compare, mod_compare> map1, map2; \
BOOST_PP_SEQ_FOR_EACH(UNORDERED_MAP_INSERT, map1, seq1) \
BOOST_PP_SEQ_FOR_EACH(UNORDERED_MAP_INSERT, map2, seq2) \
BOOST_TEST(map1 op map2); \
}
#endif
#define UNORDERED_EQUALITY_MULTIMAP_TEST(seq1, op, seq2) \
#define UNORDERED_EQUALITY_SET_TEST(seq1, op, seq2) \
{ \
boost::unordered_multimap<int, int, mod_compare, mod_compare> map1, map2; \
boost_unordered_set set1, set2; \
BOOST_PP_SEQ_FOR_EACH(UNORDERED_SET_INSERT, set1, seq1) \
BOOST_PP_SEQ_FOR_EACH(UNORDERED_SET_INSERT, set2, seq2) \
BOOST_TEST(set1 op set2); \
}
#define UNORDERED_EQUALITY_MAP_TEST(seq1, op, seq2) \
{ \
boost_unordered_map map1, map2; \
BOOST_PP_SEQ_FOR_EACH(UNORDERED_MAP_INSERT, map1, seq1) \
BOOST_PP_SEQ_FOR_EACH(UNORDERED_MAP_INSERT, map2, seq2) \
BOOST_TEST(map1 op map2); \
@@ -67,7 +85,11 @@ namespace equality_tests {
map.insert(std::pair<int const, int> BOOST_PP_SEQ_TO_TUPLE(item));
UNORDERED_AUTO_TEST (equality_size_tests) {
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_set<int> x1, x2;
#else
boost::unordered_set<int> x1, x2;
#endif
BOOST_TEST(x1 == x2);
BOOST_TEST(!(x1 != x2));
@@ -134,7 +156,7 @@ namespace equality_tests {
// different hash functions but the same equality predicate.
UNORDERED_AUTO_TEST (equality_different_hash_test) {
typedef boost::unordered_set<int, mod_compare, mod_compare> set;
typedef boost_unordered_set set;
set set1(0, mod_compare(false), mod_compare(false));
set set2(0, mod_compare(true), mod_compare(true));
BOOST_TEST(set1 == set2);

View File

@@ -1,14 +1,10 @@
// Copyright 2006-2009 Daniel James.
// Copyright 2022 Christian Mazakas.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// clang-format off
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
// clang-format on
#include "../helpers/unordered.hpp"
#include "../helpers/test.hpp"
#include <algorithm>
@@ -38,8 +34,11 @@ void test_equal_insertion(Iterator begin, Iterator end)
UNORDERED_AUTO_TEST (set_tests) {
int values[][5] = {{1}, {54, 23}, {-13, 65}, {77, 77}, {986, 25, 986}};
#ifdef BOOST_UNORDERED_FOA_TESTS
typedef boost::unordered_flat_set<int> set;
#else
typedef boost::unordered_set<int> set;
typedef boost::unordered_multiset<int> multiset;
#endif
test_equal_insertion<set>(values[0], values[0] + 1);
test_equal_insertion<set>(values[1], values[1] + 2);
@@ -47,6 +46,7 @@ UNORDERED_AUTO_TEST (set_tests) {
test_equal_insertion<set>(values[3], values[3] + 2);
test_equal_insertion<set>(values[4], values[4] + 3);
typedef boost::unordered_multiset<int> multiset;
test_equal_insertion<multiset>(values[0], values[0] + 1);
test_equal_insertion<multiset>(values[1], values[1] + 2);
test_equal_insertion<multiset>(values[2], values[2] + 2);
@@ -66,12 +66,17 @@ UNORDERED_AUTO_TEST (map_tests) {
v[2].push_back(std::pair<int const, int>(432, 24));
for (int i = 0; i < 5; ++i)
#ifdef BOOST_UNORDERED_FOA_TESTS
test_equal_insertion<boost::unordered_flat_map<int, int> >(
v[i].begin(), v[i].end());
#else
test_equal_insertion<boost::unordered_map<int, int> >(
v[i].begin(), v[i].end());
for (int i2 = 0; i2 < 5; ++i2)
test_equal_insertion<boost::unordered_multimap<int, int> >(
v[i2].begin(), v[i2].end());
#endif
}
RUN_TESTS()

View File

@@ -2,12 +2,7 @@
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// clang-format off
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
// clang-format on
#include "../helpers/unordered.hpp"
#include "../helpers/test.hpp"
@@ -23,36 +18,13 @@
namespace test {
struct is_even
{
is_even() {}
#if BOOST_CXX_VERSION >= 201703L
// immovable for C++17
is_even(is_even const&) = delete;
is_even(is_even&&) = delete;
is_even& operator=(is_even const&) = delete;
is_even& operator=(is_even&&) = delete;
#elif BOOST_CXX_VERSION >= 201103L
// move-only for C++11
is_even(is_even const&) = delete;
is_even(is_even&&) = default;
is_even& operator=(is_even const&) = delete;
is_even& operator=(is_even&&) = default;
#else
// copyable otherwise
is_even(is_even const&) {}
is_even& operator=(is_even const&) { return *this; }
#endif
bool operator()(
std::pair<std::string const, int>& key_value) UNORDERED_LVALUE_QUAL
bool operator()(std::pair<std::string const, int>& key_value)
{
int const v = key_value.second;
return (v % 2 == 0);
}
bool operator()(int const& value) UNORDERED_LVALUE_QUAL
bool operator()(int const& value)
{
int const v = value;
return (v % 2 == 0);
@@ -61,37 +33,13 @@ namespace test {
struct is_too_large
{
is_too_large() {}
#if BOOST_CXX_VERSION >= 201703L
// immovable for C++17
is_too_large(is_too_large const&) = delete;
is_too_large(is_too_large&&) = delete;
is_too_large& operator=(is_too_large const&) = delete;
is_too_large& operator=(is_too_large&&) = delete;
#elif BOOST_CXX_VERSION >= 201103L
// move-only for C++11
is_too_large(is_too_large const&) = delete;
is_too_large(is_too_large&&) = default;
is_too_large& operator=(is_too_large const&) = delete;
is_too_large& operator=(is_too_large&&) = default;
#else
// copyable otherwise
is_too_large(is_too_large const&) {}
is_too_large& operator=(is_too_large const&) { return *this; }
#endif
bool operator()(
std::pair<std::string const, int>& key_value) UNORDERED_LVALUE_QUAL
bool operator()(std::pair<std::string const, int>& key_value)
{
int const v = key_value.second;
return v >= 1000;
}
bool operator()(int const& value) UNORDERED_LVALUE_QUAL
bool operator()(int const& value)
{
int const v = value;
return v >= 1000;
@@ -159,11 +107,16 @@ template <class UnorderedSet> void test_set_erase_if()
}
UNORDERED_AUTO_TEST (unordered_erase_if) {
#ifdef BOOST_UNORDERED_FOA_TESTS
test_map_erase_if<boost::unordered_flat_map<std::string, int> >();
test_set_erase_if<boost::unordered_flat_set<int> >();
#else
test_map_erase_if<boost::unordered_map<std::string, int> >();
test_map_erase_if<boost::unordered_multimap<std::string, int> >();
test_set_erase_if<boost::unordered_set<int> >();
test_set_erase_if<boost::unordered_multiset<int> >();
#endif
}
RUN_TESTS()

View File

@@ -1,14 +1,10 @@
// Copyright 2006-2009 Daniel James.
// Copyright 2022 Christian Mazakas.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// clang-format off
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
// clang-format on
#include "../helpers/unordered.hpp"
#include "../helpers/test.hpp"
#include "../objects/test.hpp"
@@ -27,7 +23,9 @@ namespace erase_tests {
template <class Container>
void erase_tests1(Container*, test::random_generator generator)
{
#ifndef BOOST_UNORDERED_FOA_TESTS
typedef typename Container::iterator iterator;
#endif
typedef typename Container::const_iterator c_iterator;
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Erase by key.\n";
@@ -61,9 +59,13 @@ namespace erase_tests {
while (size > 0 && !x.empty()) {
typename Container::key_type key = test::get_key<Container>(*x.begin());
std::size_t count = x.count(key);
#ifdef BOOST_UNORDERED_FOA_TESTS
x.erase(x.begin());
#else
iterator pos = x.erase(x.begin());
--size;
BOOST_TEST(pos == x.begin());
#endif
--size;
BOOST_TEST(x.count(key) == count - 1);
BOOST_TEST(x.size() == size);
if (++iterations % 20 == 0)
@@ -93,10 +95,15 @@ namespace erase_tests {
typename Container::key_type key = test::get_key<Container>(*pos);
std::size_t count = x.count(key);
BOOST_TEST(count > 0);
#ifdef BOOST_UNORDERED_FOA_TESTS
x.erase(pos);
--size;
#else
BOOST_TEST(next == x.erase(pos));
--size;
if (size > 0)
BOOST_TEST(index == 0 ? next == x.begin() : next == test::next(prev));
#endif
BOOST_TEST(x.count(key) == count - 1);
if (x.count(key) != count - 1) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << count << " => " << x.count(key)
@@ -185,7 +192,11 @@ namespace erase_tests {
while (size > 0 && !x.empty()) {
typename Container::key_type key = test::get_key<Container>(*x.begin());
std::size_t count = x.count(key);
#ifdef BOOST_UNORDERED_FOA_TESTS
x.erase(x.begin());
#else
x.quick_erase(x.begin());
#endif
--size;
BOOST_TEST(x.count(key) == count - 1);
BOOST_TEST(x.size() == size);
@@ -216,7 +227,11 @@ namespace erase_tests {
typename Container::key_type key = test::get_key<Container>(*pos);
std::size_t count = x.count(key);
BOOST_TEST(count > 0);
#ifdef BOOST_UNORDERED_FOA_TESTS
x.erase(pos);
#else
x.quick_erase(pos);
#endif
--size;
if (size > 0)
BOOST_TEST(index == 0 ? next == x.begin() : next == test::next(prev));
@@ -246,6 +261,20 @@ namespace erase_tests {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "\n";
}
using test::default_generator;
using test::generate_collisions;
using test::limited_range;
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_set<test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_set;
boost::unordered_flat_map<test::object, test::object, test::hash,
test::equal_to, test::allocator1<test::object> >* test_map;
UNORDERED_TEST(
erase_tests1, ((test_set)(test_map))(
(default_generator)(generate_collisions)(limited_range)))
#else
boost::unordered_set<test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_set;
boost::unordered_multiset<test::object, test::hash, test::equal_to,
@@ -255,13 +284,11 @@ namespace erase_tests {
boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to, test::allocator2<test::object> >* test_multimap;
using test::default_generator;
using test::generate_collisions;
using test::limited_range;
UNORDERED_TEST(
erase_tests1, ((test_set)(test_multiset)(test_map)(test_multimap))(
(default_generator)(generate_collisions)(limited_range)))
#endif
}
RUN_TESTS()

View File

@@ -1,14 +1,10 @@
// Copyright 2006-2009 Daniel James.
// Copyright (C) 2022 Christian Mazakas
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// clang-format off
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
// clang-format on
#include "../helpers/unordered.hpp"
#include "../helpers/test.hpp"
#include "../objects/test.hpp"
@@ -133,6 +129,20 @@ namespace find_tests {
}
}
using test::default_generator;
using test::generate_collisions;
using test::limited_range;
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_set<test::object, test::hash, test::equal_to,
test::allocator2<test::object> >* test_set;
boost::unordered_flat_map<test::object, test::object, test::hash, test::equal_to,
test::allocator2<test::object> >* test_map;
UNORDERED_TEST(
find_tests1, ((test_set)(test_map))(
(default_generator)(generate_collisions)(limited_range)))
#else
boost::unordered_set<test::object, test::hash, test::equal_to,
test::allocator2<test::object> >* test_set;
boost::unordered_multiset<test::object, test::hash, test::equal_to,
@@ -142,16 +152,13 @@ namespace find_tests {
boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to, test::allocator1<test::object> >* test_multimap;
using test::default_generator;
using test::generate_collisions;
using test::limited_range;
UNORDERED_TEST(
find_tests1, ((test_set)(test_multiset)(test_map)(test_multimap))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(find_compatible_keys_test,
((test_set)(test_multiset)(test_map)(test_multimap))(
(default_generator)(generate_collisions)(limited_range)))
#endif
}
RUN_TESTS()

View File

@@ -1,14 +1,44 @@
// Copyright 2008-2009 Daniel James.
// Copyright 2022 Christian Mazakas.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// clang-format off
#include "../helpers/prefix.hpp"
#ifdef BOOST_UNORDERED_FOA_TESTS
#include <boost/unordered/unordered_flat_map_fwd.hpp>
#include <boost/unordered/detail/implementation.hpp>
#else
#include <boost/unordered/unordered_map_fwd.hpp>
#endif
#include "../helpers/postfix.hpp"
// clang-format on
#ifdef BOOST_UNORDERED_FOA_TESTS
template <typename T>
void call_swap(
boost::unordered_flat_map<T, T>& x, boost::unordered_flat_map<T, T>& y)
{
swap(x, y);
}
template <typename T>
bool call_equals(
boost::unordered_flat_map<T, T>& x, boost::unordered_flat_map<T, T>& y)
{
return x == y;
}
template <typename T>
bool call_not_equals(
boost::unordered_flat_map<T, T>& x, boost::unordered_flat_map<T, T>& y)
{
return x != y;
}
#include <boost/unordered/unordered_flat_map.hpp>
#else
template <typename T>
void call_swap(boost::unordered_map<T, T>& x, boost::unordered_map<T, T>& y)
{
@@ -50,10 +80,15 @@ bool call_not_equals(
}
#include <boost/unordered_map.hpp>
#endif
#include "../helpers/test.hpp"
#ifdef BOOST_UNORDERED_FOA_TESTS
typedef boost::unordered_flat_map<int, int> int_map;
#else
typedef boost::unordered_map<int, int> int_map;
typedef boost::unordered_multimap<int, int> int_multimap;
#endif
UNORDERED_AUTO_TEST (use_map_fwd_declared_function) {
int_map x, y;
@@ -71,11 +106,13 @@ UNORDERED_AUTO_TEST (use_map_fwd_declared_function) {
BOOST_TEST(call_not_equals(x, y));
}
#ifndef BOOST_UNORDERED_FOA_TESTS
UNORDERED_AUTO_TEST (use_multimap_fwd_declared_function) {
int_multimap x, y;
call_swap(x, y);
BOOST_TEST(call_equals(x, y));
BOOST_TEST(!call_not_equals(x, y));
}
#endif
RUN_TESTS()

View File

@@ -1,11 +1,17 @@
// Copyright 2008-2009 Daniel James.
// Copyright 2022 Christian Mazakas.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// clang-format off
#include "../helpers/prefix.hpp"
#ifdef BOOST_UNORDERED_FOA_TESTS
#include <boost/unordered/unordered_flat_set_fwd.hpp>
#include <boost/unordered/detail/implementation.hpp>
#else
#include <boost/unordered/unordered_set_fwd.hpp>
#endif
#include "../helpers/postfix.hpp"
// clang-format on
@@ -20,6 +26,31 @@ struct false_type
false_type is_unordered_set_impl(void*);
#ifdef BOOST_UNORDERED_FOA_TESTS
template <class Value, class Hash, class Pred, class Alloc>
true_type is_unordered_set_impl(
boost::unordered_flat_set<Value, Hash, Pred, Alloc>*);
template <typename T>
void call_swap(boost::unordered_flat_set<T>& x, boost::unordered_flat_set<T>& y)
{
swap(x, y);
}
template <typename T>
bool call_equals(
boost::unordered_flat_set<T>& x, boost::unordered_flat_set<T>& y)
{
return x == y;
}
template <typename T>
bool call_not_equals(
boost::unordered_flat_set<T>& x, boost::unordered_flat_set<T>& y)
{
return x != y;
}
#else
template <class Value, class Hash, class Pred, class Alloc>
true_type is_unordered_set_impl(
boost::unordered_set<Value, Hash, Pred, Alloc>*);
@@ -41,7 +72,9 @@ bool call_not_equals(boost::unordered_set<T>& x, boost::unordered_set<T>& y)
{
return x != y;
}
#endif
#ifndef BOOST_UNORDERED_FOA_TESTS
template <typename T>
void call_swap(boost::unordered_multiset<T>& x, boost::unordered_multiset<T>& y)
{
@@ -61,20 +94,29 @@ bool call_not_equals(
{
return x != y;
}
#endif
#include "../helpers/test.hpp"
#ifdef BOOST_UNORDERED_FOA_TESTS
typedef boost::unordered_flat_set<int> int_set;
#else
typedef boost::unordered_set<int> int_set;
typedef boost::unordered_multiset<int> int_multiset;
#endif
UNORDERED_AUTO_TEST (use_fwd_declared_trait_without_definition) {
BOOST_TEST(sizeof(is_unordered_set_impl((int_set*)0)) == sizeof(true_type));
}
#ifdef BOOST_UNORDERED_FOA_TESTS
#include <boost/unordered/unordered_flat_set.hpp>
#else
#include <boost/unordered_set.hpp>
#endif
UNORDERED_AUTO_TEST (use_fwd_declared_trait) {
boost::unordered_set<int> x;
int_set x;
BOOST_TEST(sizeof(is_unordered_set_impl(&x)) == sizeof(true_type));
BOOST_TEST(sizeof(is_unordered_set_impl((int*)0)) == sizeof(false_type));
@@ -96,11 +138,13 @@ UNORDERED_AUTO_TEST (use_set_fwd_declared_function) {
BOOST_TEST(call_not_equals(x, y));
}
#ifndef BOOST_UNORDERED_FOA_TESTS
UNORDERED_AUTO_TEST (use_multiset_fwd_declared_function) {
int_multiset x, y;
call_swap(x, y);
BOOST_TEST(call_equals(x, y));
BOOST_TEST(!call_not_equals(x, y));
}
#endif
RUN_TESTS()

View File

@@ -1,21 +1,21 @@
// Copyright 2009 Daniel James.
// Copyright 2022 Christian Mazakas.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// clang-format off
#include "../helpers/prefix.hpp"
#include <boost/unordered_map.hpp>
#include <boost/unordered_set.hpp>
#include "../helpers/postfix.hpp"
// clang-format on
#include "../helpers/unordered.hpp"
#include <utility>
namespace x {
struct D
{
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_map<D, D> x;
#else
boost::unordered_map<D, D> x;
#endif
};
}
@@ -29,6 +29,17 @@ namespace incomplete_test {
// Declare some instances
#ifdef BOOST_UNORDERED_FOA_TESTS
typedef boost::unordered_flat_map<value, value, hash, equals,
allocator<std::pair<value const, value> > >
map;
typedef boost::unordered_flat_map<value, value, hash, equals,
allocator<std::pair<value const, value> > >
multimap;
typedef boost::unordered_flat_set<value, hash, equals, allocator<value> > set;
typedef boost::unordered_flat_set<value, hash, equals, allocator<value> >
multiset;
#else
typedef boost::unordered_map<value, value, hash, equals,
allocator<std::pair<value const, value> > >
map;
@@ -38,6 +49,7 @@ namespace incomplete_test {
typedef boost::unordered_set<value, hash, equals, allocator<value> > set;
typedef boost::unordered_multiset<value, hash, equals, allocator<value> >
multiset;
#endif
// Now define the types which are stored as members, as they are needed for
// declaring struct members.
@@ -76,7 +88,28 @@ namespace incomplete_test {
//
// Incomplete hash, equals and allocator aren't here supported at the
// moment.
#ifdef BOOST_UNORDERED_FOA_TESTS
struct struct1
{
boost::unordered_flat_map<struct1, struct1, hash, equals,
allocator<std::pair<struct1 const, struct1> > >
x;
};
struct struct2
{
boost::unordered_flat_map<struct2, struct2, hash, equals,
allocator<std::pair<struct2 const, struct2> > >
x;
};
struct struct3
{
boost::unordered_flat_set<struct3, hash, equals, allocator<struct3> > x;
};
struct struct4
{
boost::unordered_flat_set<struct4, hash, equals, allocator<struct4> > x;
};
#else
struct struct1
{
boost::unordered_map<struct1, struct1, hash, equals,
@@ -97,7 +130,7 @@ namespace incomplete_test {
{
boost::unordered_multiset<struct4, hash, equals, allocator<struct4> > x;
};
#endif
// Now define the value type.
struct value

View File

@@ -0,0 +1,244 @@
// Copyright 2022 Christian Mazakas.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or move at http://www.boost.org/LICENSE_1_0.txt)
#if !defined(BOOST_UNORDERED_FOA_TESTS)
#error "This test is only for the FOA-style conatiners"
#endif
#include "../helpers/unordered.hpp"
#include "../helpers/test.hpp"
struct move_only
{
int x_ = -1;
move_only() = default;
move_only(int x) : x_{x} {}
move_only(move_only const&) = delete;
move_only(move_only&&) = default;
friend bool operator==(move_only const& lhs, move_only const& rhs)
{
return lhs.x_ == rhs.x_;
}
};
namespace std{
template <> struct hash<move_only>
{
std::size_t operator()(move_only const& mo) const noexcept
{
return std::hash<int>()(mo.x_);
}
};
} // namespace std
struct raii_tracker
{
static unsigned move_constructs;
static unsigned copy_constructs;
int x_ = -1;
static void reset_counts()
{
move_constructs = 0;
copy_constructs = 0;
}
raii_tracker() {}
raii_tracker(int x) : x_{x} {}
raii_tracker(raii_tracker const& rhs) : x_{rhs.x_} { ++copy_constructs; }
raii_tracker(raii_tracker&& rhs) noexcept : x_{rhs.x_}
{
rhs.x_ = -1;
++move_constructs;
}
friend bool operator==(raii_tracker const& lhs, raii_tracker const& rhs)
{
return lhs.x_ == rhs.x_;
}
};
namespace std{
template <> struct hash<raii_tracker>
{
std::size_t operator()(raii_tracker const& rt) const noexcept
{
return std::hash<int>()(rt.x_);
}
};
} // namespace std
unsigned raii_tracker::move_constructs = 0;
unsigned raii_tracker::copy_constructs = 0;
static void test_move_only()
{
int const v = 128;
boost::unordered_flat_map<move_only, int, std::hash<move_only> > map;
using init_type = decltype(map)::init_type;
static_assert(
std::is_same<decltype(std::make_pair(move_only(1), v)), init_type>::value,
"");
map.insert(std::make_pair(move_only(1), v));
map.insert({move_only(2), v});
BOOST_TEST_EQ(map.size(), 2u);
map.rehash(1024);
BOOST_TEST_GE(map.bucket_count(), 1024u);
}
static void test_insert_tracking()
{
raii_tracker::reset_counts();
BOOST_TEST_EQ(raii_tracker::copy_constructs, 0u);
BOOST_TEST_EQ(raii_tracker::move_constructs, 0u);
boost::unordered_flat_map<raii_tracker, raii_tracker,
std::hash<raii_tracker> >
map;
{
std::pair<raii_tracker, raii_tracker> value{1, 2};
map.insert(value);
BOOST_TEST_EQ(raii_tracker::copy_constructs, 2u);
BOOST_TEST_EQ(raii_tracker::move_constructs, 0u);
}
{
std::pair<raii_tracker, raii_tracker> value{2, 3};
map.insert(std::move(value));
BOOST_TEST_EQ(raii_tracker::copy_constructs, 2u);
BOOST_TEST_EQ(raii_tracker::move_constructs, 2u);
}
{
std::pair<raii_tracker const, raii_tracker> value{3, 4};
map.insert(value);
BOOST_TEST_EQ(raii_tracker::copy_constructs, 4u);
BOOST_TEST_EQ(raii_tracker::move_constructs, 2u);
}
{
std::pair<raii_tracker const, raii_tracker> value{4, 5};
map.insert(std::move(value));
BOOST_TEST_EQ(raii_tracker::copy_constructs, 5u);
BOOST_TEST_EQ(raii_tracker::move_constructs, 3u);
}
{
map.insert(std::make_pair(5, 6));
BOOST_TEST_EQ(raii_tracker::copy_constructs, 5u);
BOOST_TEST_EQ(raii_tracker::move_constructs, 5u);
}
{
map.insert({6, 7});
BOOST_TEST_EQ(raii_tracker::copy_constructs, 5u);
BOOST_TEST_EQ(raii_tracker::move_constructs, 7u);
}
BOOST_TEST_EQ(map.size(), 6u);
map.rehash(1024);
BOOST_TEST_EQ(raii_tracker::copy_constructs, 5u);
BOOST_TEST_EQ(raii_tracker::move_constructs, 7u + 2u * map.size());
}
static void test_insert_hint_tracking()
{
raii_tracker::reset_counts();
BOOST_TEST_EQ(raii_tracker::copy_constructs, 0u);
BOOST_TEST_EQ(raii_tracker::move_constructs, 0u);
boost::unordered_flat_map<raii_tracker, raii_tracker,
std::hash<raii_tracker> >
map;
{
std::pair<raii_tracker, raii_tracker> value{1, 2};
map.insert(map.begin(), value);
BOOST_TEST_EQ(raii_tracker::copy_constructs, 2u);
BOOST_TEST_EQ(raii_tracker::move_constructs, 0u);
}
{
std::pair<raii_tracker, raii_tracker> value{2, 3};
map.insert(std::move(value));
BOOST_TEST_EQ(raii_tracker::copy_constructs, 2u);
BOOST_TEST_EQ(raii_tracker::move_constructs, 2u);
}
{
std::pair<raii_tracker const, raii_tracker> value{3, 4};
map.insert(map.begin(), value);
BOOST_TEST_EQ(raii_tracker::copy_constructs, 4u);
BOOST_TEST_EQ(raii_tracker::move_constructs, 2u);
}
{
std::pair<raii_tracker const, raii_tracker> value{4, 5};
map.insert(map.begin(), std::move(value));
BOOST_TEST_EQ(raii_tracker::copy_constructs, 5u);
BOOST_TEST_EQ(raii_tracker::move_constructs, 3u);
}
{
map.insert(map.begin(), std::make_pair(5, 6));
BOOST_TEST_EQ(raii_tracker::copy_constructs, 5u);
BOOST_TEST_EQ(raii_tracker::move_constructs, 5u);
}
{
map.insert(map.begin(), {6, 7});
BOOST_TEST_EQ(raii_tracker::copy_constructs, 5u);
BOOST_TEST_EQ(raii_tracker::move_constructs, 7u);
}
BOOST_TEST_EQ(map.size(), 6u);
map.rehash(1024);
BOOST_TEST_EQ(raii_tracker::copy_constructs, 5u);
BOOST_TEST_EQ(raii_tracker::move_constructs, 7u + 2u * map.size());
}
int main()
{
test_move_only();
test_insert_tracking();
test_insert_hint_tracking();
return boost::report_errors();
}

View File

@@ -1,14 +1,10 @@
// Copyright 2016 Daniel James.
// Copyright 2022 Christian Mazakas.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// clang-format off
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
// clang-format on
#include "../helpers/unordered.hpp"
#include "../helpers/test.hpp"
#include "../helpers/invariants.hpp"
@@ -17,6 +13,7 @@
#include <set>
namespace insert_hint {
#ifndef BOOST_UNORDERED_FOA_TESTS
UNORDERED_AUTO_TEST (insert_hint_empty) {
typedef boost::unordered_multiset<int> container;
container x;
@@ -90,9 +87,13 @@ namespace insert_hint {
}
}
}
#endif
UNORDERED_AUTO_TEST (insert_hint_unique) {
#ifdef BOOST_UNORDERED_FOA_TESTS
typedef boost::unordered_flat_set<int> container;
#else
typedef boost::unordered_set<int> container;
#endif
container x;
x.insert(x.cbegin(), 10);
BOOST_TEST_EQ(x.size(), 1u);
@@ -101,7 +102,11 @@ namespace insert_hint {
}
UNORDERED_AUTO_TEST (insert_hint_unique_single) {
#ifdef BOOST_UNORDERED_FOA_TESTS
typedef boost::unordered_flat_set<int> container;
#else
typedef boost::unordered_set<int> container;
#endif
container x;
x.insert(10);

View File

@@ -1,16 +1,12 @@
// Copyright 2006-2010 Daniel James.
// Copyright (C) 2022 Christian Mazakas
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#if !defined(PIECEWISE_TEST_NAME)
// clang-format off
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
// clang-format on
#include "../helpers/unordered.hpp"
#include "../helpers/test.hpp"
#include "../objects/test.hpp"
@@ -21,6 +17,8 @@
#include "../helpers/input_iterator.hpp"
#include "../helpers/helpers.hpp"
#include <vector>
namespace insert_tests {
test::seed_t initialize_seed(243432);
@@ -678,6 +676,23 @@ namespace insert_tests {
}
}
template <class X> void set_tests(X*, test::random_generator)
{
// prove that our insert(iterator, iterator) implementation honors
// Cpp17EmplaceConstructible
//
X x;
std::vector<int> v;
v.reserve(1000);
for (unsigned i = 0; i < 1000; ++i) {
v.push_back(static_cast<int>(i));
}
x.insert(v.begin(), v.end());
BOOST_TEST_EQ(x.size(), 1000u);
}
template <class X>
void try_emplace_tests(X*, test::random_generator generator)
{
@@ -870,6 +885,53 @@ namespace insert_tests {
test::check_equivalent_keys(x);
}
using test::default_generator;
using test::generate_collisions;
using test::limited_range;
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_set<test::movable, test::hash, test::equal_to,
std::allocator<test::movable> >* test_set_std_alloc;
boost::unordered_flat_set<test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_set;
boost::unordered_flat_map<test::movable, test::movable, test::hash,
test::equal_to, test::allocator2<test::movable> >* test_map;
UNORDERED_TEST(unique_insert_tests1,
((test_set_std_alloc)(test_set)(test_map))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(
insert_tests2, ((test_set)(test_map))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(unique_emplace_tests1,
((test_set_std_alloc)(test_set)(test_map))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(move_emplace_tests,
((test_set_std_alloc)(test_set)(test_map))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(default_emplace_tests,
((test_set_std_alloc)(test_set)(test_map))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(map_tests,
((test_map))((default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(
map_tests2, ((test_map))((default_generator)(generate_collisions)))
UNORDERED_TEST(map_insert_range_test1,
((test_map))((default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(map_insert_range_test2,
((test_map))((default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(
set_tests, ((test_set_std_alloc)(test_set))((default_generator)))
#else
boost::unordered_set<test::movable, test::hash, test::equal_to,
std::allocator<test::movable> >* test_set_std_alloc;
boost::unordered_multimap<test::object, test::object, test::hash,
@@ -884,10 +946,6 @@ namespace insert_tests {
boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to, test::allocator1<test::object> >* test_multimap;
using test::default_generator;
using test::generate_collisions;
using test::limited_range;
UNORDERED_TEST(unique_insert_tests1,
((test_set_std_alloc)(test_set)(test_map))(
(default_generator)(generate_collisions)(limited_range)))
@@ -897,8 +955,8 @@ namespace insert_tests {
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(insert_tests2,
((test_multimap_std_alloc)(test_set)(test_multiset)(test_map)(
test_multimap))((default_generator)(generate_collisions)(limited_range)))
((test_multimap_std_alloc)(test_set)(test_multiset)(test_map)(test_multimap))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(unique_emplace_tests1,
((test_set_std_alloc)(test_set)(test_map))(
@@ -909,13 +967,11 @@ namespace insert_tests {
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(move_emplace_tests,
((test_set_std_alloc)(test_multimap_std_alloc)(test_set)(test_map)(
test_multiset)(test_multimap))(
((test_set_std_alloc)(test_multimap_std_alloc)(test_set)(test_map)(test_multiset)(test_multimap))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(default_emplace_tests,
((test_set_std_alloc)(test_multimap_std_alloc)(test_set)(test_map)(
test_multiset)(test_multimap))(
((test_set_std_alloc)(test_multimap_std_alloc)(test_set)(test_map)(test_multiset)(test_multimap))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(map_tests,
@@ -932,6 +988,10 @@ namespace insert_tests {
((test_multimap_std_alloc)(test_map)(test_multimap))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(
set_tests, ((test_set_std_alloc)(test_set)(test_multiset))((default_generator)))
#endif
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
struct initialize_from_two_ints
@@ -950,13 +1010,21 @@ namespace insert_tests {
};
UNORDERED_AUTO_TEST (insert_initializer_list_set) {
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_set<int> set;
#else
boost::unordered_set<int> set;
#endif
set.insert({1, 2, 3, 1});
BOOST_TEST_EQ(set.size(), 3u);
BOOST_TEST(set.find(1) != set.end());
BOOST_TEST(set.find(4) == set.end());
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_set<initialize_from_two_ints> set2;
#else
boost::unordered_set<initialize_from_two_ints> set2;
#endif
#if defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 5))
set2.insert({{1, 2}});
@@ -985,6 +1053,7 @@ namespace insert_tests {
BOOST_TEST(set2.find({8, 7}) == set2.end());
}
#ifndef BOOST_UNORDERED_FOA_TESTS
#if !BOOST_WORKAROUND(BOOST_MSVC, == 1800)
UNORDERED_AUTO_TEST (insert_initializer_list_multiset) {
@@ -1002,16 +1071,22 @@ namespace insert_tests {
BOOST_TEST_EQ(multiset.count("c"), 0u);
}
#endif
#endif
UNORDERED_AUTO_TEST (insert_initializer_list_map) {
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_map<std::string, std::string> map;
#else
boost::unordered_map<std::string, std::string> map;
#endif
// map.insert({});
BOOST_TEST(map.empty());
map.insert({{"a", "b"}, {"a", "b"}, {"d", ""}});
BOOST_TEST_EQ(map.size(), 2u);
}
#ifndef BOOST_UNORDERED_FOA_TESTS
UNORDERED_AUTO_TEST (insert_initializer_list_multimap) {
boost::unordered_multimap<std::string, std::string> multimap;
// multimap.insert({});
@@ -1020,6 +1095,7 @@ namespace insert_tests {
BOOST_TEST_EQ(multimap.size(), 3u);
BOOST_TEST_EQ(multimap.count("a"), 2u);
}
#endif
#endif
@@ -1050,10 +1126,18 @@ namespace insert_tests {
UNORDERED_AUTO_TEST (map_emplace_test) {
{
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_map<int, overloaded_constructor, test::hash,
test::equal_to,
test::allocator1<std::pair<int const, overloaded_constructor> > >
x;
#else
boost::unordered_map<int, overloaded_constructor, test::hash,
test::equal_to,
test::allocator1<std::pair<int const, overloaded_constructor> > >
x;
#endif
#if !BOOST_UNORDERED_SUN_WORKAROUNDS1
x.emplace();
@@ -1070,6 +1154,7 @@ namespace insert_tests {
x.find(5) != x.end() && x.find(5)->second == overloaded_constructor());
}
#ifndef BOOST_UNORDERED_FOA_TESTS
{
boost::unordered_multimap<int, overloaded_constructor, test::hash,
test::equal_to,
@@ -1086,11 +1171,17 @@ namespace insert_tests {
BOOST_TEST(
x.find(2) != x.end() && x.find(2)->second == overloaded_constructor(3));
}
#endif
}
UNORDERED_AUTO_TEST (set_emplace_test) {
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_set<overloaded_constructor> x;
overloaded_constructor check;
#else
boost::unordered_set<overloaded_constructor> x;
overloaded_constructor check;
#endif
#if !BOOST_UNORDERED_SUN_WORKAROUNDS1
x.emplace();
@@ -1136,6 +1227,7 @@ namespace insert_tests {
}
};
#ifndef BOOST_UNORDERED_FOA_TESTS
UNORDERED_AUTO_TEST (map_emplace_test2) {
// Emulating piecewise construction with boost::tuple bypasses the
// allocator's construct method, but still uses test destroy method.
@@ -1259,10 +1351,13 @@ namespace insert_tests {
std::make_pair(overloaded_constructor(1), overloaded_constructor(2, 3));
BOOST_TEST(x.find(check) != x.end() && *x.find(check) == check);
}
#endif
// Use the preprocessor to generate tests using different combinations of
// boost/std piecewise_construct_t/tuple.
#ifndef BOOST_UNORDERED_FOA_TESTS
#define PIECEWISE_TEST_NAME boost_tuple_piecewise_tests
#define PIECEWISE_NAMESPACE boost::unordered
#define TUPLE_NAMESPACE boost
@@ -1289,6 +1384,8 @@ namespace insert_tests {
#endif
#endif
#if !defined(BOOST_NO_CXX11_HDR_TUPLE) && \
BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT
@@ -1311,12 +1408,21 @@ UNORDERED_AUTO_TEST (PIECEWISE_TEST_NAME) {
#endif
{
#if defined(BOOST_UNORDERED_FOA_TESTS)
boost::unordered_flat_map<overloaded_constructor, overloaded_constructor,
boost::hash<overloaded_constructor>,
std::equal_to<overloaded_constructor>,
test::allocator1<
std::pair<overloaded_constructor const, overloaded_constructor> > >
x;
#else
boost::unordered_map<overloaded_constructor, overloaded_constructor,
boost::hash<overloaded_constructor>,
std::equal_to<overloaded_constructor>,
test::allocator1<
std::pair<overloaded_constructor const, overloaded_constructor> > >
x;
#endif
x.emplace(PIECEWISE_NAMESPACE::piecewise_construct,
TUPLE_NAMESPACE::make_tuple(), TUPLE_NAMESPACE::make_tuple());
@@ -1360,6 +1466,7 @@ UNORDERED_AUTO_TEST (PIECEWISE_TEST_NAME) {
x.find(overloaded_constructor(2, 3))->second ==
overloaded_constructor(4, 5, 6));
}
#ifndef BOOST_UNORDERED_FOA_TESTS
{
boost::unordered_multimap<overloaded_constructor, overloaded_constructor,
boost::hash<overloaded_constructor>,
@@ -1393,6 +1500,7 @@ UNORDERED_AUTO_TEST (PIECEWISE_TEST_NAME) {
x.find(overloaded_constructor(9, 3, 1))->second ==
overloaded_constructor(10));
}
#endif
}
UNORDERED_AUTO_TEST (BOOST_PP_CAT(PIECEWISE_TEST_NAME, 2)) {
@@ -1400,9 +1508,15 @@ UNORDERED_AUTO_TEST (BOOST_PP_CAT(PIECEWISE_TEST_NAME, 2)) {
test::detail::disable_construction_tracking _scoped;
#endif
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_set<
std::pair<overloaded_constructor, overloaded_constructor> >
x;
#else
boost::unordered_set<
std::pair<overloaded_constructor, overloaded_constructor> >
x;
#endif
std::pair<overloaded_constructor, overloaded_constructor> check;
x.emplace(PIECEWISE_NAMESPACE::piecewise_construct,

View File

@@ -1,15 +1,24 @@
// Copyright 2006-2009 Daniel James.
// Copyright 2022 Christian Mazakas.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// clang-format off
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
// clang-format on
#include "../helpers/unordered.hpp"
#ifdef BOOST_UNORDERED_FOA_TESTS
void foo(boost::unordered_flat_set<int>&, boost::unordered_flat_map<int, int>&);
int main()
{
boost::unordered_flat_set<int> x1;
boost::unordered_flat_map<int, int> x2;
foo(x1, x2);
return 0;
}
#else
void foo(boost::unordered_set<int>&, boost::unordered_map<int, int>&,
boost::unordered_multiset<int>&, boost::unordered_multimap<int, int>&);
@@ -24,3 +33,4 @@ int main()
return 0;
}
#endif

View File

@@ -1,15 +1,27 @@
// Copyright 2006-2009 Daniel James.
// Copyright 2022 Christian Mazakas.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// clang-format off
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
// clang-format on
#include "../helpers/unordered.hpp"
#ifdef BOOST_UNORDERED_FOA_TESTS
void foo(
boost::unordered_flat_set<int>& x1, boost::unordered_flat_map<int, int>& x2)
{
#if BOOST_WORKAROUND(BOOST_CODEGEARC, BOOST_TESTED_AT(0x0613))
struct dummy
{
boost::unordered_flat_set<int> x1;
boost::unordered_flat_map<int, int> x2;
};
#endif
x1.insert(1);
x2[2] = 2;
}
#else
void foo(boost::unordered_set<int>& x1, boost::unordered_map<int, int>& x2,
boost::unordered_multiset<int>& x3, boost::unordered_multimap<int, int>& x4)
{
@@ -28,3 +40,4 @@ void foo(boost::unordered_set<int>& x1, boost::unordered_map<int, int>& x2,
x3.insert(3);
x4.insert(std::make_pair(4, 5));
}
#endif

View File

@@ -1,14 +1,10 @@
// Copyright 2006-2009 Daniel James.
// Copyright 2022 Christian Mazakas.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// clang-format off
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
// clang-format on
#include "../helpers/unordered.hpp"
#include "../helpers/test.hpp"
#include <boost/limits.hpp>
@@ -26,7 +22,17 @@ namespace load_factor_tests {
template <class X> void set_load_factor_tests(X*)
{
X x;
#ifdef BOOST_UNORDERED_FOA_TESTS
BOOST_TEST(x.max_load_factor() == boost::unordered::detail::foa::mlf);
BOOST_TEST(x.load_factor() == 0);
// A valid implementation could fail these tests, but I think they're
// reasonable.
x.max_load_factor(2.0);
BOOST_TEST(x.max_load_factor() == boost::unordered::detail::foa::mlf);
x.max_load_factor(0.5);
BOOST_TEST(x.max_load_factor() == boost::unordered::detail::foa::mlf);
#else
BOOST_TEST(x.max_load_factor() == 1.0);
BOOST_TEST(x.load_factor() == 0);
@@ -36,6 +42,7 @@ namespace load_factor_tests {
BOOST_TEST(x.max_load_factor() == 2.0);
x.max_load_factor(0.5);
BOOST_TEST(x.max_load_factor() == 0.5);
#endif
}
template <class X>
@@ -72,21 +79,32 @@ namespace load_factor_tests {
insert_test(ptr, std::numeric_limits<float>::infinity(), generator);
}
using test::default_generator;
using test::generate_collisions;
using test::limited_range;
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_set<int>* int_set_ptr;
boost::unordered_flat_map<int, int>* int_map_ptr;
UNORDERED_TEST(set_load_factor_tests, ((int_set_ptr)(int_map_ptr)))
UNORDERED_TEST(load_factor_insert_tests,
((int_set_ptr)(int_map_ptr))(
(default_generator)(generate_collisions)(limited_range)))
#else
boost::unordered_set<int>* int_set_ptr;
boost::unordered_multiset<int>* int_multiset_ptr;
boost::unordered_map<int, int>* int_map_ptr;
boost::unordered_multimap<int, int>* int_multimap_ptr;
using test::default_generator;
using test::generate_collisions;
using test::limited_range;
UNORDERED_TEST(set_load_factor_tests,
((int_set_ptr)(int_multiset_ptr)(int_map_ptr)(int_multimap_ptr)))
UNORDERED_TEST(load_factor_insert_tests,
((int_set_ptr)(int_multiset_ptr)(int_map_ptr)(int_multimap_ptr))(
(default_generator)(generate_collisions)(limited_range)))
#endif
}
RUN_TESTS()

View File

@@ -1,12 +1,10 @@
// Copyright 2016 Daniel James.
// Copyright 2022 Christian Mazakas.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "../helpers/postfix.hpp"
#include "../helpers/prefix.hpp"
#include <boost/unordered_map.hpp>
#include <boost/unordered_set.hpp>
#include "../helpers/unordered.hpp"
#include "../helpers/count.hpp"
#include "../helpers/helpers.hpp"
@@ -19,8 +17,13 @@
namespace merge_tests {
UNORDERED_AUTO_TEST (merge_set) {
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_set<int> x;
boost::unordered_flat_set<int> y;
#else
boost::unordered_set<int> x;
boost::unordered_set<int> y;
#endif
x.merge(y);
BOOST_TEST(x.empty());
@@ -57,6 +60,7 @@ namespace merge_tests {
test::check_equivalent_keys(y);
}
#ifndef BOOST_UNORDERED_FOA_TESTS
UNORDERED_AUTO_TEST (merge_multiset) {
boost::unordered_multiset<int> x;
boost::unordered_multiset<int> y;
@@ -134,6 +138,7 @@ namespace merge_tests {
test::check_equivalent_keys(x);
test::check_equivalent_keys(y);
}
#endif
template <class X1, class X2>
void merge_empty_test(X1*, X2*, test::random_generator generator)
@@ -228,6 +233,82 @@ namespace merge_tests {
test::check_equivalent_keys(x2);
}
using test::default_generator;
using test::generate_collisions;
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_set<test::movable, test::hash, test::equal_to,
std::allocator<test::movable> >* test_set_std_alloc;
boost::unordered_flat_map<test::object, test::object, test::hash, test::equal_to,
std::allocator<test::object> >* test_map_std_alloc;
boost::unordered_flat_set<test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_set;
boost::unordered_flat_map<test::movable, test::movable, test::hash, test::equal_to,
test::allocator2<test::movable> >* test_map;
// clang-format off
UNORDERED_TEST(merge_empty_test,
((test_set_std_alloc))
((test_set_std_alloc))
((default_generator)(generate_collisions)))
UNORDERED_TEST(merge_empty_test,
((test_map_std_alloc))
((test_map_std_alloc))
((default_generator)(generate_collisions)))
UNORDERED_TEST(merge_empty_test,
((test_set))
((test_set))
((default_generator)(generate_collisions)))
UNORDERED_TEST(merge_empty_test,
((test_map))
((test_map))
((default_generator)(generate_collisions)))
UNORDERED_TEST(merge_into_empty_test,
((test_set_std_alloc))
((default_generator)(generate_collisions)))
UNORDERED_TEST(merge_into_empty_test,
((test_map_std_alloc))
((default_generator)(generate_collisions)))
UNORDERED_TEST(merge_into_empty_test,
((test_set))
((default_generator)(generate_collisions)))
UNORDERED_TEST(merge_into_empty_test,
((test_map))
((default_generator)(generate_collisions)))
UNORDERED_TEST(merge_into_unique_keys_test,
((test_set_std_alloc))
((test_set_std_alloc))
((0)(1)(2))
((0)(1)(2))
((default_generator)(generate_collisions)))
UNORDERED_TEST(merge_into_unique_keys_test,
((test_map_std_alloc))
((test_map_std_alloc))
((0)(1)(2))
((0)(1)(2))
((default_generator)(generate_collisions)))
UNORDERED_TEST(merge_into_unique_keys_test,
((test_set))
((test_set))
((0)(1)(2))
((0)(1)(2))
((default_generator)(generate_collisions)))
UNORDERED_TEST(merge_into_unique_keys_test,
((test_map))
((test_map))
((0)(1)(2))
((0)(1)(2))
((default_generator)(generate_collisions)))
// clang-format on
#else
boost::unordered_set<test::movable, test::hash, test::equal_to,
std::allocator<test::movable> >* test_set_std_alloc;
boost::unordered_multiset<test::movable, test::hash, test::equal_to,
@@ -248,9 +329,6 @@ namespace merge_tests {
boost::unordered_multimap<test::movable, test::movable, test::hash,
test::equal_to, test::allocator2<test::movable> >* test_multimap;
using test::default_generator;
using test::generate_collisions;
// clang-format off
UNORDERED_TEST(merge_empty_test,
((test_set_std_alloc)(test_multiset_std_alloc))
@@ -332,6 +410,8 @@ UNORDERED_TEST(merge_into_equiv_keys_test,
((0)(1)(2))
((default_generator)(generate_collisions)))
// clang-format on
#endif
}
RUN_TESTS()

View File

@@ -1,14 +1,10 @@
// Copyright 2008-2009 Daniel James.
// Copyright 2022 Christian Mazakas.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or move at http://www.boost.org/LICENSE_1_0.txt)
// clang-format off
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
// clang-format on
#include "../helpers/unordered.hpp"
#include "../helpers/test.hpp"
#include "../objects/test.hpp"
@@ -18,6 +14,9 @@
#include "../helpers/equivalent.hpp"
#include "../helpers/invariants.hpp"
#include <boost/core/ignore_unused.hpp>
#include <iterator>
#if defined(BOOST_MSVC)
#pragma warning(disable : 4127) // conditional expression is constant
#endif
@@ -68,8 +67,16 @@ namespace move_tests {
BOOST_TEST(test::equivalent(y.hash_function(), hf));
BOOST_TEST(test::equivalent(y.key_eq(), eq));
BOOST_TEST(test::equivalent(y.get_allocator(), al));
#ifdef BOOST_UNORDERED_FOA_TESTS
BOOST_TEST(y.max_load_factor() == 0.875);
#else
BOOST_TEST(y.max_load_factor() == 1.0);
#endif
test::check_equivalent_keys(y);
#if defined(BOOST_UNORDERED_USE_MOVE) || \
!defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
BOOST_TEST_EQ(test::detail::tracker.count_allocations, 0u);
#endif
}
{
@@ -87,7 +94,7 @@ namespace move_tests {
}
template <class T>
void move_assign_tests1(T*, test::random_generator const& generator)
void move_assign_tests1(T* p, test::random_generator const& generator)
{
{
test::check_instances check_;
@@ -98,6 +105,19 @@ namespace move_tests {
y = create(v, count);
#if BOOST_UNORDERED_TEST_MOVING && defined(BOOST_HAS_NRVO)
BOOST_TEST(count == test::global_object_count);
#endif
test::check_container(y, v);
test::check_equivalent_keys(y);
}
{
test::random_values<T> v;
T y;
y = empty(p);
#if defined(BOOST_UNORDERED_USE_MOVE) || \
!defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
BOOST_TEST_EQ(test::detail::tracker.count_allocations, 0u);
#endif
test::check_container(y, v);
test::check_equivalent_keys(y);
@@ -126,7 +146,11 @@ namespace move_tests {
BOOST_TEST(test::equivalent(y.hash_function(), hf));
BOOST_TEST(test::equivalent(y.key_eq(), eq));
BOOST_TEST(test::equivalent(y.get_allocator(), al));
#ifdef BOOST_UNORDERED_FOA_TESTS
BOOST_TEST(y.max_load_factor() == 0.875);
#else
BOOST_TEST(y.max_load_factor() == 0.5); // Not necessarily required.
#endif
test::check_equivalent_keys(y);
}
@@ -142,7 +166,11 @@ namespace move_tests {
BOOST_TEST(test::equivalent(y.hash_function(), hf));
BOOST_TEST(test::equivalent(y.key_eq(), eq));
BOOST_TEST(test::equivalent(y.get_allocator(), al2));
#ifdef BOOST_UNORDERED_FOA_TESTS
BOOST_TEST(y.max_load_factor() == 0.875);
#else
BOOST_TEST(y.max_load_factor() == 2.0); // Not necessarily required.
#endif
test::check_equivalent_keys(y);
}
@@ -172,7 +200,11 @@ namespace move_tests {
BOOST_TEST(test::equivalent(y.hash_function(), hf));
BOOST_TEST(test::equivalent(y.key_eq(), eq));
BOOST_TEST(test::equivalent(y.get_allocator(), al));
#ifdef BOOST_UNORDERED_FOA_TESTS
BOOST_TEST(y.max_load_factor() == 0.875);
#else
BOOST_TEST(y.max_load_factor() == 1.0); // Not necessarily required.
#endif
test::check_equivalent_keys(y);
}
}
@@ -195,7 +227,11 @@ namespace move_tests {
BOOST_TEST(y.empty());
test::check_container(y, v2);
test::check_equivalent_keys(y);
#ifdef BOOST_UNORDERED_FOA_TESTS
BOOST_TEST(y.max_load_factor() == 0.875);
#else
BOOST_TEST(y.max_load_factor() == 2.0);
#endif
#if defined(BOOST_HAS_NRVO)
if (BOOST_UNORDERED_TEST_MOVING
@@ -220,7 +256,11 @@ namespace move_tests {
#endif
test::check_container(y, v);
test::check_equivalent_keys(y);
#ifdef BOOST_UNORDERED_FOA_TESTS
BOOST_TEST(y.max_load_factor() == 0.875);
#else
BOOST_TEST(y.max_load_factor() == 0.5);
#endif
#if defined(BOOST_HAS_NRVO)
if (BOOST_UNORDERED_TEST_MOVING
@@ -233,6 +273,36 @@ namespace move_tests {
#endif
}
{
test::random_values<T> v;
T y(0, hf, eq, al1);
T x(0, hf, eq, al2);
x.max_load_factor(0.25);
BOOST_TEST_EQ(test::detail::tracker.count_allocations, 0u);
y = boost::move(x);
#if defined(BOOST_UNORDERED_USE_MOVE) || \
!defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
BOOST_TEST_EQ(test::detail::tracker.count_allocations, 0u);
#endif
test::check_container(y, v);
test::check_equivalent_keys(y);
#ifdef BOOST_UNORDERED_FOA_TESTS
BOOST_TEST(y.max_load_factor() == 0.875);
#else
BOOST_TEST(y.max_load_factor() == 0.25);
#endif
if (BOOST_UNORDERED_TEST_MOVING
? (bool)allocator_type::is_propagate_on_move
: (bool)allocator_type::is_propagate_on_assign) {
BOOST_TEST(test::equivalent(y.get_allocator(), al2));
} else {
BOOST_TEST(test::equivalent(y.get_allocator(), al1));
}
}
{
test::check_instances check_;
@@ -250,7 +320,11 @@ namespace move_tests {
}
test::check_container(y, v);
test::check_equivalent_keys(y);
#ifdef BOOST_UNORDERED_FOA_TESTS
BOOST_TEST(y.max_load_factor() == 0.875);
#else
BOOST_TEST(y.max_load_factor() == 0.25);
#endif
if (BOOST_UNORDERED_TEST_MOVING
? (bool)allocator_type::is_propagate_on_move
@@ -286,7 +360,11 @@ namespace move_tests {
test::check_container(y, v2);
test::check_equivalent_keys(y);
#ifdef BOOST_UNORDERED_FOA_TESTS
BOOST_TEST(y.max_load_factor() == 0.875);
#else
BOOST_TEST(y.max_load_factor() == 0.5);
#endif
if (BOOST_UNORDERED_TEST_MOVING
? (bool)allocator_type::is_propagate_on_move
@@ -298,17 +376,65 @@ namespace move_tests {
}
}
using test::default_generator;
using test::generate_collisions;
using test::limited_range;
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_map<test::object, test::object, test::hash,
test::equal_to,
std::allocator<std::pair<test::object const, test::object> > >*
test_map_std_alloc;
boost::unordered_flat_set<test::object, test::hash, test::equal_to,
test::allocator2<test::object> >* test_set;
boost::unordered_flat_map<test::object, test::object, test::hash,
test::equal_to,
test::allocator1<std::pair<test::object const, test::object> > >* test_map;
boost::unordered_flat_set<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::propagate_move> >*
test_set_prop_move;
boost::unordered_flat_map<test::object, test::object, test::hash,
test::equal_to,
test::cxx11_allocator<std::pair<test::object const, test::object>,
test::propagate_move> >* test_map_prop_move;
boost::unordered_flat_set<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_move> >*
test_set_no_prop_move;
boost::unordered_flat_map<test::object, test::object, test::hash,
test::equal_to,
test::cxx11_allocator<std::pair<test::object const, test::object>,
test::no_propagate_move> >* test_map_no_prop_move;
UNORDERED_TEST(move_construct_tests1,
((test_map_std_alloc)(test_set)(test_map)(test_set_prop_move)(test_map_prop_move)(test_set_no_prop_move)(test_map_no_prop_move))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(move_assign_tests1,
((test_map_std_alloc)(test_set)(test_map)(test_set_prop_move)(test_map_prop_move)(test_set_no_prop_move)(test_map_no_prop_move))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(move_construct_tests2,
((test_set)(test_map)(test_set_prop_move)(test_map_prop_move)(test_set_no_prop_move)(test_map_no_prop_move))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(move_assign_tests2,
((test_set)(test_map)(test_set_prop_move)(test_map_prop_move)(test_set_no_prop_move)(test_map_no_prop_move))(
(default_generator)(generate_collisions)(limited_range)))
#else
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
std::allocator<test::object> >* test_map_std_alloc;
std::allocator<std::pair<test::object const, test::object> > >*
test_map_std_alloc;
boost::unordered_set<test::object, test::hash, test::equal_to,
test::allocator2<test::object> >* test_set;
boost::unordered_multiset<test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_map;
test::allocator1<std::pair<test::object const, test::object> > >* test_map;
boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to, test::allocator2<test::object> >* test_multimap;
test::equal_to,
test::allocator2<std::pair<test::object const, test::object> > >*
test_multimap;
boost::unordered_set<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::propagate_move> >*
@@ -317,11 +443,12 @@ namespace move_tests {
test::cxx11_allocator<test::object, test::propagate_move> >*
test_multiset_prop_move;
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::propagate_move> >*
test_map_prop_move;
test::cxx11_allocator<std::pair<test::object const, test::object>,
test::propagate_move> >* test_map_prop_move;
boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to, test::cxx11_allocator<test::object, test::propagate_move> >*
test_multimap_prop_move;
test::equal_to,
test::cxx11_allocator<std::pair<test::object const, test::object>,
test::propagate_move> >* test_multimap_prop_move;
boost::unordered_set<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_move> >*
@@ -330,16 +457,12 @@ namespace move_tests {
test::cxx11_allocator<test::object, test::no_propagate_move> >*
test_multiset_no_prop_move;
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_move> >*
test_map_no_prop_move;
test::cxx11_allocator<std::pair<test::object const, test::object>,
test::no_propagate_move> >* test_map_no_prop_move;
boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_move> >*
test_multimap_no_prop_move;
using test::default_generator;
using test::generate_collisions;
using test::limited_range;
test::cxx11_allocator<std::pair<test::object const, test::object>,
test::no_propagate_move> >* test_multimap_no_prop_move;
UNORDERED_TEST(move_construct_tests1,
((test_map_std_alloc)(test_set)(test_multiset)(test_map)(test_multimap)(
@@ -367,6 +490,7 @@ namespace move_tests {
test_set_no_prop_move)(test_multiset_no_prop_move)(test_map_no_prop_move)(
test_multimap_no_prop_move))(
(default_generator)(generate_collisions)(limited_range)))
#endif
}
RUN_TESTS()

View File

@@ -1,16 +1,13 @@
// Copyright 2013 Daniel James.
// Copyright 2022 Christian Mazakas.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// clang-format off
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
// clang-format on
#include "../helpers/unordered.hpp"
#include "../helpers/test.hpp"
#include "../helpers/fwd.hpp"
#if defined(BOOST_MSVC)
#pragma warning(push)
@@ -201,6 +198,12 @@ namespace noexcept_tests {
UNORDERED_AUTO_TEST (test_noexcept) {
if (have_is_nothrow_move) {
#ifdef BOOST_UNORDERED_FOA_TESTS
BOOST_TEST((boost::is_nothrow_move_constructible<
boost::unordered_flat_set<int> >::value));
BOOST_TEST((boost::is_nothrow_move_constructible<
boost::unordered_flat_map<int, int> >::value));
#else
BOOST_TEST((boost::is_nothrow_move_constructible<
boost::unordered_set<int> >::value));
BOOST_TEST((boost::is_nothrow_move_constructible<
@@ -209,19 +212,35 @@ namespace noexcept_tests {
boost::unordered_map<int, int> >::value));
BOOST_TEST((boost::is_nothrow_move_constructible<
boost::unordered_multimap<int, int> >::value));
#endif
}
#ifdef BOOST_UNORDERED_FOA_TESTS
BOOST_TEST(
(!boost::is_nothrow_move_constructible<
boost::unordered_flat_set<int, hash_possible_exception> >::value));
BOOST_TEST(
(!boost::is_nothrow_move_constructible<boost::unordered_flat_set<int,
boost::hash<int>, equal_to_possible_exception> >::value));
#else
BOOST_TEST((!boost::is_nothrow_move_constructible<
boost::unordered_set<int, hash_possible_exception> >::value));
BOOST_TEST(
(!boost::is_nothrow_move_constructible<boost::unordered_multiset<int,
boost::hash<int>, equal_to_possible_exception> >::value));
#endif
}
UNORDERED_AUTO_TEST (test_nothrow_move_when_noexcept) {
#ifdef BOOST_UNORDERED_FOA_TESTS
typedef boost::unordered_flat_set<int, hash_nothrow_move_construct,
equal_to_nothrow_move_construct>
throwing_set;
#else
typedef boost::unordered_set<int, hash_nothrow_move_construct,
equal_to_nothrow_move_construct>
throwing_set;
#endif
if (have_is_nothrow_move) {
BOOST_TEST(boost::is_nothrow_move_constructible<throwing_set>::value);
@@ -247,42 +266,76 @@ namespace noexcept_tests {
throwing_test_exception = false;
}
UNORDERED_AUTO_TEST (test_nothrow_move_assign_when_noexcept) {
typedef boost::unordered_set<int, hash_nothrow_move_assign,
equal_to_nothrow_move_assign>
throwing_set;
template <class T>
void test_nothrow_move_assign_when_noexcept(T*, test::random_generator const&)
{
{
if (have_is_nothrow_move_assign) {
BOOST_TEST(boost::is_nothrow_move_assignable<T>::value);
}
if (have_is_nothrow_move_assign) {
BOOST_TEST(boost::is_nothrow_move_assignable<throwing_set>::value);
throwing_test_exception = false;
T x1;
T x2;
x1.insert(10);
x1.insert(50);
for (int i = 0; i < 100; ++i) {
x2.insert(i);
}
try {
throwing_test_exception = true;
x2 = boost::move(x1);
BOOST_TEST(x2.size() == 2);
BOOST_TEST(*x2.begin() == 10 || *x2.begin() == 50);
BOOST_TEST(have_is_nothrow_move_assign);
} catch (test_exception) {
BOOST_TEST(!have_is_nothrow_move_assign);
}
throwing_test_exception = false;
}
throwing_test_exception = false;
{
if (have_is_nothrow_move_assign) {
BOOST_TEST(boost::is_nothrow_move_assignable<T>::value);
}
throwing_set x1;
throwing_set x2;
x1.insert(10);
x1.insert(50);
for (int i = 0; i < 100; ++i) {
x2.insert(i);
throwing_test_exception = false;
T x1;
T x2;
x1.insert(10);
x1.insert(50);
for (int i = 0; i < 100; ++i) {
x2.insert(i);
}
try {
throwing_test_exception = true;
x1 = boost::move(x2);
BOOST_TEST(x1.size() == 100);
BOOST_TEST(have_is_nothrow_move_assign);
} catch (test_exception) {
BOOST_TEST(!have_is_nothrow_move_assign);
}
throwing_test_exception = false;
}
try {
throwing_test_exception = true;
x2 = boost::move(x1);
BOOST_TEST(x2.size() == 2);
BOOST_TEST(*x2.begin() == 10 || *x2.begin() == 50);
BOOST_TEST(have_is_nothrow_move_assign);
} catch (test_exception) {
BOOST_TEST(!have_is_nothrow_move_assign);
}
throwing_test_exception = false;
}
UNORDERED_AUTO_TEST (test_nothrow_swap_when_noexcept) {
#if BOOST_UNORDERED_FOA_TESTS
typedef boost::unordered_flat_set<int, hash_nothrow_swap,
equal_to_nothrow_swap>
throwing_set;
#else
typedef boost::unordered_set<int, hash_nothrow_swap, equal_to_nothrow_swap>
throwing_set;
#endif
if (have_is_nothrow_swap) {
BOOST_TEST(boost::is_nothrow_swappable<throwing_set>::value);
@@ -318,4 +371,93 @@ namespace noexcept_tests {
#pragma warning(pop)
#endif
template <class T> class allocator1
{
BOOST_COPYABLE_AND_MOVABLE(allocator1)
allocator1 operator=(BOOST_COPY_ASSIGN_REF(allocator1));
allocator1 operator=(BOOST_RV_REF(allocator1));
public:
typedef T value_type;
allocator1() {}
allocator1(allocator1 const&) {}
template <class U> allocator1(allocator1<U> const&) {}
T* allocate(std::size_t n)
{
noexcept_tests::test_throw("Allocate");
return static_cast<T*>(::operator new(n * sizeof(T)));
}
void deallocate(T* p, std::size_t) { ::operator delete(p); }
friend bool operator==(allocator1 const&, allocator1 const&) { return true; }
friend bool operator!=(allocator1 const&, allocator1 const&) { return false; }
};
template <class T> class allocator2
{
BOOST_COPYABLE_AND_MOVABLE(allocator2)
allocator2 operator=(BOOST_COPY_ASSIGN_REF(allocator2));
public:
typedef T value_type;
typedef boost::true_type propagate_on_container_move_assignment;
allocator2() {}
allocator2(allocator2 const&) {}
template <class U> allocator2(allocator2<U> const&) {}
allocator2& operator=(BOOST_RV_REF(allocator2)) { return *this; }
T* allocate(std::size_t n)
{
noexcept_tests::test_throw("Allocate");
return static_cast<T*>(::operator new(n * sizeof(T)));
}
void deallocate(T* p, std::size_t) { ::operator delete(p); }
friend bool operator==(allocator2 const&, allocator2 const&) { return true; }
friend bool operator!=(allocator2 const&, allocator2 const&) { return false; }
};
UNORDERED_AUTO_TEST (prelim_allocator_checks) {
BOOST_TEST(boost::allocator_is_always_equal<allocator1<int> >::type::value);
BOOST_TEST(!boost::allocator_propagate_on_container_move_assignment<
allocator1<int> >::type::value);
BOOST_TEST(boost::allocator_is_always_equal<allocator2<int> >::type::value);
BOOST_TEST(boost::allocator_propagate_on_container_move_assignment<
allocator2<int> >::type::value);
}
using test::default_generator;
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_set<int, noexcept_tests::hash_nothrow_move_assign,
noexcept_tests::equal_to_nothrow_move_assign, allocator1<int> >*
throwing_set_alloc1;
boost::unordered_flat_set<int, noexcept_tests::hash_nothrow_move_assign,
noexcept_tests::equal_to_nothrow_move_assign, allocator2<int> >*
throwing_set_alloc2;
UNORDERED_TEST(test_nothrow_move_assign_when_noexcept,
((throwing_set_alloc1)(throwing_set_alloc2))((default_generator)))
#else
boost::unordered_set<int, noexcept_tests::hash_nothrow_move_assign,
noexcept_tests::equal_to_nothrow_move_assign, allocator1<int> >*
throwing_set_alloc1;
boost::unordered_set<int, noexcept_tests::hash_nothrow_move_assign,
noexcept_tests::equal_to_nothrow_move_assign, allocator2<int> >*
throwing_set_alloc2;
UNORDERED_TEST(test_nothrow_move_assign_when_noexcept,
((throwing_set_alloc1)(throwing_set_alloc2))((default_generator)))
#endif
RUN_TESTS()

View File

@@ -0,0 +1,666 @@
// Copyright (C) 2022 Christian Mazakas
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or move at http://www.boost.org/LICENSE_1_0.txt)
#include "../helpers/unordered.hpp"
#include "../helpers/test.hpp"
#include "../objects/test.hpp"
#include "../objects/cxx11_allocator.hpp"
#include "../helpers/random_values.hpp"
#include "../helpers/tracker.hpp"
#include "../helpers/equivalent.hpp"
#include "../helpers/invariants.hpp"
#include <boost/core/ignore_unused.hpp>
#include <iterator>
#if defined(BOOST_MSVC)
#pragma warning(disable : 4127) // conditional expression is constant
#endif
namespace move_tests {
test::seed_t initialize_seed(98624);
#if defined(BOOST_UNORDERED_USE_MOVE) || \
!defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
#define BOOST_UNORDERED_TEST_MOVING 1
#else
#define BOOST_UNORDERED_TEST_MOVING 0
#endif
template <class T> T empty(T*) { return T(); }
template <class T>
T create(test::random_values<T> const& v, test::object_count& count)
{
T x(v.begin(), v.end());
count = test::global_object_count;
return x;
}
template <class T>
T create(test::random_values<T> const& v, test::object_count& count,
typename T::hasher hf, typename T::key_equal eq,
typename T::allocator_type al, float mlf)
{
T x(0, hf, eq, al);
x.max_load_factor(mlf);
x.insert(v.begin(), v.end());
count = test::global_object_count;
return x;
}
template <class T> T const& get_key(T const& t) { return t; }
template <class K, class V> K const& get_key(std::pair<K const, V> const& kv)
{
return kv.first;
}
template <class T> T const& get_value(T const& t) { return t; }
template <class K, class V> K const& get_value(std::pair<K const, V> const& kv)
{
return kv.second;
}
template <class T>
static void insert_range(T& y, test::random_values<T> const& v)
{
y.insert(v.begin(), v.end());
BOOST_TEST_EQ(y.size(),
static_cast<typename T::size_type>(std::distance(y.begin(), y.end())));
}
template <class T>
static void insert_single(T& y, test::random_values<T> const& v)
{
y.insert(*v.begin());
BOOST_TEST_EQ(y.size(),
static_cast<typename T::size_type>(std::distance(y.begin(), y.end())));
}
template <class T>
static void insert_single_hint(T& y, test::random_values<T> const& v)
{
y.insert(y.end(), *v.begin());
BOOST_TEST_EQ(y.size(),
static_cast<typename T::size_type>(std::distance(y.begin(), y.end())));
}
template <class T> struct insert_or_assign_invoker
{
void operator()(T&, test::random_values<T> const&) {}
};
template <class Key, class T, class Hash, class KeyEqual, class Allocator>
struct insert_or_assign_invoker<
boost::unordered_map<Key, T, Hash, KeyEqual, Allocator> >
{
void operator()(boost::unordered_map<Key, T, Hash, KeyEqual, Allocator>& y,
test::random_values<
boost::unordered_map<Key, T, Hash, KeyEqual, Allocator> > const& v)
{
typedef typename boost::unordered_map<Key, T, Hash, KeyEqual,
Allocator>::size_type size_type;
y.insert_or_assign(get_key(*v.begin()), get_value(*v.begin()));
BOOST_TEST_EQ(
y.size(), static_cast<size_type>(std::distance(y.begin(), y.end())));
}
};
template <class T>
static void insert_or_assign(T& y, test::random_values<T> const& v)
{
insert_or_assign_invoker<T>()(y, v);
}
template <class T> struct insert_or_assign_hint_invoker
{
void operator()(T&, test::random_values<T> const&) {}
};
template <class Key, class T, class Hash, class KeyEqual, class Allocator>
struct insert_or_assign_hint_invoker<
boost::unordered_map<Key, T, Hash, KeyEqual, Allocator> >
{
void operator()(boost::unordered_map<Key, T, Hash, KeyEqual, Allocator>& y,
test::random_values<
boost::unordered_map<Key, T, Hash, KeyEqual, Allocator> > const& v)
{
typedef typename boost::unordered_map<Key, T, Hash, KeyEqual,
Allocator>::size_type size_type;
y.insert_or_assign(y.end(), get_key(*v.begin()), get_value(*v.begin()));
BOOST_TEST_EQ(
y.size(), static_cast<size_type>(std::distance(y.begin(), y.end())));
}
};
template <class T>
static void insert_or_assign_hint(T& y, test::random_values<T> const& v)
{
insert_or_assign_hint_invoker<T>()(y, v);
}
template <class T> struct try_emplace_invoker
{
void operator()(T&, test::random_values<T> const&) {}
};
template <class Key, class T, class Hash, class KeyEqual, class Allocator>
struct try_emplace_invoker<
boost::unordered_map<Key, T, Hash, KeyEqual, Allocator> >
{
void operator()(boost::unordered_map<Key, T, Hash, KeyEqual, Allocator>& y,
test::random_values<
boost::unordered_map<Key, T, Hash, KeyEqual, Allocator> > const& v)
{
typedef typename boost::unordered_map<Key, T, Hash, KeyEqual,
Allocator>::size_type size_type;
y.try_emplace(get_key(*v.begin()), get_value(*v.begin()));
BOOST_TEST_EQ(
y.size(), static_cast<size_type>(std::distance(y.begin(), y.end())));
}
};
template <class T>
static void try_emplace(T& y, test::random_values<T> const& v)
{
try_emplace_invoker<T>()(y, v);
}
template <class T> struct try_emplace_hint_invoker
{
void operator()(T&, test::random_values<T> const&) {}
};
template <class Key, class T, class Hash, class KeyEqual, class Allocator>
struct try_emplace_hint_invoker<
boost::unordered_map<Key, T, Hash, KeyEqual, Allocator> >
{
void operator()(boost::unordered_map<Key, T, Hash, KeyEqual, Allocator>& y,
test::random_values<
boost::unordered_map<Key, T, Hash, KeyEqual, Allocator> > const& v)
{
typedef typename boost::unordered_map<Key, T, Hash, KeyEqual,
Allocator>::size_type size_type;
y.try_emplace(y.end(), get_key(*v.begin()), get_value(*v.begin()));
BOOST_TEST_EQ(
y.size(), static_cast<size_type>(std::distance(y.begin(), y.end())));
}
};
template <class T>
static void try_emplace_hint(T& y, test::random_values<T> const& v)
{
try_emplace_hint_invoker<T>()(y, v);
}
template <class T> struct at_invoker
{
void operator()(T&, test::random_values<T> const&) {}
};
template <class Key, class T, class Hash, class KeyEqual, class Allocator>
struct at_invoker<boost::unordered_map<Key, T, Hash, KeyEqual, Allocator> >
{
void operator()(boost::unordered_map<Key, T, Hash, KeyEqual, Allocator>& y,
test::random_values<
boost::unordered_map<Key, T, Hash, KeyEqual, Allocator> > const& v)
{
BOOST_TRY { y.at(get_key(*v.begin())); }
BOOST_CATCH(...) {}
BOOST_CATCH_END
}
};
template <class T> static void at(T& y, test::random_values<T> const& v)
{
at_invoker<T>()(y, v);
}
template <class T> struct index_operator_invoker
{
void operator()(T&, test::random_values<T> const&) {}
};
template <class Key, class T, class Hash, class KeyEqual, class Allocator>
struct index_operator_invoker<
boost::unordered_map<Key, T, Hash, KeyEqual, Allocator> >
{
void operator()(boost::unordered_map<Key, T, Hash, KeyEqual, Allocator>& y,
test::random_values<
boost::unordered_map<Key, T, Hash, KeyEqual, Allocator> > const& v)
{
typedef typename boost::unordered_map<Key, T, Hash, KeyEqual,
Allocator>::size_type size_type;
y[get_key(*v.begin())] = get_value(*v.begin());
BOOST_TEST_EQ(
y.size(), static_cast<size_type>(std::distance(y.begin(), y.end())));
}
};
template <class T>
static void index_operator(T& y, test::random_values<T> const& v)
{
index_operator_invoker<T>()(y, v);
}
template <class T> static void clear(T& y, test::random_values<T> const&)
{
y.clear();
BOOST_TEST(y.empty());
BOOST_TEST_EQ(y.size(),
static_cast<typename T::size_type>(std::distance(y.begin(), y.end())));
}
template <class T> static void capacity(T& y, test::random_values<T> const&)
{
(void)y.empty();
(void)y.size();
(void)y.max_size();
(void)y.load_factor();
(void)y.max_load_factor();
(void)y.hash_function();
(void)y.key_eq();
(void)y.get_allocator();
}
template <class T> static void iterators(T& y, test::random_values<T> const&)
{
BOOST_TEST_EQ(y.size(),
static_cast<typename T::size_type>(std::distance(y.begin(), y.end())));
}
template <class T>
static void erase_range(T& y, test::random_values<T> const&)
{
y.erase(y.begin(), y.end());
BOOST_TEST(y.empty());
BOOST_TEST_EQ(y.size(),
static_cast<typename T::size_type>(std::distance(y.begin(), y.end())));
}
template <class T>
static void erase_key(T& y, test::random_values<T> const& v)
{
y.erase(get_key(*v.begin()));
BOOST_TEST_EQ(y.size(),
static_cast<typename T::size_type>(std::distance(y.begin(), y.end())));
}
template <class T> static void lookup(T& y, test::random_values<T> const& v)
{
(void)y.count(get_key(*v.begin()));
(void)y.find(get_key(*v.begin()));
(void)y.contains(get_key(*v.begin()));
(void)y.equal_range(get_key(*v.begin()));
}
template <class T> static void reserve(T& y, test::random_values<T> const&)
{
y.reserve(1337);
BOOST_TEST_GT(y.bucket_count(), 1337u);
BOOST_TEST_EQ(y.size(),
static_cast<typename T::size_type>(std::distance(y.begin(), y.end())));
}
template <class T>
static void copy_assignment(T& y, test::random_values<T> const& v)
{
T x(v.begin(), v.end());
y = x;
BOOST_TEST_EQ(y.size(), x.size());
BOOST_TEST_EQ(y.size(),
static_cast<typename T::size_type>(std::distance(y.begin(), y.end())));
}
template <class T>
static void move_assignment(T& y, test::random_values<T> const& v)
{
T x(v.begin(), v.end());
std::size_t const size = x.size();
y = boost::move(x);
BOOST_TEST_GE(y.size(), size);
BOOST_TEST_EQ(y.size(),
static_cast<typename T::size_type>(std::distance(y.begin(), y.end())));
}
template <class T> static void equal(T& y, test::random_values<T> const& v)
{
T x(v.begin(), v.end());
(void)(y == x);
BOOST_TEST_EQ(y.size(),
static_cast<typename T::size_type>(std::distance(y.begin(), y.end())));
}
template <class T> static void extract(T& y, test::random_values<T> const& v)
{
(void)y.extract(get_key(*v.begin()));
BOOST_TEST_EQ(y.size(),
static_cast<typename T::size_type>(std::distance(y.begin(), y.end())));
}
template <class T> static void merge(T& y, test::random_values<T> const& v)
{
T x(v.begin(), v.end());
if (y.get_allocator() == x.get_allocator()) {
y.merge(x);
}
BOOST_TEST_EQ(y.size(),
static_cast<typename T::size_type>(std::distance(y.begin(), y.end())));
}
template <class X> bool pred(X const&) { return true; }
template <class T>
static void erase_with_pred(T& y, test::random_values<T> const&)
{
erase_if(y, pred<typename T::value_type>);
BOOST_TEST_EQ(y.size(),
static_cast<typename T::size_type>(std::distance(y.begin(), y.end())));
}
template <class T>
static void container_swap(T& y, test::random_values<T> const& v)
{
T x(v.begin(), v.end());
if (boost::allocator_propagate_on_container_swap<
typename T::allocator_type>::type::value ||
x.get_allocator() == y.get_allocator()) {
y.swap(x);
}
BOOST_TEST_EQ(y.size(),
static_cast<typename T::size_type>(std::distance(y.begin(), y.end())));
}
template <class T> static void buckets(T& y, test::random_values<T> const& v)
{
(void)y.begin(0);
(void)y.end(0);
(void)y.bucket_count();
(void)y.max_bucket_count();
(void)y.bucket_size(0);
(void)y.bucket(get_key(*v.begin()));
}
template <class T>
static void double_move_construct(T& y, test::random_values<T> const&)
{
T x = boost::move(y);
x.clear();
BOOST_TEST_EQ(y.size(),
static_cast<typename T::size_type>(std::distance(y.begin(), y.end())));
BOOST_TEST_EQ(x.size(),
static_cast<typename T::size_type>(std::distance(x.begin(), x.end())));
}
template <class T>
static void double_move_assign(T& y, test::random_values<T> const&)
{
T x;
x = boost::move(y);
x.clear();
BOOST_TEST_EQ(y.size(),
static_cast<typename T::size_type>(std::distance(y.begin(), y.end())));
BOOST_TEST_EQ(x.size(),
static_cast<typename T::size_type>(std::distance(x.begin(), x.end())));
}
template <class T>
static void post_move_tests(T* ptr, test::random_generator const& generator)
{
// clang-format off
void (*fps[])(T&, test::random_values<T> const&) = {
insert_range<T>,
insert_single<T>,
insert_single_hint<T>,
insert_or_assign<T>,
insert_or_assign_hint<T>,
try_emplace<T>,
try_emplace_hint<T>,
at<T>,
index_operator<T>,
clear<T>,
capacity<T>,
iterators<T>,
erase_range<T>,
erase_key<T>,
lookup<T>,
reserve<T>,
copy_assignment<T>,
move_assignment<T>,
equal<T>,
#ifndef BOOST_UNORDERED_FOA_TESTS
extract<T>,
buckets<T>,
#endif
merge<T>,
erase_with_pred<T>,
container_swap<T>,
double_move_construct<T>,
double_move_assign<T>
};
// clang-format on
std::size_t const len = (sizeof(fps) / sizeof(*(fps)));
for (std::size_t i = 0; i < len; ++i) {
test::check_instances check_;
test::random_values<T> const v(1000, generator);
test::object_count count;
T y(create(v, count));
unsigned num_allocs = test::detail::tracker.count_allocations;
(void)num_allocs;
T x(boost::move(y));
#if defined(BOOST_UNORDERED_USE_MOVE) || \
!defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
BOOST_TEST(y.empty());
BOOST_TEST(y.begin() == y.end());
BOOST_TEST_EQ(y.bucket_count(), 0u);
BOOST_TEST_EQ(test::detail::tracker.count_allocations, num_allocs);
#endif
fps[i](y, v);
test::check_container(x, v);
test::check_equivalent_keys(x);
}
for (std::size_t i = 0; i < len; ++i) {
typename T::hasher hf(1);
typename T::key_equal eq(1);
typename T::allocator_type al1(1);
typename T::allocator_type al2(2);
test::check_instances check_;
test::random_values<T> v(1000, generator);
test::object_count count;
T y(v.begin(), v.end(), 0, hf, eq, al1);
T x(boost::move(y), al2);
#ifdef BOOST_UNORDERED_FOA_TESTS
BOOST_TEST(y.empty());
BOOST_TEST(y.begin() == y.end());
#else
BOOST_TEST_NOT(y.empty());
BOOST_TEST(y.begin() != y.end());
#endif
fps[i](y, v);
test::check_container(x, v);
test::check_equivalent_keys(x);
}
for (std::size_t i = 0; i < len; ++i) {
test::check_instances check_;
test::random_values<T> v(1000, generator);
test::object_count count;
T y(create(v, count));
unsigned num_allocs = test::detail::tracker.count_allocations;
(void)num_allocs;
T x(empty(ptr));
x = boost::move(y);
#if defined(BOOST_UNORDERED_USE_MOVE) || \
!defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
BOOST_TEST(y.empty());
BOOST_TEST(y.begin() == y.end());
BOOST_TEST_EQ(y.bucket_count(), 0u);
BOOST_TEST_EQ(test::detail::tracker.count_allocations, num_allocs);
#endif
fps[i](y, v);
test::check_container(x, v);
test::check_equivalent_keys(x);
}
for (std::size_t i = 0; i < len; ++i) {
typename T::hasher hf(1);
typename T::key_equal eq(1);
typename T::allocator_type al1(1);
typename T::allocator_type al2(2);
test::check_instances check_;
test::random_values<T> v(1000, generator);
test::object_count count;
T y(v.begin(), v.end(), 0, hf, eq, al1);
unsigned num_allocs = test::detail::tracker.count_allocations;
(void)num_allocs;
T x(al2);
x = boost::move(y);
bool b = boost::allocator_propagate_on_container_move_assignment<
typename T::allocator_type>::type::value;
if (b) {
#if defined(BOOST_UNORDERED_USE_MOVE) || \
!defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
BOOST_TEST(y.empty());
BOOST_TEST(y.begin() == y.end());
BOOST_TEST_EQ(y.bucket_count(), 0u);
BOOST_TEST_EQ(test::detail::tracker.count_allocations, num_allocs);
#else
BOOST_TEST_NOT(y.empty());
BOOST_TEST(y.begin() != y.end());
#endif
} else {
#ifdef BOOST_UNORDERED_FOA_TESTS
BOOST_TEST(y.empty());
BOOST_TEST(y.begin() == y.end());
#else
BOOST_TEST_NOT(y.empty());
BOOST_TEST(y.begin() != y.end());
#endif
}
fps[i](y, v);
test::check_container(x, v);
test::check_equivalent_keys(x);
}
}
using test::default_generator;
using test::generate_collisions;
using test::limited_range;
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_map<test::object, test::object, test::hash,
test::equal_to,
std::allocator<std::pair<test::object const, test::object> > >*
test_map_std_alloc;
boost::unordered_flat_set<test::object, test::hash, test::equal_to,
test::allocator2<test::object> >* test_set;
boost::unordered_flat_map<test::object, test::object, test::hash,
test::equal_to,
test::allocator1<std::pair<test::object const, test::object> > >* test_map;
boost::unordered_flat_set<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::propagate_move> >*
test_set_prop_move;
boost::unordered_flat_map<test::object, test::object, test::hash,
test::equal_to,
test::cxx11_allocator<std::pair<test::object const, test::object>,
test::propagate_move> >* test_map_prop_move;
boost::unordered_flat_set<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_move> >*
test_set_no_prop_move;
boost::unordered_flat_map<test::object, test::object, test::hash,
test::equal_to,
test::cxx11_allocator<std::pair<test::object const, test::object>,
test::no_propagate_move> >* test_map_no_prop_move;
UNORDERED_TEST(post_move_tests,
((test_set)(test_map)(test_set_prop_move)(test_map_prop_move)(test_set_no_prop_move)(test_map_no_prop_move))(
(default_generator)(generate_collisions)(limited_range)))
#else
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
std::allocator<std::pair<test::object const, test::object> > >*
test_map_std_alloc;
boost::unordered_set<test::object, test::hash, test::equal_to,
test::allocator2<test::object> >* test_set;
boost::unordered_multiset<test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
test::allocator1<std::pair<test::object const, test::object> > >* test_map;
boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to,
test::allocator2<std::pair<test::object const, test::object> > >*
test_multimap;
boost::unordered_set<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::propagate_move> >*
test_set_prop_move;
boost::unordered_multiset<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::propagate_move> >*
test_multiset_prop_move;
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
test::cxx11_allocator<std::pair<test::object const, test::object>,
test::propagate_move> >* test_map_prop_move;
boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to,
test::cxx11_allocator<std::pair<test::object const, test::object>,
test::propagate_move> >* test_multimap_prop_move;
boost::unordered_set<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_move> >*
test_set_no_prop_move;
boost::unordered_multiset<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_move> >*
test_multiset_no_prop_move;
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
test::cxx11_allocator<std::pair<test::object const, test::object>,
test::no_propagate_move> >* test_map_no_prop_move;
boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to,
test::cxx11_allocator<std::pair<test::object const, test::object>,
test::no_propagate_move> >* test_multimap_no_prop_move;
UNORDERED_TEST(post_move_tests,
((test_set)(test_multiset)(test_map)(test_multimap)(test_set_prop_move)(
test_multiset_prop_move)(test_map_prop_move)(test_multimap_prop_move)(
test_set_no_prop_move)(test_multiset_no_prop_move)(test_map_no_prop_move)(
test_multimap_no_prop_move))(
(default_generator)(generate_collisions)(limited_range)))
#endif
}
RUN_TESTS()

View File

@@ -1,14 +1,10 @@
// Copyright 2006-2009 Daniel James.
// Copyright 2022 Christian Mazakas.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// clang-format off
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
// clang-format on
#include "../helpers/unordered.hpp"
#include "../helpers/test.hpp"
#include "../helpers/random_values.hpp"
@@ -81,6 +77,305 @@ namespace rehash_tests {
BOOST_TEST(postcondition(x, 0));
}
template <class X> void rehash_empty_tracking(X*, test::random_generator)
{
// valid for all load factors
float const max_load_factors[] = {
0.5f, 1.0f, 1e6f, std::numeric_limits<float>::infinity()};
std::size_t const max_load_factors_len =
sizeof(max_load_factors) / sizeof(*max_load_factors);
for (std::size_t i = 0; i < max_load_factors_len; ++i) {
X x;
BOOST_TEST_EQ(x.size(), 0u);
BOOST_TEST_EQ(test::detail::tracker.count_allocations, 0u);
x.max_load_factor(max_load_factors[i]);
{
BOOST_TEST_EQ(x.bucket_count(), 0u);
x.rehash(0);
BOOST_TEST_EQ(x.bucket_count(), 0u);
BOOST_TEST_EQ(test::detail::tracker.count_allocations, 0u);
}
{
BOOST_TEST_EQ(x.bucket_count(), 0u);
x.rehash(1000);
BOOST_TEST_GE(x.bucket_count(), 1000u);
BOOST_TEST_GT(test::detail::tracker.count_allocations, 0u);
x.rehash(0);
BOOST_TEST_EQ(x.bucket_count(), 0u);
BOOST_TEST_EQ(test::detail::tracker.count_allocations, 0u);
}
{
BOOST_TEST_EQ(x.bucket_count(), 0u);
x.rehash(1000);
BOOST_TEST_GE(x.bucket_count(), 1000u);
BOOST_TEST_GT(test::detail::tracker.count_allocations, 0u);
x.rehash(10);
BOOST_TEST_GE(x.bucket_count(), 10u);
BOOST_TEST_LT(x.bucket_count(), 1000u);
BOOST_TEST_GT(test::detail::tracker.count_allocations, 0u);
}
{
BOOST_TEST_GT(x.bucket_count(), 0u);
BOOST_TEST_LT(x.bucket_count(), 1000u);
x.rehash(1000);
BOOST_TEST_GE(x.bucket_count(), 1000u);
BOOST_TEST_GT(test::detail::tracker.count_allocations, 0u);
x.rehash(0);
BOOST_TEST_EQ(x.bucket_count(), 0u);
BOOST_TEST_EQ(test::detail::tracker.count_allocations, 0u);
}
}
for (std::size_t i = 0; i < max_load_factors_len; ++i) {
typedef typename X::size_type size_type;
X x;
BOOST_TEST_EQ(x.size(), 0u);
BOOST_TEST_EQ(test::detail::tracker.count_allocations, 0u);
#ifdef BOOST_UNORDERED_FOA_TESTS
float const mlf = boost::unordered::detail::foa::mlf;
x.max_load_factor(max_load_factors[i]);
#else
float const mlf = max_load_factors[i];
x.max_load_factor(mlf);
#endif
{
BOOST_TEST_EQ(x.bucket_count(), 0u);
x.reserve(0);
BOOST_TEST_EQ(x.bucket_count(), 0u);
BOOST_TEST_EQ(test::detail::tracker.count_allocations, 0u);
}
{
BOOST_TEST_EQ(x.bucket_count(), 0u);
x.reserve(1000);
BOOST_TEST_GE(
x.bucket_count(), static_cast<size_type>(std::ceil(1000 / mlf)));
BOOST_TEST_GT(test::detail::tracker.count_allocations, 0u);
x.reserve(0);
BOOST_TEST_EQ(x.bucket_count(), 0u);
BOOST_TEST_EQ(test::detail::tracker.count_allocations, 0u);
}
{
BOOST_TEST_EQ(x.bucket_count(), 0u);
x.reserve(1000);
BOOST_TEST_GE(
x.bucket_count(), static_cast<size_type>(std::ceil(1000 / mlf)));
BOOST_TEST_GT(test::detail::tracker.count_allocations, 0u);
x.reserve(10);
BOOST_TEST_GE(
x.bucket_count(), static_cast<size_type>(std::ceil(10 / mlf)));
BOOST_TEST_LT(x.bucket_count(), 1000u);
BOOST_TEST_GT(test::detail::tracker.count_allocations, 0u);
}
{
BOOST_TEST_GT(x.bucket_count(), 0u);
BOOST_TEST_LT(x.bucket_count(), 1000u);
x.reserve(1000);
BOOST_TEST_GE(
x.bucket_count(), static_cast<size_type>(std::ceil(1000 / mlf)));
BOOST_TEST_GT(test::detail::tracker.count_allocations, 0u);
x.reserve(0);
BOOST_TEST_EQ(x.bucket_count(), 0u);
BOOST_TEST_EQ(test::detail::tracker.count_allocations, 0u);
}
}
}
template <class X>
void rehash_nonempty_tracking(X*, test::random_generator generator)
{
test::random_values<X> const v(1000, generator);
typedef typename X::size_type size_type;
float const max_load_factors[] = {0.5f, 1.0f, 1e2f};
size_type const max_load_factors_len =
sizeof(max_load_factors) / sizeof(*max_load_factors);
for (size_type i = 0; i < max_load_factors_len; ++i) {
float const mlf = max_load_factors[i];
X x(v.begin(), v.end());
BOOST_TEST_GT(x.size(), 0u);
BOOST_TEST_GT(test::detail::tracker.count_allocations, 0u);
x.max_load_factor(mlf);
size_type bucket_count = x.bucket_count();
{
BOOST_TEST_GT(x.bucket_count(), 0u);
x.rehash(0);
BOOST_TEST_GE(x.bucket_count(),
static_cast<size_type>(
std::floor(static_cast<float>(x.size()) / x.max_load_factor())));
BOOST_TEST_GT(test::detail::tracker.count_allocations, 0u);
bucket_count = x.bucket_count();
}
{
BOOST_TEST_GT(bucket_count, 0u);
x.rehash(2 * x.bucket_count());
BOOST_TEST_GT(x.bucket_count(), bucket_count);
bucket_count = x.bucket_count();
}
{
float const old_mlf = x.max_load_factor();
BOOST_TEST_GT(bucket_count, 0u);
x.rehash(bucket_count / 4);
BOOST_TEST_LT(x.bucket_count(), bucket_count);
x.max_load_factor(std::numeric_limits<float>::infinity());
x.rehash(0);
BOOST_TEST_GT(x.bucket_count(), 0u);
x.max_load_factor(old_mlf);
}
{
std::size_t const max_load =
static_cast<std::size_t>(static_cast<double>(x.max_load_factor()) *
static_cast<double>(x.bucket_count()));
while (x.size() < max_load) {
test::random_values<X> const t(max_load, generator);
typename test::random_values<X>::const_iterator pos = t.begin();
typename test::random_values<X>::const_iterator end = t.end();
for (; pos != end; ++pos) {
x.insert(*pos);
if (x.size() == max_load) {
break;
}
}
}
while (x.size() > max_load) {
x.erase(x.begin());
}
BOOST_TEST_EQ(x.size(), max_load);
bucket_count = x.bucket_count();
x.rehash(x.bucket_count());
BOOST_TEST_EQ(x.bucket_count(), bucket_count);
}
}
for (size_type i = 0; i < max_load_factors_len; ++i) {
X x(v.begin(), v.end());
BOOST_TEST_GT(x.size(), 0u);
BOOST_TEST_GT(test::detail::tracker.count_allocations, 0u);
float const mlf = max_load_factors[i];
x.max_load_factor(mlf);
size_type bucket_count = x.bucket_count();
{
BOOST_TEST_GT(x.bucket_count(), 0u);
x.reserve(0);
BOOST_TEST_GE(x.bucket_count(),
static_cast<size_type>(
std::floor(static_cast<float>(x.size()) / x.max_load_factor())));
BOOST_TEST_GT(test::detail::tracker.count_allocations, 0u);
bucket_count = x.bucket_count();
}
{
BOOST_TEST_GT(x.bucket_count(), 0u);
x.reserve(
2 * (static_cast<size_type>(
std::floor(static_cast<float>(x.size()) / x.max_load_factor()) +
std::floor(static_cast<float>(x.size()) * x.max_load_factor()))));
BOOST_TEST_GT(x.bucket_count(), bucket_count);
bucket_count = x.bucket_count();
BOOST_TEST_GT(bucket_count, 1u);
}
{
float const old_mlf = x.max_load_factor();
BOOST_TEST_GT(bucket_count, 4u);
x.reserve(bucket_count / 4);
BOOST_TEST_LT(x.bucket_count(), bucket_count);
x.max_load_factor(std::numeric_limits<float>::infinity());
x.reserve(0);
BOOST_TEST_GT(x.bucket_count(), 0u);
x.max_load_factor(old_mlf);
}
{
std::size_t const max_load =
static_cast<std::size_t>(static_cast<double>(x.max_load_factor()) *
static_cast<double>(x.bucket_count()));
while (x.size() < max_load) {
test::random_values<X> const t(max_load, generator);
typename test::random_values<X>::const_iterator pos = t.begin();
typename test::random_values<X>::const_iterator end = t.end();
for (; pos != end; ++pos) {
x.insert(*pos);
if (x.size() == max_load) {
break;
}
}
}
while (x.size() > max_load) {
x.erase(x.begin());
}
BOOST_TEST_EQ(x.size(), max_load);
bucket_count = x.bucket_count();
x.reserve(x.size());
BOOST_TEST_EQ(x.bucket_count(), bucket_count);
}
}
}
template <class X> void rehash_test1(X*, test::random_generator generator)
{
test::random_values<X> v(1000, generator);
@@ -125,6 +420,15 @@ namespace rehash_tests {
X x;
x.max_load_factor(0.25);
#ifdef BOOST_UNORDERED_FOA_TESTS
x.reserve(10000);
BOOST_TEST(x.bucket_count() >= 10000);
x.reserve(0);
x.reserve(10000000);
BOOST_TEST(x.bucket_count() >= 10000000);
#else
x.reserve(10000);
BOOST_TEST(x.bucket_count() >= 40000);
@@ -132,6 +436,7 @@ namespace rehash_tests {
x.reserve(10000000);
BOOST_TEST(x.bucket_count() >= 40000000);
#endif
}
template <class X> void reserve_test1(X*, test::random_generator generator)
@@ -192,6 +497,47 @@ namespace rehash_tests {
}
}
using test::default_generator;
using test::generate_collisions;
using test::limited_range;
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_set<int>* int_set_ptr;
boost::unordered_flat_map<test::movable, test::movable, test::hash,
test::equal_to, test::allocator2<test::movable> >* test_map_ptr;
boost::unordered_flat_set<test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_set_tracking;
boost::unordered_flat_map<test::object, test::object, test::hash,
test::equal_to,
test::allocator1<std::pair<test::object const, test::object> > >*
test_map_tracking;
UNORDERED_TEST(rehash_empty_test1, ((int_set_ptr)(test_map_ptr)))
UNORDERED_TEST(rehash_empty_test2,
((int_set_ptr)(test_map_ptr))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(rehash_empty_test3,
((int_set_ptr)(test_map_ptr))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(
rehash_test1, ((int_set_ptr)(test_map_ptr))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(reserve_empty_test1, ((int_set_ptr)(test_map_ptr)))
UNORDERED_TEST(reserve_empty_test2, ((int_set_ptr)(test_map_ptr)))
UNORDERED_TEST(
reserve_test1, ((int_set_ptr)(test_map_ptr))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(
reserve_test2, ((int_set_ptr)(test_map_ptr))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(rehash_empty_tracking,
((test_set_tracking)(test_map_tracking))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(rehash_nonempty_tracking,
((test_set_tracking)(test_map_tracking))(
(default_generator)(generate_collisions)(limited_range)))
#else
boost::unordered_set<int>* int_set_ptr;
boost::unordered_multiset<test::object, test::hash, test::equal_to,
test::allocator2<test::object> >* test_multiset_ptr;
@@ -199,9 +545,17 @@ namespace rehash_tests {
test::allocator2<test::movable> >* test_map_ptr;
boost::unordered_multimap<int, int>* int_multimap_ptr;
using test::default_generator;
using test::generate_collisions;
using test::limited_range;
boost::unordered_set<test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_set_tracking;
boost::unordered_multiset<test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_multiset_tracking;
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
test::allocator1<std::pair<test::object const, test::object> > >*
test_map_tracking;
boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to,
test::allocator1<std::pair<test::object const, test::object> > >*
test_multimap_tracking;
UNORDERED_TEST(rehash_empty_test1,
((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr)))
@@ -224,6 +578,13 @@ namespace rehash_tests {
UNORDERED_TEST(reserve_test2,
((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(rehash_empty_tracking,
((test_set_tracking)(test_multiset_tracking)(test_map_tracking)(test_multimap_tracking))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(rehash_nonempty_tracking,
((test_set_tracking)(test_multiset_tracking)(test_map_tracking)(test_multimap_tracking))(
(default_generator)(generate_collisions)(limited_range)))
#endif
}
RUN_TESTS()

View File

@@ -2,12 +2,7 @@
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// clang-format off
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
// clang-format on
#include "../helpers/unordered.hpp"
#include "../helpers/test.hpp"
@@ -113,8 +108,8 @@ template <class UnorderedContainer> void reserve_tests()
s.max_load_factor(0.37f);
s.reserve(count);
std::size_t expected_bucket_count =
static_cast<std::size_t>(std::ceil(static_cast<float>(count) / 0.37f));
std::size_t expected_bucket_count = static_cast<std::size_t>(
std::ceil(static_cast<float>(count) / s.max_load_factor()));
BOOST_TEST_GE(total_allocation, expected_bucket_count * sizeof(void*));
BOOST_TEST_GE(s.bucket_count(), expected_bucket_count);
@@ -173,6 +168,12 @@ template <class UnorderedContainer> void rehash_tests()
// note, the test is vulnerable to cases where the next calculated bucket
// count can exceed `prev_count + count`
//
#ifdef BOOST_UNORDERED_FOA_TESTS
BOOST_TEST_LT(s.bucket_count(), prev_count + count);
BOOST_TEST_LE(total_allocation,
(prev_count + count) * sizeof(typename UnorderedContainer::value_type) +
((prev_count + count) / 15 + 1) * 16);
#else
std::size_t const estimated_bucket_group_size =
3 * sizeof(void*) + sizeof(std::size_t);
std::size_t const estimated_bucket_groups =
@@ -182,6 +183,7 @@ template <class UnorderedContainer> void rehash_tests()
BOOST_TEST_LE(total_allocation,
(prev_count + count) * sizeof(void*) +
estimated_bucket_group_size * estimated_bucket_groups);
#endif
}
BOOST_TEST_GT(num_allocations, 0u);
@@ -214,6 +216,28 @@ UNORDERED_AUTO_TEST (unordered_set_reserve) {
BOOST_ASSERT(A<int>(b) == a);
}
#ifdef BOOST_UNORDERED_FOA_TESTS
typedef boost::unordered_flat_set<int*, boost::hash<int*>,
std::equal_to<int*>, A<int*> >
unordered_set;
typedef boost::unordered_flat_map<int*, int*, boost::hash<int*>,
std::equal_to<int*>, A<std::pair<int const*, int*> > >
unordered_map;
bucket_count_constructor<unordered_set>();
bucket_count_constructor<unordered_map>();
range_bucket_constructor<unordered_set>();
range_bucket_constructor<unordered_map>();
reserve_tests<unordered_set>();
reserve_tests<unordered_map>();
rehash_tests<unordered_set>();
rehash_tests<unordered_map>();
#else
typedef boost::unordered_set<int, boost::hash<int>, std::equal_to<int>,
A<int> >
unordered_set;
@@ -249,6 +273,7 @@ UNORDERED_AUTO_TEST (unordered_set_reserve) {
rehash_tests<unordered_map>();
rehash_tests<unordered_multiset>();
rehash_tests<unordered_multimap>();
#endif
}
RUN_TESTS()

View File

@@ -2,14 +2,8 @@
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// clang-format off
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
// clang-format on
#include "../helpers/test.hpp"
#include "../helpers/unordered.hpp"
#include "../objects/test.hpp"
#include <memory>
@@ -107,8 +101,7 @@ public:
// ever using it with an int with has a trivial destructor so it eliminates
// the code and generates a warning about an unused variable
//
template <class U>
void destroy(U* p)
template <class U> void destroy(U* p)
{
(void)p;
p->~U();
@@ -192,8 +185,7 @@ public:
// ever using it with an int with has a trivial destructor so it eliminates
// the code and generates a warning about an unused variable
//
template <class U>
void destroy(U* p)
template <class U> void destroy(U* p)
{
(void)p;
p->~U();
@@ -224,13 +216,15 @@ template <class C1, class C2> void scary_test()
typename C2::const_iterator cbegin(x.cbegin());
BOOST_TEST(cbegin == x.cend());
BOOST_ASSERT(x.bucket_count() > 0);
BOOST_TEST_EQ(x.bucket_count(), 0u);
#ifndef BOOST_UNORDERED_FOA_TESTS
typename C2::local_iterator lbegin(x.begin(0));
BOOST_TEST(lbegin == x.end(0));
typename C2::const_local_iterator clbegin(x.cbegin(0));
BOOST_TEST(clbegin == x.cend(0));
#endif
}
template <
@@ -316,11 +310,16 @@ void set_scary_test()
}
UNORDERED_AUTO_TEST (scary_tests) {
#ifdef BOOST_UNORDERED_FOA_TESTS
map_scary_test<boost::unordered_flat_map>();
set_scary_test<boost::unordered_flat_set>();
#else
map_scary_test<boost::unordered_map>();
map_scary_test<boost::unordered_multimap>();
set_scary_test<boost::unordered_set>();
set_scary_test<boost::unordered_multiset>();
#endif
}
RUN_TESTS()

View File

@@ -19,12 +19,7 @@ int main() {}
// https://github.com/boostorg/unordered/issues/22
//
// clang-format off
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
// clang-format on
#include "../helpers/unordered.hpp"
#include "../helpers/test.hpp"
@@ -32,10 +27,10 @@ int main() {}
#include <boost/core/ignore_unused.hpp>
#include <scoped_allocator>
#include <string>
#include <utility>
#include <vector>
#include <scoped_allocator>
namespace test {
template <class T> struct allocator
@@ -70,9 +65,15 @@ typedef std::scoped_allocator_adaptor<test::allocator<pair_type>,
test::allocator<boost::uint64_t> >
allocator_type;
#ifdef BOOST_UNORDERED_FOA_TESTS
typedef boost::unordered_flat_map<const boost::uint64_t, vector_type,
boost::hash<boost::uint64_t>, std::equal_to<boost::uint64_t>, allocator_type>
map_type;
#else
typedef boost::unordered_map<const boost::uint64_t, vector_type,
boost::hash<boost::uint64_t>, std::equal_to<boost::uint64_t>, allocator_type>
map_type;
#endif
UNORDERED_AUTO_TEST (scoped_allocator) {
allocator_type alloc(

View File

@@ -1,16 +1,12 @@
// Copyright 2006-2009 Daniel James.
// Copyright 2022 Christian Mazakas.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// This test checks the runtime requirements of containers.
// clang-format off
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
// clang-format on
#include "../helpers/unordered.hpp"
#include "../helpers/test.hpp"
#include <cstdlib>
@@ -93,7 +89,11 @@ UNORDERED_AUTO_TEST (simple_tests) {
srand(14878);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_set.\n";
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_set<int> set;
#else
boost::unordered_set<int> set;
#endif
simple_test(set);
set.insert(1);
@@ -101,6 +101,7 @@ UNORDERED_AUTO_TEST (simple_tests) {
set.insert(1456);
simple_test(set);
#ifndef BOOST_UNORDERED_FOA_TESTS
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multiset.\n";
boost::unordered_multiset<int> multiset;
simple_test(multiset);
@@ -111,15 +112,21 @@ UNORDERED_AUTO_TEST (simple_tests) {
multiset.insert(index);
}
simple_test(multiset);
#endif
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_map.\n";
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_map<int, int> map;
#else
boost::unordered_map<int, int> map;
#endif
for (int i2 = 0; i2 < 1000; ++i2) {
map.insert(std::pair<const int, int>(rand(), rand()));
}
simple_test(map);
#ifndef BOOST_UNORDERED_FOA_TESTS
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multimap.\n";
boost::unordered_multimap<int, int> multimap;
@@ -129,6 +136,7 @@ UNORDERED_AUTO_TEST (simple_tests) {
multimap.insert(std::pair<const int, int>(index, rand()));
}
simple_test(multimap);
#endif
}
RUN_TESTS()

View File

@@ -1,14 +1,10 @@
// Copyright 2006-2009 Daniel James.
// Copyright 2022 Christian Mazakas.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// clang-format off
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
// clang-format on
#include "../helpers/unordered.hpp"
#include <boost/config.hpp>
#include <algorithm>
@@ -139,6 +135,53 @@ namespace swap_tests {
}
}
using test::default_generator;
using test::generate_collisions;
using test::limited_range;
template <typename T> bool is_propagate(T*)
{
return T::allocator_type::is_propagate_on_swap;
}
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_map<test::object, test::object, test::hash,
test::equal_to, std::allocator<test::object> >* test_map_std_alloc;
boost::unordered_flat_set<test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_set;
boost::unordered_flat_map<test::object, test::object, test::hash,
test::equal_to, test::allocator1<test::object> >* test_map;
boost::unordered_flat_set<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::propagate_swap> >*
test_set_prop_swap;
boost::unordered_flat_map<test::object, test::object, test::hash,
test::equal_to, test::cxx11_allocator<test::object, test::propagate_swap> >*
test_map_prop_swap;
boost::unordered_flat_set<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_swap> >*
test_set_no_prop_swap;
boost::unordered_flat_map<test::object, test::object, test::hash,
test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_swap> >*
test_map_no_prop_swap;
UNORDERED_AUTO_TEST (check_traits) {
BOOST_TEST(!is_propagate(test_set));
BOOST_TEST(is_propagate(test_set_prop_swap));
BOOST_TEST(!is_propagate(test_set_no_prop_swap));
}
UNORDERED_TEST(swap_tests1,
((test_map_std_alloc)(test_set)(test_map)(test_set_prop_swap)(test_map_prop_swap)(test_set_no_prop_swap)(test_map_no_prop_swap))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(swap_tests2,
((test_set)(test_map)(test_set_prop_swap)(test_map_prop_swap)(test_set_no_prop_swap)(test_map_no_prop_swap))(
(default_generator)(generate_collisions)(limited_range)))
#else
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
std::allocator<test::object> >* test_map_std_alloc;
@@ -178,15 +221,6 @@ namespace swap_tests {
test::cxx11_allocator<test::object, test::no_propagate_swap> >*
test_multimap_no_prop_swap;
template <typename T> bool is_propagate(T*)
{
return T::allocator_type::is_propagate_on_swap;
}
using test::default_generator;
using test::generate_collisions;
using test::limited_range;
UNORDERED_AUTO_TEST (check_traits) {
BOOST_TEST(!is_propagate(test_set));
BOOST_TEST(is_propagate(test_set_prop_swap));
@@ -207,5 +241,6 @@ namespace swap_tests {
test_set_no_prop_swap)(test_multiset_no_prop_swap)(test_map_no_prop_swap)(
test_multimap_no_prop_swap))(
(default_generator)(generate_collisions)(limited_range)))
#endif
}
RUN_TESTS()

View File

@@ -2,12 +2,7 @@
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// clang-format off
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
// clang-format on
#include "../helpers/unordered.hpp"
#include "../helpers/test.hpp"
@@ -1053,14 +1048,25 @@ template <class UnorderedMap> struct convertible_to_const_iterator
}
};
#ifdef BOOST_UNORDERED_FOA_TESTS
typedef boost::unordered_flat_map<int, int, transparent_hasher,
transparent_key_equal>
transparent_unordered_map;
#else
typedef boost::unordered_map<int, int, transparent_hasher,
transparent_key_equal>
transparent_unordered_map;
#endif
// test that in the presence of the member function template `erase()`, we still
// invoke the correct iterator overloads when the type is implicitly convertible
//
transparent_unordered_map::iterator map_erase_overload_compile_test()
#ifdef BOOST_UNORDERED_FOA_TESTS
void
#else
transparent_unordered_map::iterator
#endif
map_erase_overload_compile_test()
{
convertible_to_iterator<transparent_unordered_map> c;
transparent_unordered_map map;
@@ -1069,7 +1075,11 @@ transparent_unordered_map::iterator map_erase_overload_compile_test()
return map.erase(c);
}
#ifdef BOOST_UNORDERED_FOA_TESTS
void
#else
transparent_unordered_map::const_iterator
#endif
map_erase_const_overload_compile_test()
{
convertible_to_const_iterator<transparent_unordered_map> c;
@@ -1079,6 +1089,7 @@ map_erase_const_overload_compile_test()
return map.erase(c);
}
#ifndef BOOST_UNORDERED_FOA_TESTS
typedef boost::unordered_multimap<int, int, transparent_hasher,
transparent_key_equal>
transparent_unordered_multimap;
@@ -1101,6 +1112,7 @@ multimap_erase_const_overload_compile_test()
pos = c;
return map.erase(c);
}
#endif
template <class UnorderedMap> void test_map_transparent_erase()
{
@@ -1197,14 +1209,25 @@ template <class UnorderedMap> void test_map_non_transparent_erase()
BOOST_TEST_EQ(key::count_, key_count);
}
#if BOOST_UNORDERED_FOA_TESTS
typedef boost::unordered_flat_set<int, transparent_hasher,
transparent_key_equal>
transparent_unordered_set;
#else
typedef boost::unordered_set<int, transparent_hasher, transparent_key_equal>
transparent_unordered_set;
typedef boost::unordered_multiset<int, transparent_hasher,
transparent_key_equal>
transparent_unordered_multiset;
#endif
transparent_unordered_set::iterator set_erase_overload_compile_test()
#ifdef BOOST_UNORDERED_FOA_TESTS
void
#else
transparent_unordered_set::iterator
#endif
set_erase_overload_compile_test()
{
convertible_to_iterator<transparent_unordered_set> c;
transparent_unordered_set set;
@@ -1213,7 +1236,11 @@ transparent_unordered_set::iterator set_erase_overload_compile_test()
return set.erase(c);
}
#ifdef BOOST_UNORDERED_FOA_TESTS
void
#else
transparent_unordered_set::const_iterator
#endif
set_erase_const_overload_compile_test()
{
convertible_to_const_iterator<transparent_unordered_set> c;
@@ -1223,6 +1250,7 @@ set_erase_const_overload_compile_test()
return set.erase(c);
}
#ifndef BOOST_UNORDERED_FOA_TESTS
transparent_unordered_multiset::iterator multiset_erase_overload_compile_test()
{
convertible_to_iterator<transparent_unordered_multiset> c;
@@ -1241,6 +1269,7 @@ multiset_erase_const_overload_compile_test()
pos = c;
return set.erase(c);
}
#endif
template <class UnorderedSet> void test_set_transparent_erase()
{
@@ -1337,6 +1366,7 @@ template <class UnorderedSet> void test_set_non_transparent_erase()
BOOST_TEST_EQ(key::count_, key_count);
}
#ifndef BOOST_UNORDERED_FOA_TESTS
// test that in the presence of the member function template `extract()`, we
// still invoke the correct iterator overloads when the type is implicitly
// convertible
@@ -1359,9 +1389,11 @@ multimap_extract_const_overload_compile_test()
pos = c;
return map.extract(c);
}
#endif
template <class UnorderedMap> void test_map_transparent_extract()
{
#ifndef BOOST_UNORDERED_FOA_TESTS
typedef typename UnorderedMap::node_type node_type;
typedef typename UnorderedMap::const_iterator const_iterator;
typedef std::pair<const_iterator, const_iterator> const_iterator_pair;
@@ -1397,10 +1429,12 @@ template <class UnorderedMap> void test_map_transparent_extract()
BOOST_TEST(nh.empty());
BOOST_TEST_EQ(key::count_, expected_key_count);
#endif
}
template <class UnorderedMap> void test_map_non_transparent_extract()
{
#ifndef BOOST_UNORDERED_FOA_TESTS
typedef typename UnorderedMap::node_type node_type;
typedef typename UnorderedMap::const_iterator const_iterator;
typedef std::pair<const_iterator, const_iterator> const_iterator_pair;
@@ -1441,8 +1475,10 @@ template <class UnorderedMap> void test_map_non_transparent_extract()
++key_count;
BOOST_TEST(nh.empty());
BOOST_TEST_EQ(key::count_, key_count);
#endif
}
#ifndef BOOST_UNORDERED_FOA_TESTS
transparent_unordered_set::node_type set_extract_overload_compile_test()
{
convertible_to_iterator<transparent_unordered_set> c;
@@ -1480,9 +1516,11 @@ multiset_extract_const_overload_compile_test()
pos = c;
return set.extract(c);
}
#endif
template <class UnorderedSet> void test_set_transparent_extract()
{
#ifndef BOOST_UNORDERED_FOA_TESTS
typedef typename UnorderedSet::node_type node_type;
count_reset();
@@ -1526,10 +1564,12 @@ template <class UnorderedSet> void test_set_transparent_extract()
BOOST_TEST_EQ(set.size(), set_size);
BOOST_TEST_EQ(key::count_, expected_key_count);
#endif
}
template <class UnorderedSet> void test_set_non_transparent_extract()
{
#ifndef BOOST_UNORDERED_FOA_TESTS
typedef typename UnorderedSet::node_type node_type;
count_reset();
@@ -1583,13 +1623,22 @@ template <class UnorderedSet> void test_set_non_transparent_extract()
BOOST_TEST_EQ(set.size(), set_size);
BOOST_TEST_EQ(key::count_, key_count);
#endif
}
template <class Key, class T, class Hash, class KeyEqual> struct map_type
{
#ifdef BOOST_UNORDERED_FOA_TESTS
typedef boost::unordered_flat_map<Key, T, Hash, KeyEqual> type;
#else
typedef boost::unordered_map<Key, T, Hash, KeyEqual> type;
#endif
};
void test_unordered_map()
{
{
typedef boost::unordered_map<key, int, transparent_hasher,
transparent_key_equal>
typedef map_type<key, int, transparent_hasher, transparent_key_equal>::type
unordered_map;
test_map_transparent_count<unordered_map>();
@@ -1602,7 +1651,7 @@ void test_unordered_map()
{
// non-transparent Hash, non-transparent KeyEqual
//
typedef boost::unordered_map<key, int, hasher, key_equal> unordered_map;
typedef map_type<key, int, hasher, key_equal>::type unordered_map;
test_map_non_transparent_count<unordered_map>();
test_map_non_transparent_find<unordered_map>();
@@ -1614,7 +1663,7 @@ void test_unordered_map()
{
// transparent Hash, non-transparent KeyEqual
//
typedef boost::unordered_map<key, int, transparent_hasher, key_equal>
typedef map_type<key, int, transparent_hasher, key_equal>::type
unordered_map;
test_map_non_transparent_count<unordered_map>();
@@ -1627,7 +1676,7 @@ void test_unordered_map()
{
// non-transparent Hash, transparent KeyEqual
//
typedef boost::unordered_map<key, int, hasher, transparent_key_equal>
typedef map_type<key, int, hasher, transparent_key_equal>::type
unordered_map;
test_map_non_transparent_count<unordered_map>();
@@ -1638,6 +1687,7 @@ void test_unordered_map()
}
}
#ifndef BOOST_UNORDERED_FOA_TESTS
void test_unordered_multimap()
{
{
@@ -1691,11 +1741,21 @@ void test_unordered_multimap()
test_map_non_transparent_extract<unordered_multimap>();
}
}
#endif
template <class Key, class Hash, class KeyEqual> struct set_type
{
#ifdef BOOST_UNORDERED_FOA_TESTS
typedef boost::unordered_flat_set<Key, Hash, KeyEqual> type;
#else
typedef boost::unordered_set<Key, Hash, KeyEqual> type;
#endif
};
void test_unordered_set()
{
{
typedef boost::unordered_set<key, transparent_hasher, transparent_key_equal>
typedef set_type<key, transparent_hasher, transparent_key_equal>::type
unordered_set;
test_set_transparent_count<unordered_set>();
@@ -1708,7 +1768,7 @@ void test_unordered_set()
{
// non-transparent Hash, non-transparent KeyEqual
//
typedef boost::unordered_set<key, hasher, key_equal> unordered_set;
typedef set_type<key, hasher, key_equal>::type unordered_set;
test_set_non_transparent_count<unordered_set>();
test_set_non_transparent_find<unordered_set>();
@@ -1720,8 +1780,7 @@ void test_unordered_set()
{
// transparent Hash, non-transparent KeyEqual
//
typedef boost::unordered_set<key, transparent_hasher, key_equal>
unordered_set;
typedef set_type<key, transparent_hasher, key_equal>::type unordered_set;
test_set_non_transparent_count<unordered_set>();
test_set_non_transparent_find<unordered_set>();
@@ -1733,8 +1792,7 @@ void test_unordered_set()
{
// non-transparent Hash, transparent KeyEqual
//
typedef boost::unordered_set<key, hasher, transparent_key_equal>
unordered_set;
typedef set_type<key, hasher, transparent_key_equal>::type unordered_set;
test_set_non_transparent_count<unordered_set>();
test_set_non_transparent_find<unordered_set>();
@@ -1744,6 +1802,7 @@ void test_unordered_set()
}
}
#ifndef BOOST_UNORDERED_FOA_TESTS
void test_unordered_multiset()
{
{
@@ -1796,12 +1855,16 @@ void test_unordered_multiset()
test_set_non_transparent_extract<unordered_set>();
}
}
#endif
UNORDERED_AUTO_TEST (transparent_ops) {
test_unordered_map();
test_unordered_multimap();
test_unordered_set();
#ifndef BOOST_UNORDERED_FOA_TESTS
test_unordered_multimap();
test_unordered_multiset();
#endif
}
RUN_TESTS()