Compare commits

..

298 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
52 changed files with 5925 additions and 915 deletions
+32 -4
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,14 +76,37 @@ 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
File diff suppressed because it is too large Load Diff
@@ -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>
@@ -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
@@ -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
+75
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
+44
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
@@ -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
@@ -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
@@ -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
@@ -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
+53
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 ;
+24 -6
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
+73 -4
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"
@@ -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[]
@@ -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()
+49 -4
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()
+5
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"
+15
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
}
}
+22
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
+2 -1
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
+59 -15
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"
@@ -201,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;
@@ -241,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));
@@ -271,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());
@@ -291,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};
+7 -5
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;
+94 -5
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()
+127 -9
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()
+61
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:
+41 -10
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"
@@ -497,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;
@@ -509,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)))
@@ -528,12 +549,17 @@ namespace constructor_tests {
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());
}
@@ -542,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());
}
+38 -8
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()
+38 -21
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"
@@ -229,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,
@@ -264,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()
+128 -16
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);
+38 -16
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);
+12 -7
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()
+10 -57
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()
+37 -10
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()
+17 -10
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()
+37
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()
+45 -1
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()
+41 -8
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
+244
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();
}
+12 -7
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);
+130 -16
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,
+16 -6
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
+19 -6
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
+28 -10
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()
+87 -7
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()
+83 -528
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"
@@ -71,7 +67,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);
#endif
test::check_equivalent_keys(y);
#if defined(BOOST_UNORDERED_USE_MOVE) || \
!defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
@@ -146,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);
}
@@ -162,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);
}
@@ -192,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);
}
}
@@ -215,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
@@ -240,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
@@ -268,7 +288,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.25);
#endif
if (BOOST_UNORDERED_TEST_MOVING
? (bool)allocator_type::is_propagate_on_move
@@ -296,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
@@ -332,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
@@ -344,519 +376,51 @@ namespace move_tests {
}
}
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>,
extract<T>,
merge<T>,
erase_with_pred<T>,
container_swap<T>,
buckets<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);
BOOST_TEST_NOT(y.empty());
BOOST_TEST(y.begin() != y.end());
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);
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_TEST_NOT(y.empty());
BOOST_TEST(y.begin() != y.end());
#endif
} else {
BOOST_TEST_NOT(y.empty());
BOOST_TEST(y.begin() != y.end());
}
fps[i](y, v);
test::check_container(x, v);
test::check_equivalent_keys(x);
}
}
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;
@@ -900,10 +464,6 @@ namespace move_tests {
test::cxx11_allocator<std::pair<test::object const, test::object>,
test::no_propagate_move> >* test_multimap_no_prop_move;
using test::default_generator;
using test::generate_collisions;
using test::limited_range;
UNORDERED_TEST(move_construct_tests1,
((test_map_std_alloc)(test_set)(test_multiset)(test_map)(test_multimap)(
test_set_prop_move)(test_multiset_prop_move)(test_map_prop_move)(
@@ -930,12 +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)))
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()
+45 -8
View File
@@ -1,14 +1,10 @@
// 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"
@@ -202,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<
@@ -210,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);
@@ -310,8 +328,14 @@ namespace noexcept_tests {
}
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);
@@ -410,6 +434,20 @@ UNORDERED_AUTO_TEST (prelim_allocator_checks) {
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;
@@ -418,9 +456,8 @@ boost::unordered_set<int, noexcept_tests::hash_nothrow_move_assign,
noexcept_tests::equal_to_nothrow_move_assign, allocator2<int> >*
throwing_set_alloc2;
using test::default_generator;
UNORDERED_TEST(test_nothrow_move_assign_when_noexcept,
((throwing_set_alloc1)(throwing_set_alloc2))((default_generator)))
#endif
RUN_TESTS()
+666
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()
+59 -10
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"
@@ -151,8 +147,13 @@ namespace rehash_tests {
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);
@@ -419,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);
@@ -426,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)
@@ -486,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;
@@ -505,10 +557,6 @@ namespace rehash_tests {
test::allocator1<std::pair<test::object const, test::object> > >*
test_multimap_tracking;
using test::default_generator;
using test::generate_collisions;
using test::limited_range;
UNORDERED_TEST(rehash_empty_test1,
((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr)))
UNORDERED_TEST(rehash_empty_test2,
@@ -536,6 +584,7 @@ namespace rehash_tests {
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()
+33 -8
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()
+10 -11
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();
@@ -226,11 +218,13 @@ template <class C1, class C2> void scary_test()
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()
+8 -7
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(
+14 -6
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()
+50 -15
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()
+83 -20
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()