Compare commits

...

110 Commits

Author SHA1 Message Date
Christian Mazakas e8af8dcc7d Simplify group14::overflow() implementation, update code to use group15 on non-SSE2 targets 2023-03-09 11:18:36 -08:00
Christian Mazakas ef791cbafd Update reserve_tests for new group layout 2023-03-08 15:34:15 -08:00
Christian Mazakas b49fa571fb Add group14 prototype 2023-03-08 15:34:06 -08:00
joaquintides 1bf193b8fc updated release notes 2023-03-06 21:46:42 +01:00
joaquintides 7faec20f26 Merge branch 'feature/foa_fast_iteration' of https://github.com/boostorg/unordered into feature/foa_fast_iteration 2023-03-06 21:44:55 +01:00
joaquintides ced8b45add fixed UB with begin when using fast iteration 2023-03-06 12:44:10 -08:00
joaquintides 15c9bc40f7 added fast table_iterator::increment variant for regular-layout groups 2023-03-06 12:44:10 -08:00
joaquintides 9aedb95296 Merge pull request #185 from boostorg/fix/uses-allocator 2023-03-06 21:38:13 +01:00
Christian Mazakas e56cb4418c Remove extraneous information from TypePolicy's construct, destroy docs 2023-03-06 09:48:26 -08:00
Christian Mazakas 1ae21c6d1a Remove extraneous typedef from destroy_on_exit 2023-03-06 09:47:33 -08:00
Peter Dimov 82acad3794 Increase GHA timeout to 180 minutes 2023-03-06 17:04:06 +02:00
joaquintides c50461528c fixed UB with begin when using fast iteration 2023-03-06 13:50:25 +01:00
joaquintides bd08e49255 added fast table_iterator::increment variant for regular-layout groups 2023-03-06 11:56:49 +01:00
Peter Dimov dbba3cec7b Add C++03 deprecation notice 2023-03-06 09:43:45 +02:00
Christian Mazakas 6c5b5b3186 Update comments on type policy to include changes to construct, destroy and move 2023-03-03 11:33:32 -08:00
Christian Mazakas 47dd02a4b3 Add bugfix notes to release notes 2023-03-03 11:18:41 -08:00
Christian Mazakas 8429d1a6aa Refactor node_handle to directly store element_type by modularizing and extending it 2023-03-03 11:17:38 -08:00
Christian Mazakas 86d3f9f632 Refactor move(init_type&) to handle defects in C++20 versions of libstdc++ for gcc versions <=12 2023-03-03 11:17:38 -08:00
Christian Mazakas 48e92afd92 Refactor drop_guard into destroy_on_exit 2023-03-03 11:17:38 -08:00
Christian Mazakas 5a5c31de35 Rename storage to uninitialized_storage 2023-03-03 11:17:38 -08:00
Christian Mazakas 088941dc7b Clean up usage of Allocators for flat containers 2023-03-03 11:17:38 -08:00
Christian Mazakas 5f6f1691e5 Format node_map 2023-03-03 11:17:38 -08:00
Christian Mazakas 45d6c07be6 Update emplace() to no longer needlessly rebind its allocator 2023-03-03 11:17:38 -08:00
Christian Mazakas 5c63cd2bdb Update drone to run using the same branches as listed in GHA's ci.yml 2023-03-03 11:17:38 -08:00
Christian Mazakas 86318c1e88 Update foa to construct stack-locals with the user's Allocator during emplace() 2023-03-03 11:17:38 -08:00
Christian Mazakas 0ff1fa0f6e Add test that ensures proper uses-allocator construction is followed 2023-03-03 11:17:38 -08:00
Christian Mazakas d90bf0c438 Merge pull request #186 from boostorg/cxx03-deprecation
Update changelog to reflect planned C++03 deprecation
2023-03-01 09:53:24 -08:00
Christian Mazakas dc63438e22 Add missing end-of-list marker to compliance section 2023-03-01 09:37:49 -08:00
Christian Mazakas 0a3ac26f00 Update changelog to reflect planned C++03 deprecation 2023-02-28 15:44:44 -08:00
joaquintides c64ed1caa3 Feature/SIMD config (#184)
* added BOOST_UNORDERED_[ENABLE|DISABLE]_[SSE2|LITTLE_ENDIAN_NEON]
* renamed and refactored
* removed #undefs of SIMD usage macros
2023-02-26 16:39:50 +01:00
joaquintides efc33b18be Merge pull request #182 from boostorg/feature/unordered_node_map_docs
Feature/unordered node map docs
2023-02-25 10:20:05 +01:00
joaquintides c189d8d5e8 updated boost::unordered_(flat|node)_map benchmarks 2023-02-25 10:03:10 +01:00
joaquintides 886227db3b updated link to P2363 2023-02-24 09:58:51 +01:00
joaquintides 719eb90d03 fixed copy&paste error 2023-02-24 08:59:45 +01:00
joaquintides fadb686bc5 added boost::unordered_node_map to benchmarks 2023-02-23 20:17:01 +01:00
Christian Mazakas aebefaef0d Merge pull request #183 from boostorg/unordered_node_map_rc
Node Map Release Candidate
2023-02-22 08:39:59 -08:00
Christian Mazakas 63a564e8ff Update foa comments for changes in TypePolicy 2023-02-21 11:12:33 -08:00
Christian Mazakas 16c1593368 Remove extraneous copy constructor from flat set's type policy 2023-02-21 07:53:09 -08:00
Christian Mazakas 53580a3070 Fix bug in hint-based overload for node_type insertion where elements were erroneously reallocated 2023-02-19 21:26:06 -08:00
Christian Mazakas d26aeed68f Update node_handle tests to cover address stability for inserted nodes when using the hint-based overloads 2023-02-19 21:26:06 -08:00
Christian Mazakas 73eefd2b5d Rename Node{X}Types to TypePolicy in node-based foa containers 2023-02-19 21:26:06 -08:00
Christian Mazakas 3df600d069 Remove extraneous construct() overloads from the flat foa-based containers 2023-02-19 21:26:06 -08:00
Christian Mazakas a1adacdfe2 Refactor erase_on_exit to use a const_iterator so callsites can avoid a const cast 2023-02-19 21:26:06 -08:00
Christian Mazakas f405fa9118 Rename foa's emplace_dispatch to emplace_value 2023-02-19 21:26:06 -08:00
Christian Mazakas 7b5d6e7c29 Fix typos in code comments in foa 2023-02-19 21:26:06 -08:00
Christian Mazakas 7d0ba7178e Clean up naming in delete_ impl to use storage_traits for foa 2023-02-19 21:26:06 -08:00
Christian Mazakas df5e2c3aca Remove extraneous commented out code from foa 2023-02-19 21:26:06 -08:00
Christian Mazakas 343e344582 Reify implementation of node_handle's swap 2023-02-19 21:26:06 -08:00
Christian Mazakas 34ed463bea Reify implementation of node_handle's move assignment operator 2023-02-19 21:26:06 -08:00
Christian Mazakas 5986f75d16 Refactor node_handle's clear() member function to reset() 2023-02-19 21:26:06 -08:00
Christian Mazakas b08810c0c4 Add missing copyright notice to foa.hpp 2023-02-19 21:26:06 -08:00
Christian Mazakas 7c608ae7bc Include missing extract tests in transparent_tests 2023-02-19 21:25:25 -08:00
joaquintides d51cee35d5 updated open-addressing benchmark info 2023-02-18 12:31:26 +01:00
joaquintides d0289b4c7b editorial 2023-02-18 12:13:14 +01:00
Christian Mazakas bc7ba9cb3b Implement internal foa updates + node_handle for node-based containers 2023-02-14 10:55:35 -08:00
Christian Mazakas 6b10c8a4d3 Update unordered_flat_map for new type traits 2023-02-14 10:55:35 -08:00
Christian Mazakas b9805c7309 Update unordered_flat_set for new type traits 2023-02-14 10:55:35 -08:00
Christian Mazakas 844460fd22 Add unordered_node_map 2023-02-14 10:55:35 -08:00
Christian Mazakas a600278d27 Add unordered_node_set 2023-02-14 10:55:35 -08:00
Christian Mazakas 4398ffe8c9 Add foa-based node containers to node_handle_tests 2023-02-14 10:55:35 -08:00
Christian Mazakas eed1eeedeb Add foa-based node containers to extract_tests 2023-02-14 10:55:35 -08:00
Christian Mazakas 8c0c230f78 Add foa-based node containers to the exception tests 2023-02-14 10:55:35 -08:00
Christian Mazakas e96ec1e79a Add foa-based node containers to transparent_tests 2023-02-14 10:55:35 -08:00
Christian Mazakas be7dd51fab Add foa-based node containers to swap_tests 2023-02-14 10:55:35 -08:00
Christian Mazakas 4dec95840b Add foa-based node containers to simple_tests 2023-02-14 10:55:35 -08:00
Christian Mazakas d44fb36581 Add foa-based node containers to scoped_allocator tests 2023-02-14 10:55:35 -08:00
Christian Mazakas 9d3bbe27db Add foa-based node containers to scary_tests 2023-02-14 10:55:35 -08:00
Christian Mazakas 13ed4afc95 Add foa-based node containers to reserve_tests 2023-02-14 10:55:35 -08:00
Christian Mazakas b3f54e74a7 Add foa-based node containers to rehash_tests 2023-02-14 10:55:35 -08:00
Christian Mazakas d6374e2718 Add foa-based node containers to post_move_tests 2023-02-14 10:55:35 -08:00
Christian Mazakas 74156b6b06 Add foa-based node containers to noexcept_tests 2023-02-14 10:55:35 -08:00
Christian Mazakas 965048d3e6 Add foa-based node containers to move_tests 2023-02-14 10:55:35 -08:00
Christian Mazakas 36dfe6b98b Add foa-based node containers to merge_tests 2023-02-14 10:55:35 -08:00
Christian Mazakas e4e89bdbde Add foa-based node containers to max_load_tests 2023-02-14 10:55:35 -08:00
Christian Mazakas 85a9d8d81d Add foa-based node containers to load_factor_tests 2023-02-14 10:55:35 -08:00
Christian Mazakas b21ad13bbb Add foa-based node containers to link tests 2023-02-14 10:55:35 -08:00
Christian Mazakas f0d10308e3 Add foa-based node containers to insert_tests 2023-02-14 10:55:35 -08:00
Christian Mazakas f240e587cb Add foa-based node containers to insert_hint_tests 2023-02-14 10:55:35 -08:00
Christian Mazakas 2a7dc9e40e Add foa-based node containers to init_type_insert_tests 2023-02-14 10:55:35 -08:00
Christian Mazakas 99b8d0063b Add foa-based node containers to incomplete_test 2023-02-14 10:55:35 -08:00
Christian Mazakas c6aff9278a Add foa-based node containers to fwd_set_test 2023-02-14 10:55:35 -08:00
Christian Mazakas 129497133e Add foa-based node containers to fwd_map_test 2023-02-14 10:55:35 -08:00
Christian Mazakas eaa9ff0cec Add foa-based node containers to find_tests 2023-02-14 10:55:35 -08:00
Christian Mazakas fa735864a3 Add foa-based node containers to erase_tests 2023-02-14 10:55:35 -08:00
Christian Mazakas 0ce180e19b Add foa-based node containers to erase_if tests 2023-02-14 10:55:35 -08:00
Christian Mazakas e578b7eee3 Add foa-based node containers to equivalent_keys_tests 2023-02-14 10:55:35 -08:00
Christian Mazakas 1844695b0c Add foa-based node containers to equality_tests 2023-02-14 10:55:35 -08:00
Christian Mazakas 54b9adbdbc Add foa-based node containers to emplace_tests 2023-02-14 10:55:35 -08:00
Christian Mazakas 8b71656cd7 Add foa-based node containers to copy_tests 2023-02-14 10:55:35 -08:00
Christian Mazakas a858ef5688 Add foa-based node containers to contains_tests 2023-02-14 10:55:35 -08:00
Christian Mazakas 18395c8d21 Add foa-based node containers to constructor_tests 2023-02-14 10:55:35 -08:00
Christian Mazakas e68ec5c9a9 Add foa-based node containers to compile_set tests 2023-02-14 10:55:35 -08:00
Christian Mazakas d3b264345d Add foa-based node containers to compile_map tests 2023-02-14 10:55:35 -08:00
Christian Mazakas f1e1733c06 Add foa-based node containers to at_tests 2023-02-14 10:55:35 -08:00
Christian Mazakas 66ffbdb881 Add foa-based node containers to assign_tests 2023-02-14 10:55:35 -08:00
Christian Mazakas f7f5466ed2 Add necessary #include's and typedefs for test suite to use foa-based node containers 2023-02-14 10:55:35 -08:00
Christian Mazakas 83410fcabe Add -Wunused-template to tests run with the clang-14 toolset 2023-02-14 10:55:35 -08:00
Christian Mazakas 1ee91d494d Fix bug in impl of test::exception::less::operator() 2023-02-14 10:55:35 -08:00
Christian Mazakas e8fe550d6c Add less_tests to track bug in test::exception::less::operator() impl 2023-02-14 10:55:35 -08:00
Christian Mazakas 5b0fe7f655 Update test::compare_range to use BOOST_TEST_ALL_WITH 2023-02-14 10:55:35 -08:00
Christian Mazakas ba439437bf Add osx 12 to gha ci matrix 2023-02-14 10:55:35 -08:00
joaquintides aa6eef135e editorial 2023-02-13 18:40:36 +01:00
joaquintides 1dd085daaa added unordered_node_[map|set] containers to the tutorial 2023-02-13 13:29:52 +01:00
joaquintides 2a8f50bcb7 added reference for unordered_node_set 2023-02-12 18:32:26 +01:00
joaquintides 866c58a879 typo 2023-02-12 17:35:02 +01:00
joaquintides c9a75a56c2 added reference for unordered_node_map 2023-02-11 13:23:34 +01:00
joaquintides e1861aa3d9 updated copyright notes 2023-02-11 13:23:12 +01:00
joaquintides 242c7cb93a updated release notes 2023-02-11 13:22:55 +01:00
joaquintides 0597463902 Merge pull request #181 from boostorg/feature/mulx_docs
Documented the new mulx-based mixing algorithm
2023-02-09 09:06:51 +01:00
joaquintides 14d80725eb documented the new mulx-based mixing algorithm 2023-02-08 20:07:23 +01:00
106 changed files with 8604 additions and 1364 deletions
+1 -1
View File
@@ -6,7 +6,7 @@ local library = "unordered";
local triggers =
{
branch: [ "master", "develop", "feature/*", "bugfix/*" ]
branch: [ "master", "develop", "feature/*", "bugfix/*", "fix/*", "pr/*" ]
};
local ubsan = { UBSAN: '1', UBSAN_OPTIONS: 'print_stacktrace=1' };
+3 -2
View File
@@ -72,9 +72,10 @@ jobs:
compiler: clang-14, cxxstd: '17,20,2b', os: ubuntu-22.04, ccache_key: "san2" }
# OSX, clang
- { compiler: clang, cxxstd: '03,11,14,17,2a', os: macos-11, sanitize: yes }
- { compiler: clang, cxxstd: '03,11,14,17,2a', os: macos-11, }
- { compiler: clang, cxxstd: '03,11,14,17,2a', os: macos-12, sanitize: yes }
timeout-minutes: 120
timeout-minutes: 180
runs-on: ${{matrix.os}}
container: ${{matrix.container}}
env: {B2_USE_CCACHE: 1}
+10
View File
@@ -1,4 +1,5 @@
// Copyright 2021 Peter Dimov.
// Copyright 2023 Joaquin M Lopez Munoz.
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
@@ -6,6 +7,7 @@
#define _SILENCE_CXX20_CISO646_REMOVED_WARNING
#include <boost/unordered_map.hpp>
#include <boost/unordered/unordered_node_map.hpp>
#include <boost/unordered/unordered_flat_map.hpp>
#include <boost/core/detail/splitmix64.hpp>
#include <boost/config.hpp>
@@ -272,6 +274,9 @@ template<class K, class V> using std_unordered_map =
template<class K, class V> using boost_unordered_map =
boost::unordered_map<K, V, boost::hash<K>, std::equal_to<K>, allocator_for<K, V>>;
template<class K, class V> using boost_unordered_node_map =
boost::unordered_node_map<K, V, boost::hash<K>, std::equal_to<K>, allocator_for<K, V>>;
template<class K, class V> using boost_unordered_flat_map =
boost::unordered_flat_map<K, V, boost::hash<K>, std::equal_to<K>, allocator_for<K, V>>;
@@ -345,6 +350,9 @@ std::unordered_map<K, V, fnv1a_hash, std::equal_to<K>, allocator_for<K, V>>;
template<class K, class V> using boost_unordered_map_fnv1a =
boost::unordered_map<K, V, fnv1a_hash, std::equal_to<K>, allocator_for<K, V>>;
template<class K, class V> using boost_unordered_node_map_fnv1a =
boost::unordered_node_map<K, V, fnv1a_hash, std::equal_to<K>, allocator_for<K, V>>;
template<class K, class V> using boost_unordered_flat_map_fnv1a =
boost::unordered_flat_map<K, V, fnv1a_hash, std::equal_to<K>, allocator_for<K, V>>;
@@ -373,6 +381,7 @@ int main()
test<std_unordered_map>( "std::unordered_map" );
test<boost_unordered_map>( "boost::unordered_map" );
test<boost_unordered_node_map>( "boost::unordered_node_map" );
test<boost_unordered_flat_map>( "boost::unordered_flat_map" );
#ifdef HAVE_ANKERL_UNORDERED_DENSE
@@ -390,6 +399,7 @@ int main()
test<std_unordered_map_fnv1a>( "std::unordered_map, FNV-1a" );
test<boost_unordered_map_fnv1a>( "boost::unordered_map, FNV-1a" );
test<boost_unordered_node_map_fnv1a>( "boost::unordered_node_map, FNV-1a" );
test<boost_unordered_flat_map_fnv1a>( "boost::unordered_flat_map, FNV-1a" );
#ifdef HAVE_ANKERL_UNORDERED_DENSE
+10
View File
@@ -1,4 +1,5 @@
// Copyright 2021 Peter Dimov.
// Copyright 2023 Joaquin M Lopez Munoz.
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
@@ -6,6 +7,7 @@
#define _SILENCE_CXX20_CISO646_REMOVED_WARNING
#include <boost/unordered_map.hpp>
#include <boost/unordered/unordered_node_map.hpp>
#include <boost/unordered/unordered_flat_map.hpp>
#include <boost/core/detail/splitmix64.hpp>
#include <boost/config.hpp>
@@ -273,6 +275,9 @@ template<class K, class V> using std_unordered_map =
template<class K, class V> using boost_unordered_map =
boost::unordered_map<K, V, boost::hash<K>, std::equal_to<K>, allocator_for<K, V>>;
template<class K, class V> using boost_unordered_node_map =
boost::unordered_node_map<K, V, boost::hash<K>, std::equal_to<K>, allocator_for<K, V>>;
template<class K, class V> using boost_unordered_flat_map =
boost::unordered_flat_map<K, V, boost::hash<K>, std::equal_to<K>, allocator_for<K, V>>;
@@ -346,6 +351,9 @@ std::unordered_map<K, V, fnv1a_hash, std::equal_to<K>, allocator_for<K, V>>;
template<class K, class V> using boost_unordered_map_fnv1a =
boost::unordered_map<K, V, fnv1a_hash, std::equal_to<K>, allocator_for<K, V>>;
template<class K, class V> using boost_unordered_node_map_fnv1a =
boost::unordered_node_map<K, V, fnv1a_hash, std::equal_to<K>, allocator_for<K, V>>;
template<class K, class V> using boost_unordered_flat_map_fnv1a =
boost::unordered_flat_map<K, V, fnv1a_hash, std::equal_to<K>, allocator_for<K, V>>;
@@ -374,6 +382,7 @@ int main()
test<std_unordered_map>( "std::unordered_map" );
test<boost_unordered_map>( "boost::unordered_map" );
test<boost_unordered_node_map>( "boost::unordered_node_map" );
test<boost_unordered_flat_map>( "boost::unordered_flat_map" );
#ifdef HAVE_ANKERL_UNORDERED_DENSE
@@ -391,6 +400,7 @@ int main()
test<std_unordered_map_fnv1a>( "std::unordered_map, FNV-1a" );
test<boost_unordered_map_fnv1a>( "boost::unordered_map, FNV-1a" );
test<boost_unordered_node_map_fnv1a>( "boost::unordered_node_map, FNV-1a" );
test<boost_unordered_flat_map_fnv1a>( "boost::unordered_flat_map, FNV-1a" );
#ifdef HAVE_ANKERL_UNORDERED_DENSE
+6
View File
@@ -1,4 +1,5 @@
// Copyright 2021 Peter Dimov.
// Copyright 2023 Joaquin M Lopez Munoz.
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
@@ -6,6 +7,7 @@
#define _SILENCE_CXX20_CISO646_REMOVED_WARNING
#include <boost/unordered_map.hpp>
#include <boost/unordered/unordered_node_map.hpp>
#include <boost/unordered/unordered_flat_map.hpp>
#include <boost/endian/conversion.hpp>
#include <boost/core/detail/splitmix64.hpp>
@@ -289,6 +291,9 @@ template<class K, class V> using std_unordered_map =
template<class K, class V> using boost_unordered_map =
boost::unordered_map<K, V, boost::hash<K>, std::equal_to<K>, allocator_for<K, V>>;
template<class K, class V> using boost_unordered_node_map =
boost::unordered_node_map<K, V, boost::hash<K>, std::equal_to<K>, allocator_for<K, V>>;
template<class K, class V> using boost_unordered_flat_map =
boost::unordered_flat_map<K, V, boost::hash<K>, std::equal_to<K>, allocator_for<K, V>>;
@@ -315,6 +320,7 @@ int main()
test<std_unordered_map>( "std::unordered_map" );
test<boost_unordered_map>( "boost::unordered_map" );
test<boost_unordered_node_map>( "boost::unordered_node_map" );
test<boost_unordered_flat_map>( "boost::unordered_flat_map" );
#ifdef HAVE_ANKERL_UNORDERED_DENSE
+6
View File
@@ -1,4 +1,5 @@
// Copyright 2021 Peter Dimov.
// Copyright 2023 Joaquin M Lopez Munoz.
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
@@ -6,6 +7,7 @@
#define _SILENCE_CXX20_CISO646_REMOVED_WARNING
#include <boost/unordered_map.hpp>
#include <boost/unordered/unordered_node_map.hpp>
#include <boost/unordered/unordered_flat_map.hpp>
#include <boost/endian/conversion.hpp>
#include <boost/core/detail/splitmix64.hpp>
@@ -289,6 +291,9 @@ template<class K, class V> using std_unordered_map =
template<class K, class V> using boost_unordered_map =
boost::unordered_map<K, V, boost::hash<K>, std::equal_to<K>, allocator_for<K, V>>;
template<class K, class V> using boost_unordered_node_map =
boost::unordered_node_map<K, V, boost::hash<K>, std::equal_to<K>, allocator_for<K, V>>;
template<class K, class V> using boost_unordered_flat_map =
boost::unordered_flat_map<K, V, boost::hash<K>, std::equal_to<K>, allocator_for<K, V>>;
@@ -325,6 +330,7 @@ int main()
#endif
test<boost_unordered_map>( "boost::unordered_map" );
test<boost_unordered_node_map>( "boost::unordered_node_map" );
test<boost_unordered_flat_map>( "boost::unordered_flat_map" );
#ifdef HAVE_ANKERL_UNORDERED_DENSE
+6
View File
@@ -1,4 +1,5 @@
// Copyright 2021, 2022 Peter Dimov.
// Copyright 2023 Joaquin M Lopez Munoz.
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
@@ -6,6 +7,7 @@
#define _SILENCE_CXX20_CISO646_REMOVED_WARNING
#include <boost/unordered_map.hpp>
#include <boost/unordered/unordered_node_map.hpp>
#include <boost/unordered/unordered_flat_map.hpp>
#include <boost/endian/conversion.hpp>
#include <boost/core/detail/splitmix64.hpp>
@@ -340,6 +342,9 @@ template<class K, class V> using std_unordered_map =
template<class K, class V> using boost_unordered_map =
boost::unordered_map<K, V, boost::hash<K>, std::equal_to<K>, allocator_for<K, V>>;
template<class K, class V> using boost_unordered_node_map =
boost::unordered_node_map<K, V, boost::hash<K>, std::equal_to<K>, allocator_for<K, V>>;
template<class K, class V> using boost_unordered_flat_map =
boost::unordered_flat_map<K, V, boost::hash<K>, std::equal_to<K>, allocator_for<K, V>>;
@@ -366,6 +371,7 @@ int main()
test<std_unordered_map>( "std::unordered_map" );
test<boost_unordered_map>( "boost::unordered_map" );
test<boost_unordered_node_map>( "boost::unordered_node_map" );
test<boost_unordered_flat_map>( "boost::unordered_flat_map" );
#ifdef HAVE_ANKERL_UNORDERED_DENSE
+10
View File
@@ -1,4 +1,5 @@
// Copyright 2021, 2022 Peter Dimov.
// Copyright 2023 Joaquin M Lopez Munoz.
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
@@ -6,6 +7,7 @@
#define _SILENCE_CXX20_CISO646_REMOVED_WARNING
#include <boost/unordered_map.hpp>
#include <boost/unordered/unordered_node_map.hpp>
#include <boost/unordered/unordered_flat_map.hpp>
#include <boost/regex.hpp>
#ifdef HAVE_ABSEIL
@@ -227,6 +229,9 @@ template<class K, class V> using std_unordered_map =
template<class K, class V> using boost_unordered_map =
boost::unordered_map<K, V, boost::hash<K>, std::equal_to<K>, allocator_for<K, V>>;
template<class K, class V> using boost_unordered_node_map =
boost::unordered_node_map<K, V, boost::hash<K>, std::equal_to<K>, allocator_for<K, V>>;
template<class K, class V> using boost_unordered_flat_map =
boost::unordered_flat_map<K, V, boost::hash<K>, std::equal_to<K>, allocator_for<K, V>>;
@@ -300,6 +305,9 @@ std::unordered_map<K, V, fnv1a_hash, std::equal_to<K>, allocator_for<K, V>>;
template<class K, class V> using boost_unordered_map_fnv1a =
boost::unordered_map<K, V, fnv1a_hash, std::equal_to<K>, allocator_for<K, V>>;
template<class K, class V> using boost_unordered_node_map_fnv1a =
boost::unordered_node_map<K, V, fnv1a_hash, std::equal_to<K>, allocator_for<K, V>>;
template<class K, class V> using boost_unordered_flat_map_fnv1a =
boost::unordered_flat_map<K, V, fnv1a_hash, std::equal_to<K>, allocator_for<K, V>>;
@@ -328,6 +336,7 @@ int main()
test<std_unordered_map>( "std::unordered_map" );
test<boost_unordered_map>( "boost::unordered_map" );
test<boost_unordered_node_map>( "boost::unordered_node_map" );
test<boost_unordered_flat_map>( "boost::unordered_flat_map" );
#ifdef HAVE_ANKERL_UNORDERED_DENSE
@@ -345,6 +354,7 @@ int main()
test<std_unordered_map_fnv1a>( "std::unordered_map, FNV-1a" );
test<boost_unordered_map_fnv1a>( "boost::unordered_map, FNV-1a" );
test<boost_unordered_node_map_fnv1a>( "boost::unordered_node_map, FNV-1a" );
test<boost_unordered_flat_map_fnv1a>( "boost::unordered_flat_map, FNV-1a" );
#ifdef HAVE_ANKERL_UNORDERED_DENSE
+6
View File
@@ -1,4 +1,5 @@
// Copyright 2021, 2022 Peter Dimov.
// Copyright 2023 Joaquin M Lopez Munoz.
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
@@ -6,6 +7,7 @@
#define _SILENCE_CXX20_CISO646_REMOVED_WARNING
#include <boost/unordered_map.hpp>
#include <boost/unordered/unordered_node_map.hpp>
#include <boost/unordered/unordered_flat_map.hpp>
#include <boost/regex.hpp>
#ifdef HAVE_ABSEIL
@@ -181,6 +183,9 @@ template<class K, class V> using std_unordered_map =
template<class K, class V> using boost_unordered_map =
boost::unordered_map<K, V, boost::hash<K>, std::equal_to<K>, allocator_for<K, V>>;
template<class K, class V> using boost_unordered_node_map =
boost::unordered_node_map<K, V, boost::hash<K>, std::equal_to<K>, allocator_for<K, V>>;
template<class K, class V> using boost_unordered_flat_map =
boost::unordered_flat_map<K, V, boost::hash<K>, std::equal_to<K>, allocator_for<K, V>>;
@@ -207,6 +212,7 @@ int main()
test<std_unordered_map>( "std::unordered_map" );
test<boost_unordered_map>( "boost::unordered_map" );
test<boost_unordered_node_map>( "boost::unordered_node_map" );
test<boost_unordered_flat_map>( "boost::unordered_flat_map" );
#ifdef HAVE_ANKERL_UNORDERED_DENSE
Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 51 KiB

+3 -2
View File
@@ -278,13 +278,14 @@ max load factor 5
|===
== boost::unordered_flat_map
== boost::unordered_(flat|node)_map
All benchmarks were created using:
* `https://abseil.io/docs/cpp/guides/container[absl::flat_hash_map^]<uint64_t, uint64_t>`
* `boost::unordered_flat_map<uint64_t, uint64_t>`
* `boost::unordered_map<uint64_t, uint64_t>`
* `boost::unordered_flat_map<uint64_t, uint64_t>`
* `boost::unordered_node_map<uint64_t, uint64_t>`
The source code can be https://github.com/boostorg/boost_unordered_benchmarks/tree/boost_unordered_flat_map[found here^].
+9 -6
View File
@@ -134,7 +134,8 @@ h|*Method* h|*Description*
|Changes the number of buckets so that there at least `n` buckets, and so that the load factor is less than the maximum load factor.
2+^h| *Open-addressing containers only* +
`boost::unordered_flat_set`, `boost::unordered_flat_map`
`boost::unordered_flat_set`, `boost::unordered_flat_map` +
`boost::unordered_node_set`, `boost::unordered_node_map` +
h|*Method* h|*Description*
|`size_type max_load() const`
@@ -160,8 +161,9 @@ change the number of buckets when this happens. Iterators can be
invalidated by calls to `insert`, `rehash` and `reserve`.
As for pointers and references,
they are never invalidated for closed-addressing containers (`boost::unordered_[multi]set`, `boost::unordered_[multi]map`),
but they will when rehashing occurs for open-addressing
they are never invalidated for node-based containers
(`boost::unordered_[multi]set`, `boost::unordered_[multi]map`, `boost::unordered_node_set`, `boost::unordered_node_map`),
but they will when rehashing occurs for
`boost::unordered_flat_set` and `boost::unordered_flat_map`: this is because
these containers store elements directly into their holding buckets, so
when allocating a new bucket array the elements must be transferred by means of move construction.
@@ -252,15 +254,16 @@ xref:#rationale_boostunordered_multiset_and_boostunordered_multimap[correspondin
== Open Addressing Implementation
The diagram shows the basic internal layout of `boost::unordered_flat_map` and
`boost:unordered_flat_set`.
The diagram shows the basic internal layout of `boost::unordered_flat_map`/`unordered_node_map` and
`boost:unordered_flat_set`/`unordered_node_set`.
[#img-foa-layout]
.Open-addressing layout used by Boost.Unordered.
image::foa.png[align=center]
As with all open-addressing containers, elements are stored directly in the bucket array.
As with all open-addressing containers, elements (or pointers to the element nodes in the case of
`boost::unordered_node_map` and `boost::unordered_node_set`) are stored directly in the bucket array.
This array is logically divided into 2^_n_^ _groups_ of 15 elements each.
In addition to the bucket array, there is an associated _metadata array_ with 2^_n_^
16-byte words.
+15 -2
View File
@@ -6,10 +6,23 @@
:github-pr-url: https://github.com/boostorg/unordered/pull
:cpp: C++
== Release 1.82.0
== Release 1.83.0
* Sped up iteration of open-addressing containers.
== Release 1.82.0 - Major update
* {cpp}03 support is planned for deprecation. Boost 1.84.0 will no longer support
{cpp}03 mode and {cpp}11 will become the new minimum for using the library.
* Added node-based, open-addressing containers
`boost::unordered_node_map` and `boost::unordered_node_set`.
* Extended heterogeneous lookup to more member functions as specified in
https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2363r3.html[P2363].
https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2363r5.html[P2363].
* Replaced the previous post-mixing process for open-addressing containers with
a new algorithm based on extended multiplication by a constant.
* Fixed bug in internal emplace() impl where stack-local types were not properly
constructed using the Allocator of the container which breaks uses-allocator
construction.
== Release 1.81.0 - Major update
+2 -2
View File
@@ -33,8 +33,8 @@
|Iterators, pointers and references to the container's elements are never invalidated.
|<<buckets_iterator_invalidation,Iterators can be invalidated by calls to insert or rehash>>. +
**Closed-addressing containers:** Pointers and references to the container's elements are never invalidated. +
**Open-addressing containers:** Pointers and references to the container's elements are invalidated when rehashing occurs.
**Node-based containers:** Pointers and references to the container's elements are never invalidated. +
**Flat containers:** Pointers and references to the container's elements are invalidated when rehashing occurs.
|Iterators iterate through the container in the order defined by the comparison object.
|Iterators iterate through the container in an arbitrary order, that can change as elements are inserted, although equivalent elements are always adjacent.
+19 -15
View File
@@ -5,9 +5,9 @@
:cpp: C++
== Closed-addressing containers: unordered_[multi]set, unordered_[multi]map
== Closed-addressing containers
The intent of Boost.Unordered is to provide a conformant
`unordered_[multi]set` and `unordered_[multi]map` are intended to provide a conformant
implementation of the {cpp}20 standard that will work with {cpp}98 upwards.
This wide compatibility does mean some compromises have to be made.
With a compiler and library that fully support {cpp}11, the differences should
@@ -117,27 +117,31 @@ Variadic constructor arguments for `emplace` are only used when both
rvalue references and variadic template parameters are available.
Otherwise `emplace` can only take up to 10 constructors arguments.
== Open-addressing containers: unordered_flat_set, unordered_flat_map
== Open-addressing containers
The C++ standard does not currently provide any open-addressing container
specification to adhere to, so `boost::unordered_flat_set` and
`boost::unordered_flat_map` take inspiration from `std::unordered_set` and
specification to adhere to, so `boost::unordered_flat_set`/`unordered_node_set` and
`boost::unordered_flat_map`/`unordered_node_map` take inspiration from `std::unordered_set` and
`std::unordered_map`, respectively, and depart from their interface where
convenient or as dictated by their internal data structure, which is
radically different from that imposed by the standard (closed addressing, node based).
radically different from that imposed by the standard (closed addressing).
`unordered_flat_set` and `unordered_flat_map` only work with reasonably
Open-addressing containers provided by Boost.Unordered only work with reasonably
compliant C++11 (or later) compilers. Language-level features such as move semantics
and variadic template parameters are then not emulated.
`unordered_flat_set` and `unordered_flat_map` are fully https://en.cppreference.com/w/cpp/named_req/AllocatorAwareContainer[AllocatorAware^].
The containers are fully https://en.cppreference.com/w/cpp/named_req/AllocatorAwareContainer[AllocatorAware^].
The main differences with C++ unordered associative containers are:
* `value_type` must be move-constructible.
* Pointer stability is not kept under rehashing.
* `begin()` is not constant-time.
* `erase(iterator)` returns `void` instead of an iterator to the following element.
* There is no API for bucket handling (except `bucket_count`) or node extraction/insertion.
* The maximum load factor of the container is managed internally and can't be set by the user. The maximum load,
exposed through the public function `max_load`, may decrease on erasure under high-load conditions.
* In general:
** `begin()` is not constant-time.
** `erase(iterator)` returns `void` instead of an iterator to the following element.
** There is no API for bucket handling (except `bucket_count`).
** The maximum load factor of the container is managed internally and can't be set by the user. The maximum load,
exposed through the public function `max_load`, may decrease on erasure under high-load conditions.
* Flat containers (`boost::unordered_flat_set` and `boost::unordered_flat_map`):
** `value_type` must be move-constructible.
** Pointer stability is not kept under rehashing.
** There is no API for node extraction/insertion.
//-
+3 -3
View File
@@ -9,10 +9,10 @@ Copyright (C) 2003, 2004 Jeremy B. Maitin-Shepard
Copyright (C) 2005-2008 Daniel James
Copyright (C) 2022 Christian Mazakas
Copyright (C) 2022-2023 Christian Mazakas
Copyright (C) 2022 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz
Copyright (C) 2022-2023 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz
Copyright (C) 2022 Peter Dimov
Copyright (C) 2022-2023 Peter Dimov
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)
+63 -2
View File
@@ -106,8 +106,69 @@ namespace boost {
}
----
`boost::unordered_flat_set` and `boost::unordered_flat_map` require a
reasonably compliant C++11 compiler.
Starting in Boost 1.82, the containers `boost::unordered_node_set` and `boost::unordered_node_map`
are introduced: they use open addressing like `boost::unordered_flat_set` and `boost::unordered_flat_map`,
but internally store element _nodes_, like `boost::unordered_set` and `boost::unordered_map`,
which provide stability of pointers and references to the elements:
[source,c++]
----
// #include <boost/unordered/unordered_node_set.hpp>
//
// Note: no multiset version
namespace boost {
template <
class Key,
class Hash = boost::hash<Key>,
class Pred = std::equal_to<Key>,
class Alloc = std::allocator<Key> >
class unordered_node_set;
}
----
[source,c++]
----
// #include <boost/unordered/unordered_node_map.hpp>
//
// Note: no multimap version
namespace boost {
template <
class Key, class Mapped,
class Hash = boost::hash<Key>,
class Pred = std::equal_to<Key>,
class Alloc = std::allocator<std::pair<Key const, Mapped> > >
class unordered_node_map;
}
----
These are all the containers provided by Boost.Unordered:
[caption=, title='Table {counter:table-counter}. Boost.Unordered containers']
[cols="1,1,.^1", frame=all, grid=rows]
|===
^h|
^h|*Node-based*
^h|*Flat*
^.^h|*Closed addressing*
^| `boost::unordered_set` +
`boost::unordered_map` +
`boost::unordered_multiset` +
`boost::unordered_multimap`
^|
^.^h|*Open addressing*
^| `boost::unordered_node_set` +
`boost::unordered_node_map`
^| `boost::unordered_flat_set` +
`boost::unordered_flat_map`
|===
Closed-addressing containers are pass:[C++]98-compatible. Open-addressing containers require a
reasonably compliant pass:[C++]11 compiler.
Boost.Unordered containers are used in a similar manner to the normal associative
containers:
+16 -12
View File
@@ -4,9 +4,10 @@
= Implementation Rationale
== boost::unordered_[multi]set and boost::unordered_[multi]map
== Closed-addressing containers
These containers adhere to the standard requirements for unordered associative
`boost::unordered_[multi]set` and `boost::unordered_[multi]map`
adhere to the standard requirements for unordered associative
containers, so the interface was fixed. But there are
still some implementation decisions to make. The priorities are
conformance to the standard and portability.
@@ -64,8 +65,8 @@ of bits in the hash value, so it was only used when `size_t` was 64 bit.
Since release 1.79.0, https://en.wikipedia.org/wiki/Hash_function#Fibonacci_hashing[Fibonacci hashing]
is used instead. With this implementation, the bucket number is determined
by using `(h * m) >> (w - k)`, where `h` is the hash value, `m` is the golden
ratio multiplied by `2^w`, `w` is the word size (32 or 64), and `2^k` is the
by using `(h * m) >> (w - k)`, where `h` is the hash value, `m` is `2^w` divided
by the golden ratio, `w` is the word size (32 or 64), and `2^k` is the
number of buckets. This provides a good compromise between speed and
distribution.
@@ -73,7 +74,7 @@ Since release 1.80.0, prime numbers are chosen for the number of buckets in
tandem with sophisticated modulo arithmetic. This removes the need for "mixing"
the result of the user's hash function as was used for release 1.79.0.
== boost::unordered_flat_set and boost::unordered_flat_map
== Open-addresing containers
The C++ standard specification of unordered associative containers impose
severe limitations on permissible implementations, the most important being
@@ -81,29 +82,32 @@ that closed addressing is implicitly assumed. Slightly relaxing this specificati
opens up the possibility of providing container variations taking full
advantage of open-addressing techniques.
The design of `boost::unordered_flat_set` and `boost::unordered_flat_map` has been
The design of `boost::unordered_flat_set`/`unordered_node_set` and `boost::unordered_flat_map`/`unordered_node_map` has been
guided by Peter Dimov's https://pdimov.github.io/articles/unordered_dev_plan.html[Development Plan for Boost.Unordered^].
We discuss here the most relevant principles.
=== Hash function
Given its rich functionality and cross-platform interoperability,
`boost::hash` remains the default hash function of `boost::unordered_flat_set` and `boost::unordered_flat_map`.
`boost::hash` remains the default hash function of open-addressing containers.
As it happens, `boost::hash` for integral and other basic types does not possess
the statistical properties required by open addressing; to cope with this,
we implement a post-mixing stage:
* 64-bit architectures: we use the `xmx` function defined in
Jon Maiga's http://jonkagstrom.com/bit-mixer-construction/index.html[The construct of a bit mixer^].
* 32-bit architectures: the mixer used was selected from a set generated with https://github.com/skeeto/hash-prospector[Hash Function Prospector^]
as the best overall performer in our internal benchmarks. Score assigned by Hash Prospector is 333.7934929677524.
{nbsp}{nbsp}{nbsp}{nbsp} _a_ <- _h_ *mulx* _C_, +
{nbsp}{nbsp}{nbsp}{nbsp} _h_ <- *high*(_a_) *xor* *low*(_a_),
where *mulx* is an _extended multiplication_ (128 bits in 64-bit architectures, 64 bits in 32-bit environments),
and *high* and *low* are the upper and lower halves of an extended word, respectively.
In 64-bit architectures, _C_ is the integer part of 2^64^&#8725;https://en.wikipedia.org/wiki/Golden_ratio[_&phi;_],
whereas in 32 bits _C_ = 0xE817FB2Du has been obtained from https://arxiv.org/abs/2001.05304[Steele and Vigna (2021)^].
When using a hash function directly suitable for open addressing, post-mixing can be opted out by via a dedicated <<hash_traits_hash_is_avalanching,`hash_is_avalanching`>>trait.
`boost::hash` specializations for string types are marked as avalanching.
=== Platform interoperability
The observable behavior of `boost::unordered_flat_set` and `boost::unordered_flat_map` is deterministically
The observable behavior of `boost::unordered_flat_set`/`unordered_node_set` and `boost::unordered_flat_map`/`unordered_node_map` is deterministically
identical across different compilers as long as their ``std::size_type``s are the same size and the user-provided
hash function and equality predicate are also interoperable
&#8212;this includes elements being ordered in exactly the same way for the same sequence of
+2
View File
@@ -8,3 +8,5 @@ include::unordered_multiset.adoc[]
include::hash_traits.adoc[]
include::unordered_flat_map.adoc[]
include::unordered_flat_set.adoc[]
include::unordered_node_map.adoc[]
include::unordered_node_set.adoc[]
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+443 -117
View File
@@ -1,6 +1,7 @@
/* Fast open-addressing hash table.
*
* Copyright 2022-2023 Joaquin M Lopez Munoz.
* Copyright 2023 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)
@@ -38,12 +39,24 @@
#include <type_traits>
#include <utility>
#if defined(__SSE2__)||\
#if !defined(BOOST_UNORDERED_DISABLE_SSE2)
#if defined(BOOST_UNORDERED_ENABLE_SSE2)|| \
defined(__SSE2__)|| \
defined(_M_X64)||(defined(_M_IX86_FP)&&_M_IX86_FP>=2)
#define BOOST_UNORDERED_SSE2
#include <emmintrin.h>
#elif defined(__ARM_NEON)&&!defined(__ARM_BIG_ENDIAN)
#endif
#endif
#if !defined(BOOST_UNORDERED_DISABLE_NEON)
#if defined(BOOST_UNORDERED_ENABLE_NEON)||\
(defined(__ARM_NEON)&&!defined(__ARM_BIG_ENDIAN))
#define BOOST_UNORDERED_LITTLE_ENDIAN_NEON
#endif
#endif
#if defined(BOOST_UNORDERED_SSE2)
#include <emmintrin.h>
#elif defined(BOOST_UNORDERED_LITTLE_ENDIAN_NEON)
#include <arm_neon.h>
#endif
@@ -148,6 +161,7 @@ static const std::size_t default_bucket_count = 0;
struct group15
{
static constexpr int N=15;
static constexpr bool regular_layout=true;
struct dummy_group_type
{
@@ -173,6 +187,11 @@ struct group15
return at(pos)==sentinel_;
}
static inline bool is_sentinel(unsigned char* pc)noexcept
{
return *pc==sentinel_;
}
inline void reset(std::size_t pos)
{
BOOST_ASSERT(pos<N);
@@ -219,6 +238,11 @@ struct group15
_mm_cmpeq_epi8(m,_mm_setzero_si128()))&0x7FFF;
}
static inline bool is_occupied(unsigned char* pc)noexcept
{
return *pc!=available_;
}
inline int match_occupied()const
{
return (~match_available())&0x7FFF;
@@ -302,11 +326,179 @@ private:
alignas(16) __m128i m;
};
struct group14
{
static constexpr int N=14;
static constexpr bool regular_layout=true;
struct dummy_group_type
{
alignas(16) unsigned char storage[N+2]={0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0};
};
inline void initialize(){m=_mm_setzero_si128();}
inline void set(std::size_t pos,std::size_t hash)
{
BOOST_ASSERT(pos<N);
at(pos)=reduced_hash(hash);
}
inline void set_sentinel()
{
at(N-1)=sentinel_;
}
inline bool is_sentinel(std::size_t pos)const
{
BOOST_ASSERT(pos<N);
return at(pos)==sentinel_;
}
static inline bool is_sentinel(unsigned char* pc)noexcept
{
return *pc==sentinel_;
}
inline void reset(std::size_t pos)
{
BOOST_ASSERT(pos<N);
at(pos)=available_;
}
static inline void reset(unsigned char* pc)
{
*pc=available_;
}
inline int match(std::size_t hash)const
{
return _mm_movemask_epi8(
_mm_cmpeq_epi8(m,_mm_set1_epi32(match_word(hash))))&0x3FFF;
}
inline bool is_not_overflowed(std::size_t hash)const
{
static constexpr unsigned shift[]={
0x0001,0x0002,0x0004,0x0008,0x0010,0x0020,0x0040,0x0080,
0x0100,0x0200,0x0400,0x0800,0x1000,0x2000,0x4000,0x8000
};
return !(overflow()&shift[hash%16]);
}
inline void mark_overflow(std::size_t hash)
{
overflow()|=static_cast<boost::uint16_t>(1<<(hash%16));
}
static inline bool maybe_caused_overflow(unsigned char* pc)
{
std::size_t pos=reinterpret_cast<uintptr_t>(pc)%sizeof(group14);
auto *pg=reinterpret_cast<group14*>(pc-pos);
return !pg->is_not_overflowed(*pc);
};
inline int match_available()const
{
return _mm_movemask_epi8(
_mm_cmpeq_epi8(m,_mm_setzero_si128()))&0x3FFF;
}
static inline bool is_occupied(unsigned char* pc)noexcept
{
return *pc!=available_;
}
inline int match_occupied()const
{
return (~match_available())&0x3FFF;
}
inline int match_really_occupied()const /* excluding sentinel */
{
return at(N-1)==sentinel_?match_occupied()&0x1FFF:match_occupied();
}
private:
static constexpr unsigned char available_=0,
sentinel_=1;
inline static int match_word(std::size_t hash)
{
static constexpr boost::uint32_t word[]=
{
0x10101010u,0x11111111u,0x02020202u,0x03030303u,0x04040404u,0x05050505u,0x06060606u,0x07070707u,
0x08080808u,0x09090909u,0x0A0A0A0Au,0x0B0B0B0Bu,0x0C0C0C0Cu,0x0D0D0D0Du,0x0E0E0E0Eu,0x0F0F0F0Fu,
0x10101010u,0x11111111u,0x12121212u,0x13131313u,0x14141414u,0x15151515u,0x16161616u,0x17171717u,
0x18181818u,0x19191919u,0x1A1A1A1Au,0x1B1B1B1Bu,0x1C1C1C1Cu,0x1D1D1D1Du,0x1E1E1E1Eu,0x1F1F1F1Fu,
0x20202020u,0x21212121u,0x22222222u,0x23232323u,0x24242424u,0x25252525u,0x26262626u,0x27272727u,
0x28282828u,0x29292929u,0x2A2A2A2Au,0x2B2B2B2Bu,0x2C2C2C2Cu,0x2D2D2D2Du,0x2E2E2E2Eu,0x2F2F2F2Fu,
0x30303030u,0x31313131u,0x32323232u,0x33333333u,0x34343434u,0x35353535u,0x36363636u,0x37373737u,
0x38383838u,0x39393939u,0x3A3A3A3Au,0x3B3B3B3Bu,0x3C3C3C3Cu,0x3D3D3D3Du,0x3E3E3E3Eu,0x3F3F3F3Fu,
0x40404040u,0x41414141u,0x42424242u,0x43434343u,0x44444444u,0x45454545u,0x46464646u,0x47474747u,
0x48484848u,0x49494949u,0x4A4A4A4Au,0x4B4B4B4Bu,0x4C4C4C4Cu,0x4D4D4D4Du,0x4E4E4E4Eu,0x4F4F4F4Fu,
0x50505050u,0x51515151u,0x52525252u,0x53535353u,0x54545454u,0x55555555u,0x56565656u,0x57575757u,
0x58585858u,0x59595959u,0x5A5A5A5Au,0x5B5B5B5Bu,0x5C5C5C5Cu,0x5D5D5D5Du,0x5E5E5E5Eu,0x5F5F5F5Fu,
0x60606060u,0x61616161u,0x62626262u,0x63636363u,0x64646464u,0x65656565u,0x66666666u,0x67676767u,
0x68686868u,0x69696969u,0x6A6A6A6Au,0x6B6B6B6Bu,0x6C6C6C6Cu,0x6D6D6D6Du,0x6E6E6E6Eu,0x6F6F6F6Fu,
0x70707070u,0x71717171u,0x72727272u,0x73737373u,0x74747474u,0x75757575u,0x76767676u,0x77777777u,
0x78787878u,0x79797979u,0x7A7A7A7Au,0x7B7B7B7Bu,0x7C7C7C7Cu,0x7D7D7D7Du,0x7E7E7E7Eu,0x7F7F7F7Fu,
0x80808080u,0x81818181u,0x82828282u,0x83838383u,0x84848484u,0x85858585u,0x86868686u,0x87878787u,
0x88888888u,0x89898989u,0x8A8A8A8Au,0x8B8B8B8Bu,0x8C8C8C8Cu,0x8D8D8D8Du,0x8E8E8E8Eu,0x8F8F8F8Fu,
0x90909090u,0x91919191u,0x92929292u,0x93939393u,0x94949494u,0x95959595u,0x96969696u,0x97979797u,
0x98989898u,0x99999999u,0x9A9A9A9Au,0x9B9B9B9Bu,0x9C9C9C9Cu,0x9D9D9D9Du,0x9E9E9E9Eu,0x9F9F9F9Fu,
0xA0A0A0A0u,0xA1A1A1A1u,0xA2A2A2A2u,0xA3A3A3A3u,0xA4A4A4A4u,0xA5A5A5A5u,0xA6A6A6A6u,0xA7A7A7A7u,
0xA8A8A8A8u,0xA9A9A9A9u,0xAAAAAAAAu,0xABABABABu,0xACACACACu,0xADADADADu,0xAEAEAEAEu,0xAFAFAFAFu,
0xB0B0B0B0u,0xB1B1B1B1u,0xB2B2B2B2u,0xB3B3B3B3u,0xB4B4B4B4u,0xB5B5B5B5u,0xB6B6B6B6u,0xB7B7B7B7u,
0xB8B8B8B8u,0xB9B9B9B9u,0xBABABABAu,0xBBBBBBBBu,0xBCBCBCBCu,0xBDBDBDBDu,0xBEBEBEBEu,0xBFBFBFBFu,
0xC0C0C0C0u,0xC1C1C1C1u,0xC2C2C2C2u,0xC3C3C3C3u,0xC4C4C4C4u,0xC5C5C5C5u,0xC6C6C6C6u,0xC7C7C7C7u,
0xC8C8C8C8u,0xC9C9C9C9u,0xCACACACAu,0xCBCBCBCBu,0xCCCCCCCCu,0xCDCDCDCDu,0xCECECECEu,0xCFCFCFCFu,
0xD0D0D0D0u,0xD1D1D1D1u,0xD2D2D2D2u,0xD3D3D3D3u,0xD4D4D4D4u,0xD5D5D5D5u,0xD6D6D6D6u,0xD7D7D7D7u,
0xD8D8D8D8u,0xD9D9D9D9u,0xDADADADAu,0xDBDBDBDBu,0xDCDCDCDCu,0xDDDDDDDDu,0xDEDEDEDEu,0xDFDFDFDFu,
0xE0E0E0E0u,0xE1E1E1E1u,0xE2E2E2E2u,0xE3E3E3E3u,0xE4E4E4E4u,0xE5E5E5E5u,0xE6E6E6E6u,0xE7E7E7E7u,
0xE8E8E8E8u,0xE9E9E9E9u,0xEAEAEAEAu,0xEBEBEBEBu,0xECECECECu,0xEDEDEDEDu,0xEEEEEEEEu,0xEFEFEFEFu,
0xF0F0F0F0u,0xF1F1F1F1u,0xF2F2F2F2u,0xF3F3F3F3u,0xF4F4F4F4u,0xF5F5F5F5u,0xF6F6F6F6u,0xF7F7F7F7u,
0xF8F8F8F8u,0xF9F9F9F9u,0xFAFAFAFAu,0xFBFBFBFBu,0xFCFCFCFCu,0xFDFDFDFDu,0xFEFEFEFEu,0xFFFFFFFFu,
};
return (int)word[narrow_cast<unsigned char>(hash)];
}
inline static unsigned char reduced_hash(std::size_t hash)
{
return narrow_cast<unsigned char>(match_word(hash));
}
inline unsigned char& at(std::size_t pos)
{
return reinterpret_cast<unsigned char*>(&m)[pos];
}
inline unsigned char at(std::size_t pos)const
{
return reinterpret_cast<const unsigned char*>(&m)[pos];
}
inline boost::uint16_t& overflow()
{
return reinterpret_cast<boost::uint16_t*>(&m)[7];
}
inline boost::uint16_t overflow()const
{
return reinterpret_cast<boost::uint16_t const*>(&m)[7];
}
alignas(16) __m128i m;
};
#elif defined(BOOST_UNORDERED_LITTLE_ENDIAN_NEON)
struct group15
{
static constexpr int N=15;
static constexpr bool regular_layout=true;
struct dummy_group_type
{
@@ -332,6 +524,11 @@ struct group15
return pos==N-1&&at(N-1)==sentinel_;
}
static inline bool is_sentinel(unsigned char* pc)noexcept
{
return *pc==sentinel_;
}
inline void reset(std::size_t pos)
{
BOOST_ASSERT(pos<N);
@@ -373,6 +570,11 @@ struct group15
return simde_mm_movemask_epi8(vceqq_s8(m,vdupq_n_s8(0)))&0x7FFF;
}
static inline bool is_occupied(unsigned char* pc)noexcept
{
return *pc!=available_;
}
inline int match_occupied()const
{
return simde_mm_movemask_epi8(
@@ -465,6 +667,7 @@ private:
struct group15
{
static constexpr int N=15;
static constexpr bool regular_layout=false;
struct dummy_group_type
{
@@ -796,8 +999,7 @@ class table;
* - pg = pc-n
*
* (for explanatory purposes pg and pc are treated above as if they were memory
* addresses rather than pointers).The main drawback of this two-pointer
* representation is that iterator increment is relatively slow.
* addresses rather than pointers).
*
* p = nullptr is conventionally used to mark end() iterators.
*/
@@ -805,12 +1007,18 @@ class table;
/* internal conversion from const_iterator to iterator */
class const_iterator_cast_tag {};
template<typename Value,typename Group,bool Const>
template<typename TypePolicy,typename Group,bool Const>
class table_iterator
{
using type_policy=TypePolicy;
using table_element_type=typename type_policy::element_type;
using group_type=Group;
static constexpr auto N=group_type::N;
static constexpr auto regular_layout=group_type::regular_layout;
public:
using difference_type=std::ptrdiff_t;
using value_type=Value;
using value_type=typename type_policy::value_type;
using pointer=
typename std::conditional<Const,value_type const*,value_type*>::type;
using reference=
@@ -821,14 +1029,15 @@ public:
table_iterator()=default;
template<bool Const2,typename std::enable_if<!Const2>::type* =nullptr>
table_iterator(const table_iterator<Value,Group,Const2>& x):
table_iterator(const table_iterator<TypePolicy,Group,Const2>& x):
pc{x.pc},p{x.p}{}
table_iterator(
const_iterator_cast_tag, const table_iterator<Value,Group,true>& x):
const_iterator_cast_tag, const table_iterator<TypePolicy,Group,true>& x):
pc{x.pc},p{x.p}{}
inline reference operator*()const noexcept{return *p;}
inline pointer operator->()const noexcept{return p;}
inline reference operator*()const noexcept{return type_policy::value_from(*p);}
inline pointer operator->()const noexcept
{return std::addressof(type_policy::value_from(*p));}
inline table_iterator& operator++()noexcept{increment();return *this;}
inline table_iterator operator++(int)noexcept
{auto x=*this;increment();return x;}
@@ -843,33 +1052,65 @@ private:
template<typename,typename,bool> friend class table_iterator;
template<typename,typename,typename,typename> friend class table;
table_iterator(Group* pg,std::size_t n,const Value* p_):
pc{reinterpret_cast<unsigned char*>(const_cast<Group*>(pg))+n},
p{const_cast<Value*>(p_)}
table_iterator(Group* pg,std::size_t n,const table_element_type* p_):
pc{reinterpret_cast<unsigned char*>(const_cast<group_type*>(pg))+n},
p{const_cast<table_element_type*>(p_)}
{}
inline std::size_t rebase() noexcept
{
std::size_t off=reinterpret_cast<uintptr_t>(pc)%sizeof(Group);
pc-=off;
return off;
}
inline void increment()noexcept
{
std::size_t n0=rebase();
increment(std::integral_constant<bool,regular_layout>{});
}
int mask=(reinterpret_cast<Group*>(pc)->match_occupied()>>(n0+1))<<(n0+1);
inline void increment(std::true_type /* regular layout */)noexcept
{
for(;;){
++p;
if(reinterpret_cast<uintptr_t>(pc)%sizeof(group_type)==N-1){
pc+=sizeof(group_type)-(N-1);
break;
}
++pc;
if(!group_type::is_occupied(pc))continue;
if(BOOST_UNLIKELY(group_type::is_sentinel(pc)))p=nullptr;
return;
}
for(;;){
int mask=reinterpret_cast<group_type*>(pc)->match_occupied();
if(mask!=0){
auto n=unchecked_countr_zero(mask);
if(BOOST_UNLIKELY(reinterpret_cast<group_type*>(pc)->is_sentinel(n))){
p=nullptr;
}
else{
pc+=n;
p+=n;
}
return;
}
pc+=sizeof(group_type);
p+=N;
}
}
inline void increment(std::false_type /* interleaved */)noexcept
{
std::size_t n0=reinterpret_cast<uintptr_t>(pc)%sizeof(group_type);
pc-=n0;
int mask=(
reinterpret_cast<group_type*>(pc)->match_occupied()>>(n0+1))<<(n0+1);
if(!mask){
do{
pc+=sizeof(Group);
p+=Group::N;
pc+=sizeof(group_type);
p+=N;
}
while((mask=reinterpret_cast<Group*>(pc)->match_occupied())==0);
while((mask=reinterpret_cast<group_type*>(pc)->match_occupied())==0);
}
auto n=unchecked_countr_zero(mask);
if(BOOST_UNLIKELY(reinterpret_cast<Group*>(pc)->is_sentinel(n))){
if(BOOST_UNLIKELY(reinterpret_cast<group_type*>(pc)->is_sentinel(n))){
p=nullptr;
}
else{
@@ -879,8 +1120,8 @@ private:
}
}
unsigned char *pc=nullptr;
Value *p=nullptr;
unsigned char *pc=nullptr;
table_element_type *p=nullptr;
};
/* table_arrays controls allocation, initialization and deallocation of
@@ -921,7 +1162,9 @@ struct table_arrays
template<typename Allocator>
static table_arrays new_(Allocator& al,std::size_t n)
{
using alloc_traits=boost::allocator_traits<Allocator>;
using storage_allocator=
typename boost::allocator_rebind<Allocator, Value>::type;
using storage_traits=boost::allocator_traits<storage_allocator>;
auto groups_size_index=size_index_for<group_type,size_policy>(n);
auto groups_size=size_policy::size(groups_size_index);
@@ -931,8 +1174,9 @@ struct table_arrays
arrays.groups=dummy_groups<group_type,size_policy::min_size()>();
}
else{
arrays.elements=
boost::to_address(alloc_traits::allocate(al,buffer_size(groups_size)));
auto sal=storage_allocator(al);
arrays.elements=boost::to_address(
storage_traits::allocate(sal,buffer_size(groups_size)));
/* Align arrays.groups to sizeof(group_type). table_iterator critically
* depends on such alignment for its increment operation.
@@ -956,13 +1200,15 @@ struct table_arrays
template<typename Allocator>
static void delete_(Allocator& al,table_arrays& arrays)noexcept
{
using alloc_traits=boost::allocator_traits<Allocator>;
using pointer=typename alloc_traits::pointer;
using storage_alloc=typename boost::allocator_rebind<Allocator,Value>::type;
using storage_traits=boost::allocator_traits<storage_alloc>;
using pointer=typename storage_traits::pointer;
using pointer_traits=boost::pointer_traits<pointer>;
auto sal=storage_alloc(al);
if(arrays.elements){
alloc_traits::deallocate(
al,pointer_traits::pointer_to(*arrays.elements),
storage_traits::deallocate(
sal,pointer_traits::pointer_to(*arrays.elements),
buffer_size(arrays.groups_size_mask+1));
}
}
@@ -1101,51 +1347,85 @@ _STL_RESTORE_DEPRECATED_WARNING
#pragma warning(disable:4702)
#endif
/* We expose the hard-coded max load factor so that tests can use it without
* needing to pull it from an instantiated class template such as the table
* class
*/
constexpr static float const mlf = 0.875f;
template <class T>
union uninitialized_storage
{
T t_;
uninitialized_storage(){}
~uninitialized_storage(){}
};
/* foa::table interface departs in a number of ways from that of C++ unordered
* associative containers because it's not for end-user consumption
* (boost::unordered_flat_[map|set] wrappers complete it as appropriate) and,
* more importantly, because of fundamental restrictions imposed by open
* addressing:
*
* - value_type must be moveable.
* - Pointer stability is not kept under rehashing.
* (boost::unordered_[flat|node]_[map|set]) wrappers complete it as
* appropriate).
*
* The table supports two main modes of operation: node-based and flat. In the
* node-based case, buckets store pointers to individually heap-allocated
* elements. For flat, buckets directly store elements.
*
* For both tables:
*
* - begin() is not O(1).
* - No bucket API.
* - Load factor is fixed and can't be set by the user.
* - No extract API.
*
* For the inline table:
*
* - value_type must be moveable.
* - Pointer stability is not kept under rehashing.
* - No extract API.
*
* The TypePolicy template parameter is used to generate instantiations
* suitable for either maps or sets, and introduces non-standard init_type:
*
*
* - TypePolicy::key_type and TypePolicy::value_type have the obvious
* meaning.
*
* - TypePolicy::init_type is the type implicitly converted to when
* writing x.insert({...}). For maps, this is std::pair<Key,T> rather
* than std::pair<const Key,T> so that, for instance, x.insert({"hello",0})
* produces a cheaply moveable std::string&& ("hello") rather than
* a copyable const std::string&&. foa::table::insert is extended to accept
* both init_type and value_type references.
* - TypePolicy::move(value_type&) returns a temporary object for value
* transfer on rehashing, move copy/assignment, and merge. For maps, this
* object is a std::pair<Key&&,T&&>, which is generally cheaper to move
* than std::pair<const Key,T>&& because of the constness in Key.
*
* - TypePolicy::construct and TypePolicy::destroy are used for the
* construction and destruction of the internal types: value_type, init_type
* and element_type.
*
* - TypePolicy::move is used to provide move semantics for the internal
* types used by the container during rehashing and emplace. These types
* are init_type, value_type and emplace_type. During insertion, a
* stack-local type will be created based on the constructibility of the
* value_type and the supplied arguments. TypePolicy::move is used here
* for transfer of ownership. Similarly, TypePolicy::move is also used
* during rehashing when elements are moved to the new table.
*
* - TypePolicy::extract returns a const reference to the key part of
* a value of type value_type, init_type or
* a value of type value_type, init_type, element_type or
* decltype(TypePolicy::move(...)).
*
* try_emplace, erase and find support heterogenous lookup by default, that is,
* without checking for any ::is_transparent typedefs --the checking is done by
* boost::unordered_flat_[map|set].
*
* At the moment, we're not supporting allocators with fancy pointers.
* Allocator::pointer must be convertible to/from regular pointers.
*
* - TypePolicy::element_type is the type that table_arrays uses when
* allocating buckets. For flat containers, this is value_type. For node
* containers, this is a strong typedef to value_type*.
*
* - TypePolicy::value_from returns a mutable reference to value_type from
* a given element_type. This is used when elements of the table themselves
* need to be moved, such as during move construction/assignment when
* allocators are unequal and there is no propagation. For all other cases,
* the element_type itself is moved.
*
* try_emplace, erase and find support heterogenous lookup by default, that is,
* without checking for any ::is_transparent typedefs --the checking is done by
* boost::unordered_[flat|node]_[map|set].
*/
/* We pull this out so the tests don't have to rely on a magic constant or
* instantiate the table class template as it can be quite gory.
*/
constexpr static float const mlf = 0.875f;
template<typename TypePolicy,typename Hash,typename Pred,typename Allocator>
class
@@ -1159,7 +1439,11 @@ table:empty_value<Hash,0>,empty_value<Pred,1>,empty_value<Allocator,2>
using pred_base=empty_value<Pred,1>;
using allocator_base=empty_value<Allocator,2>;
using type_policy=TypePolicy;
#if defined(BOOST_UNORDERED_SSE2)
using group_type=group14;
#else
using group_type=group15;
#endif
static constexpr auto N=group_type::N;
using size_policy=pow2_size_policy;
using prober=pow2_quadratic_prober;
@@ -1174,6 +1458,7 @@ public:
using key_type=typename type_policy::key_type;
using init_type=typename type_policy::init_type;
using value_type=typename type_policy::value_type;
using element_type=typename type_policy::element_type;
private:
static constexpr bool has_mutable_iterator=
@@ -1189,10 +1474,10 @@ public:
using const_reference=const value_type&;
using size_type=std::size_t;
using difference_type=std::ptrdiff_t;
using const_iterator=table_iterator<value_type,group_type,true>;
using const_iterator=table_iterator<type_policy,group_type,true>;
using iterator=typename std::conditional<
has_mutable_iterator,
table_iterator<value_type,group_type,false>,
table_iterator<type_policy,group_type,false>,
const_iterator>::type;
table(
@@ -1243,15 +1528,15 @@ public:
/* This works because subsequent x.clear() does not depend on the
* elements' values.
*/
x.for_all_elements([this](value_type* p){
unchecked_insert(type_policy::move(*p));
x.for_all_elements([this](element_type* p){
unchecked_insert(type_policy::move(type_policy::value_from(*p)));
});
}
}
~table()noexcept
{
for_all_elements([this](value_type* p){
for_all_elements([this](element_type* p){
destroy_element(p);
});
delete_arrays(arrays);
@@ -1340,8 +1625,8 @@ public:
/* This works because subsequent x.clear() does not depend on the
* elements' values.
*/
x.for_all_elements([this](value_type* p){
unchecked_insert(type_policy::move(*p));
x.for_all_elements([this](element_type* p){
unchecked_insert(type_policy::move(type_policy::value_from(*p)));
});
}
}
@@ -1357,7 +1642,7 @@ public:
iterator begin()noexcept
{
iterator it{arrays.groups,0,arrays.elements};
if(!(arrays.groups[0].match_occupied()&0x1))++it;
if(arrays.elements&&!(arrays.groups[0].match_occupied()&0x1))++it;
return it;
}
@@ -1375,14 +1660,25 @@ public:
template<typename... Args>
BOOST_FORCEINLINE std::pair<iterator,bool> emplace(Args&&... args)
{
using emplace_type = typename std::conditional<
std::is_constructible<
init_type, Args...
>::value,
using emplace_type=typename std::conditional<
std::is_constructible<init_type,Args...>::value,
init_type,
value_type
>::type;
return emplace_impl(emplace_type(std::forward<Args>(args)...));
using insert_type=typename std::conditional<
std::is_constructible<
value_type,emplace_type>::value,
emplace_type,element_type
>::type;
uninitialized_storage<insert_type> s;
auto *p=std::addressof(s.t_);
type_policy::construct(al(),p,std::forward<Args>(args)...);
destroy_on_exit<insert_type> guard{al(),p};
return emplace_impl(type_policy::move(*p));
}
template<typename Key,typename... Args>
@@ -1409,6 +1705,14 @@ public:
BOOST_FORCEINLINE std::pair<iterator,bool>
insert(value_type&& x){return emplace_impl(std::move(x));}
template<typename T=element_type>
BOOST_FORCEINLINE
typename std::enable_if<
!std::is_same<T,value_type>::value,
std::pair<iterator,bool>
>::type
insert(element_type&& x){return emplace_impl(std::move(x));}
template<
bool dependent_value=false,
typename std::enable_if<
@@ -1483,14 +1787,21 @@ public:
}
}
element_type extract(const_iterator pos)
{
BOOST_ASSERT(pos!=end());
erase_on_exit e{*this,pos};
(void)e;
return std::move(*pos.p);
}
// TODO: should we accept different allocator too?
template<typename Hash2,typename Pred2>
void merge(table<TypePolicy,Hash2,Pred2,Allocator>& x)
{
x.for_all_elements([&,this](group_type* pg,unsigned int n,value_type* p){
if(emplace_impl(type_policy::move(*p)).second){
x.erase(iterator{pg,n,p});
}
x.for_all_elements([&,this](group_type* pg,unsigned int n,element_type* p){
erase_on_exit e{x,{pg,n,p}};
if(!emplace_impl(type_policy::move(*p)).second)e.rollback();
});
}
@@ -1550,7 +1861,7 @@ public:
private:
template<typename,typename,typename,typename> friend class table;
using arrays_type=table_arrays<value_type,group_type,size_policy>;
using arrays_type=table_arrays<element_type,group_type,size_policy>;
struct clear_on_exit
{
@@ -1558,6 +1869,26 @@ private:
table& x;
};
struct erase_on_exit
{
erase_on_exit(table& x_,const_iterator it_):x{x_},it{it_}{}
~erase_on_exit(){if(!rollback_)x.erase(it);}
void rollback(){rollback_=true;}
table& x;
const_iterator it;
bool rollback_=false;
};
template <class T>
struct destroy_on_exit
{
Allocator &a;
T *p;
~destroy_on_exit(){type_policy::destroy(a,p);};
};
Hash& h(){return hash_base::get();}
const Hash& h()const{return hash_base::get();}
Pred& pred(){return pred_base::get();}
@@ -1576,13 +1907,13 @@ private:
}
template<typename... Args>
void construct_element(value_type* p,Args&&... args)
void construct_element(element_type* p,Args&&... args)
{
alloc_traits::construct(al(),p,std::forward<Args>(args)...);
type_policy::construct(al(),p,std::forward<Args>(args)...);
}
template<typename... Args>
void construct_element(value_type* p,try_emplace_args_t,Args&&... args)
void construct_element(element_type* p,try_emplace_args_t,Args&&... args)
{
construct_element_from_try_emplace_args(
p,
@@ -1592,9 +1923,9 @@ private:
template<typename Key,typename... Args>
void construct_element_from_try_emplace_args(
value_type* p,std::false_type,Key&& x,Args&&... args)
element_type* p,std::false_type,Key&& x,Args&&... args)
{
alloc_traits::construct(
type_policy::construct(
al(),p,
std::piecewise_construct,
std::forward_as_tuple(std::forward<Key>(x)),
@@ -1607,21 +1938,21 @@ private:
template<typename Key>
void construct_element_from_try_emplace_args(
value_type* p,std::true_type,Key&& x)
element_type* p,std::true_type,Key&& x)
{
alloc_traits::construct(al(),p,std::forward<Key>(x));
type_policy::construct(al(),p,std::forward<Key>(x));
}
void destroy_element(value_type* p)noexcept
void destroy_element(element_type* p)noexcept
{
alloc_traits::destroy(al(),p);
type_policy::destroy(al(),p);
}
struct destroy_element_on_exit
{
~destroy_element_on_exit(){this_->destroy_element(p);}
table *this_;
value_type *p;
table *this_;
element_type *p;
};
void copy_elements_from(const table& x)
@@ -1632,7 +1963,7 @@ private:
fast_copy_elements_from(x);
}
else{
x.for_all_elements([this](const value_type* p){
x.for_all_elements([this](const element_type* p){
unchecked_insert(*p);
});
}
@@ -1657,9 +1988,9 @@ private:
bool,
#if BOOST_WORKAROUND(BOOST_LIBSTDCXX_VERSION,<50000)
/* std::is_trivially_copy_constructible not provided */
boost::has_trivial_copy<value_type>::value
boost::has_trivial_copy<element_type>::value
#else
std::is_trivially_copy_constructible<value_type>::value
std::is_trivially_copy_constructible<element_type>::value
#endif
&&(
is_std_allocator<Allocator>::value||
@@ -1683,14 +2014,14 @@ private:
{
std::size_t num_constructed=0;
BOOST_TRY{
x.for_all_elements([&,this](const value_type* p){
x.for_all_elements([&,this](const element_type* p){
construct_element(arrays.elements+(p-x.arrays.elements),*p);
++num_constructed;
});
}
BOOST_CATCH(...){
if(num_constructed){
x.for_all_elements_while([&,this](const value_type* p){
x.for_all_elements_while([&,this](const element_type* p){
destroy_element(arrays.elements+(p-x.arrays.elements));
return --num_constructed!=0;
});
@@ -1760,7 +2091,7 @@ private:
return size_policy::position(hash,arrays_.groups_size_index);
}
static inline void prefetch_elements(const value_type* p)
static inline void prefetch_elements(const element_type* p)
{
/* We have experimentally confirmed that ARM architectures get a higher
* speedup when around the first half of the element slots in a group are
@@ -1896,20 +2227,20 @@ private:
{
std::size_t num_destroyed=0;
BOOST_TRY{
for_all_elements([&,this](value_type* p){
for_all_elements([&,this](element_type* p){
nosize_transfer_element(p,new_arrays_,num_destroyed);
});
}
BOOST_CATCH(...){
if(num_destroyed){
for_all_elements_while(
[&,this](group_type* pg,unsigned int n,value_type*){
[&,this](group_type* pg,unsigned int n,element_type*){
recover_slot(pg,n);
return --num_destroyed!=0;
}
);
}
for_all_elements(new_arrays_,[this](value_type* p){
for_all_elements(new_arrays_,[this](element_type* p){
destroy_element(p);
});
delete_arrays(new_arrays_);
@@ -1920,7 +2251,7 @@ private:
/* either all moved and destroyed or all copied */
BOOST_ASSERT(num_destroyed==size()||num_destroyed==0);
if(num_destroyed!=size()){
for_all_elements([this](value_type* p){
for_all_elements([this](element_type* p){
destroy_element(p);
});
}
@@ -1955,18 +2286,19 @@ private:
}
void nosize_transfer_element(
value_type* p,const arrays_type& arrays_,std::size_t& num_destroyed)
element_type* p,const arrays_type& arrays_,std::size_t& num_destroyed)
{
nosize_transfer_element(
p,hash_for(key_from(*p)),arrays_,num_destroyed,
std::integral_constant< /* std::move_if_noexcept semantics */
bool,
std::is_nothrow_move_constructible<init_type>::value||
!std::is_copy_constructible<init_type>::value>{});
!std::is_same<element_type,value_type>::value||
!std::is_copy_constructible<element_type>::value>{});
}
void nosize_transfer_element(
value_type* p,std::size_t hash,const arrays_type& arrays_,
element_type* p,std::size_t hash,const arrays_type& arrays_,
std::size_t& num_destroyed,std::true_type /* ->move */)
{
/* Destroy p even if an an exception is thrown in the middle of move
@@ -1980,12 +2312,12 @@ private:
}
void nosize_transfer_element(
value_type* p,std::size_t hash,const arrays_type& arrays_,
element_type* p,std::size_t hash,const arrays_type& arrays_,
std::size_t& /*num_destroyed*/,std::false_type /* ->copy */)
{
nosize_unchecked_emplace_at(
arrays_,position_for(hash,arrays_),hash,
const_cast<const value_type&>(*p));
const_cast<const element_type&>(*p));
}
template<typename... Args>
@@ -2022,8 +2354,8 @@ private:
std::size_t erase_if_impl(Predicate pr)
{
std::size_t s=size();
for_all_elements([&,this](group_type* pg,unsigned int n,value_type* p){
if(pr(*p)) erase(iterator{pg,n,p});
for_all_elements([&,this](group_type* pg,unsigned int n,element_type* p){
if(pr(type_policy::value_from(*p))) erase(iterator{pg,n,p});
});
return std::size_t(s-size());
}
@@ -2038,7 +2370,7 @@ private:
static auto for_all_elements(const arrays_type& arrays_,F f)
->decltype(f(nullptr),void())
{
for_all_elements_while(arrays_,[&](value_type* p){f(p);return true;});
for_all_elements_while(arrays_,[&](element_type* p){f(p);return true;});
}
template<typename F>
@@ -2046,7 +2378,7 @@ private:
->decltype(f(nullptr,0,nullptr),void())
{
for_all_elements_while(
arrays_,[&](group_type* pg,unsigned int n,value_type* p)
arrays_,[&](group_type* pg,unsigned int n,element_type* p)
{f(pg,n,p);return true;});
}
@@ -2061,7 +2393,7 @@ private:
->decltype(f(nullptr),void())
{
for_all_elements_while(
arrays_,[&](group_type*,unsigned int,value_type* p){return f(p);});
arrays_,[&](group_type*,unsigned int,element_type* p){return f(p);});
}
template<typename F>
@@ -2103,13 +2435,7 @@ private:
} /* namespace unordered */
} /* namespace boost */
#undef BOOST_UNORDERED_STATIC_ASSERT_HASH_PRED
#undef BOOST_UNORDERED_ASSUME
#undef BOOST_UNORDERED_HAS_BUILTIN
#undef BOOST_UNORDERED_STATIC_ASSERT_HASH_PRED
#ifdef BOOST_UNORDERED_LITTLE_ENDIAN_NEON
#undef BOOST_UNORDERED_LITTLE_ENDIAN_NEON
#endif
#ifdef BOOST_UNORDERED_SSE2
#undef BOOST_UNORDERED_SSE2
#endif
#endif
@@ -0,0 +1,60 @@
/* Copyright 2023 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)
*
* See https://www.boost.org/libs/unordered for library home page.
*/
#ifndef BOOST_UNORDERED_DETAIL_FOA_ELEMENT_TYPE_HPP
#define BOOST_UNORDERED_DETAIL_FOA_ELEMENT_TYPE_HPP
namespace boost{
namespace unordered{
namespace detail{
namespace foa{
template<class T>
struct element_type
{
using value_type=T;
value_type* p;
/*
* we use a deleted copy constructor here so the type is no longer
* trivially copy-constructible which inhibits our memcpy
* optimizations when copying the tables
*/
element_type() = default;
element_type(value_type* p_):p(p_){}
element_type(element_type const&) = delete;
element_type(element_type&& rhs) noexcept
{
p = rhs.p;
rhs.p = nullptr;
}
element_type& operator=(element_type const&)=delete;
element_type& operator=(element_type&& rhs)noexcept
{
if (this!=&rhs){
p=rhs.p;
rhs.p=nullptr;
}
return *this;
}
void swap(element_type& rhs)noexcept
{
auto tmp=p;
p=rhs.p;
rhs.p=tmp;
}
};
}
}
}
}
#endif // BOOST_UNORDERED_DETAIL_FOA_ELEMENT_TYPE_HPP
@@ -0,0 +1,210 @@
/* Copyright 2023 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)
*
* See https://www.boost.org/libs/unordered for library home page.
*/
#ifndef BOOST_UNORDERED_DETAIL_FOA_NODE_HANDLE_HPP
#define BOOST_UNORDERED_DETAIL_FOA_NODE_HANDLE_HPP
#include <boost/config.hpp>
#include <boost/core/allocator_access.hpp>
namespace boost{
namespace unordered{
namespace detail{
namespace foa{
template <class Iterator,class NodeType>
struct insert_return_type
{
Iterator position;
bool inserted;
NodeType node;
};
template <class T>
union opt_storage {
BOOST_ATTRIBUTE_NO_UNIQUE_ADDRESS T t_;
opt_storage(){}
~opt_storage(){}
};
template <class TypePolicy,class Allocator>
struct node_handle_base
{
protected:
using type_policy=TypePolicy;
using element_type=typename type_policy::element_type;
public:
using allocator_type = Allocator;
private:
using node_value_type=typename type_policy::value_type;
element_type p_;
BOOST_ATTRIBUTE_NO_UNIQUE_ADDRESS opt_storage<Allocator> a_;
protected:
node_value_type& data()noexcept
{
return *(p_.p);
}
node_value_type const& data()const noexcept
{
return *(p_.p);
}
element_type& element()noexcept
{
BOOST_ASSERT(!empty());
return p_;
}
element_type const& element()const noexcept
{
BOOST_ASSERT(!empty());
return p_;
}
Allocator& al()noexcept
{
BOOST_ASSERT(!empty());
return a_.t_;
}
Allocator const& al()const noexcept
{
BOOST_ASSERT(!empty());
return a_.t_;
}
void emplace(element_type&& x,Allocator a)
{
BOOST_ASSERT(empty());
auto* p=x.p;
p_.p=p;
new(&a_.t_)Allocator(a);
x.p=nullptr;
}
void reset()
{
a_.t_.~Allocator();
p_.p=nullptr;
}
public:
constexpr node_handle_base()noexcept:p_{nullptr}{}
node_handle_base(node_handle_base&& nh) noexcept
{
p_.p = nullptr;
if (!nh.empty()){
emplace(std::move(nh.p_),nh.al());
nh.reset();
}
}
node_handle_base& operator=(node_handle_base&& nh)noexcept
{
if(this!=&nh){
if(empty()){
if(nh.empty()){ /* empty(), nh.empty() */
/* nothing to do */
}else{ /* empty(), !nh.empty() */
emplace(std::move(nh.p_),std::move(nh.al()));
nh.reset();
}
}else{
if(nh.empty()){ /* !empty(), nh.empty() */
type_policy::destroy(al(),&p_);
reset();
}else{ /* !empty(), !nh.empty() */
bool const pocma=
boost::allocator_propagate_on_container_move_assignment<
Allocator>::type::value;
BOOST_ASSERT(pocma||al()==nh.al());
type_policy::destroy(al(),&p_);
if(pocma){
al()=std::move(nh.al());
}
p_=std::move(nh.p_);
nh.reset();
}
}
}else{
if(empty()){ /* empty(), nh.empty() */
/* nothing to do */
}else{ /* !empty(), !nh.empty() */
type_policy::destroy(al(),&p_);
reset();
}
}
return *this;
}
~node_handle_base()
{
if(!empty()){
type_policy::destroy(al(),&p_);
reset();
}
}
allocator_type get_allocator()const noexcept{return al();}
explicit operator bool()const noexcept{ return !empty();}
BOOST_ATTRIBUTE_NODISCARD bool empty()const noexcept{return p_.p==nullptr;}
void swap(node_handle_base& nh) noexcept(
boost::allocator_is_always_equal<Allocator>::type::value||
boost::allocator_propagate_on_container_swap<Allocator>::type::value)
{
if(this!=&nh){
if(empty()){
if(nh.empty()) {
/* nothing to do here */
} else {
emplace(std::move(nh.p_), nh.al());
nh.reset();
}
}else{
if(nh.empty()){
nh.emplace(std::move(p_),al());
reset();
}else{
bool const pocs=
boost::allocator_propagate_on_container_swap<
Allocator>::type::value;
BOOST_ASSERT(pocs || al()==nh.al());
using std::swap;
p_.swap(nh.p_);
if(pocs)swap(al(),nh.al());
}
}
}
}
friend
void swap(node_handle_base& lhs,node_handle_base& rhs)
noexcept(noexcept(lhs.swap(rhs)))
{
return lhs.swap(rhs);
}
};
}
}
}
}
#endif // BOOST_UNORDERED_DETAIL_FOA_NODE_HANDLE_HPP
@@ -0,0 +1,21 @@
#ifndef BOOST_UNORDERED_DETAIL_REQUIRES_CXX11_HPP_INCLUDED
#define BOOST_UNORDERED_DETAIL_REQUIRES_CXX11_HPP_INCLUDED
// Copyright 2023 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/config.hpp>
#include <boost/config/pragma_message.hpp>
#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || \
defined(BOOST_NO_CXX11_RVALUE_REFERENCES) || \
defined(BOOST_NO_CXX11_DECLTYPE) || \
defined(BOOST_NO_CXX11_CONSTEXPR) || \
defined(BOOST_NO_CXX11_NOEXCEPT)
BOOST_PRAGMA_MESSAGE("C++03 support is deprecated in Boost.Unordered 1.82 and will be removed in Boost.Unordered 1.84.")
#endif
#endif // #ifndef BOOST_UNORDERED_DETAIL_REQUIRES_CXX11_HPP_INCLUDED
+40 -5
View File
@@ -32,10 +32,8 @@ namespace boost {
#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
namespace detail {
template <class Key, class T> struct flat_map_types
{
using key_type = Key;
using raw_key_type = typename std::remove_const<Key>::type;
@@ -45,19 +43,56 @@ namespace boost {
using moved_type = std::pair<raw_key_type&&, raw_mapped_type&&>;
using value_type = std::pair<Key const, T>;
using element_type = value_type;
static value_type& value_from(element_type& x) { return x; }
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)
static moved_type move(init_type& x)
{
return {std::move(x.first), std::move(x.second)};
}
static moved_type move(element_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))};
}
template <class A, class... Args>
static void construct(A& al, init_type* p, Args&&... args)
{
boost::allocator_construct(al, p, std::forward<Args>(args)...);
}
template <class A, class... Args>
static void construct(A& al, value_type* p, Args&&... args)
{
boost::allocator_construct(al, p, std::forward<Args>(args)...);
}
template <class A> static void destroy(A& al, init_type* p) noexcept
{
boost::allocator_destroy(al, p);
}
template <class A> static void destroy(A& al, value_type* p) noexcept
{
boost::allocator_destroy(al, p);
}
};
} // namespace detail
template <class Key, class T, class Hash, class KeyEqual, class Allocator>
class unordered_flat_map
{
using map_types = detail::flat_map_types<Key, T>;
using table_type = detail::foa::table<map_types, Hash, KeyEqual,
typename boost::allocator_rebind<Allocator,
+26 -5
View File
@@ -30,17 +30,38 @@ namespace boost {
#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
namespace detail {
template <class Key> struct flat_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 element_type = value_type;
static Key& value_from(element_type& x) { return x; }
static element_type&& move(element_type& x) { return std::move(x); }
template <class A, class... Args>
static void construct(A& al, value_type* p, Args&&... args)
{
boost::allocator_construct(al, p, std::forward<Args>(args)...);
}
template <class A> static void destroy(A& al, value_type* p) noexcept
{
boost::allocator_destroy(al, p);
}
};
} // namespace detail
template <class Key, class Hash, class KeyEqual, class Allocator>
class unordered_flat_set
{
using set_types = detail::flat_set_types<Key>;
using table_type = detail::foa::table<set_types, Hash, KeyEqual,
typename boost::allocator_rebind<Allocator,
@@ -15,6 +15,7 @@
#pragma once
#endif
#include <boost/unordered/detail/requires_cxx11.hpp>
#include <boost/core/explicit_operator_bool.hpp>
#include <boost/functional/hash.hpp>
#include <boost/move/move.hpp>
File diff suppressed because it is too large Load Diff
@@ -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_NODE_MAP_FWD_HPP_INCLUDED
#define BOOST_UNORDERED_NODE_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_node_map;
template <class Key, class T, class Hash, class KeyEqual, class Allocator>
bool operator==(
unordered_node_map<Key, T, Hash, KeyEqual, Allocator> const& lhs,
unordered_node_map<Key, T, Hash, KeyEqual, Allocator> const& rhs);
template <class Key, class T, class Hash, class KeyEqual, class Allocator>
bool operator!=(
unordered_node_map<Key, T, Hash, KeyEqual, Allocator> const& lhs,
unordered_node_map<Key, T, Hash, KeyEqual, Allocator> const& rhs);
template <class Key, class T, class Hash, class KeyEqual, class Allocator>
void swap(unordered_node_map<Key, T, Hash, KeyEqual, Allocator>& lhs,
unordered_node_map<Key, T, Hash, KeyEqual, Allocator>& rhs)
noexcept(noexcept(lhs.swap(rhs)));
} // namespace unordered
using boost::unordered::unordered_node_map;
using boost::unordered::swap;
using boost::unordered::operator==;
using boost::unordered::operator!=;
} // namespace boost
#endif
@@ -0,0 +1,764 @@
// 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_NODE_SET_HPP_INCLUDED
#define BOOST_UNORDERED_UNORDERED_NODE_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/foa/element_type.hpp>
#include <boost/unordered/detail/foa/node_handle.hpp>
#include <boost/unordered/detail/type_traits.hpp>
#include <boost/unordered/unordered_node_set_fwd.hpp>
#include <boost/core/allocator_access.hpp>
#include <boost/functional/hash.hpp>
#include <boost/throw_exception.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
namespace detail {
template <class Key> struct node_set_types
{
using key_type = Key;
using init_type = Key;
using value_type = Key;
static Key const& extract(value_type const& key) { return key; }
using element_type=foa::element_type<value_type>;
static value_type& value_from(element_type const& x) { return *x.p; }
static Key const& extract(element_type const& k) { return *k.p; }
static element_type&& move(element_type& x) { return std::move(x); }
static value_type&& move(value_type& x) { return std::move(x); }
template <class A>
static void construct(A& al, element_type* p, element_type const& copy)
{
construct(al, p, *copy.p);
}
template <typename Allocator>
static void construct(
Allocator&, element_type* p, element_type&& x) noexcept
{
p->p = x.p;
x.p = nullptr;
}
template <class A, class... Args>
static void construct(A& al, value_type* p, Args&&... args)
{
boost::allocator_construct(al, p, std::forward<Args>(args)...);
}
template <class A, class... Args>
static void construct(A& al, element_type* p, Args&&... args)
{
p->p = boost::to_address(boost::allocator_allocate(al, 1));
BOOST_TRY
{
boost::allocator_construct(al, p->p, std::forward<Args>(args)...);
}
BOOST_CATCH(...)
{
boost::allocator_deallocate(al,
boost::pointer_traits<
typename boost::allocator_pointer<A>::type>::pointer_to(*p->p),
1);
BOOST_RETHROW
}
BOOST_CATCH_END
}
template <class A> static void destroy(A& al, value_type* p) noexcept
{
boost::allocator_destroy(al, p);
}
template <class A> static void destroy(A& al, element_type* p) noexcept
{
if (p->p) {
destroy(al, p->p);
boost::allocator_deallocate(al,
boost::pointer_traits<typename boost::allocator_pointer<
A>::type>::pointer_to(*(p->p)),
1);
}
}
};
template <class TypePolicy, class Allocator>
struct node_set_handle
: public detail::foa::node_handle_base<TypePolicy, Allocator>
{
private:
using base_type = detail::foa::node_handle_base<TypePolicy, Allocator>;
using typename base_type::type_policy;
template <class Key, class Hash, class Pred, class Alloc>
friend class boost::unordered::unordered_node_set;
public:
using value_type = typename TypePolicy::value_type;
constexpr node_set_handle() noexcept = default;
node_set_handle(node_set_handle&& nh) noexcept = default;
node_set_handle& operator=(node_set_handle&&) noexcept = default;
value_type& value() const
{
BOOST_ASSERT(!this->empty());
return const_cast<value_type&>(this->data());
}
};
} // namespace detail
template <class Key, class Hash, class KeyEqual, class Allocator>
class unordered_node_set
{
using set_types = detail::node_set_types<Key>;
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_node_set<K, H, KE, A>::size_type friend erase_if(
unordered_node_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;
using node_type = detail::node_set_handle<set_types,
typename boost::allocator_rebind<Allocator,
typename set_types::value_type>::type>;
using insert_return_type =
detail::foa::insert_return_type<iterator, node_type>;
unordered_node_set() : unordered_node_set(0) {}
explicit unordered_node_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_node_set(size_type n, allocator_type const& a)
: unordered_node_set(n, hasher(), key_equal(), a)
{
}
unordered_node_set(size_type n, hasher const& h, allocator_type const& a)
: unordered_node_set(n, h, key_equal(), a)
{
}
template <class InputIterator>
unordered_node_set(
InputIterator f, InputIterator l, allocator_type const& a)
: unordered_node_set(f, l, size_type(0), hasher(), key_equal(), a)
{
}
explicit unordered_node_set(allocator_type const& a)
: unordered_node_set(0, a)
{
}
template <class Iterator>
unordered_node_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_node_set(n, h, pred, a)
{
this->insert(first, last);
}
template <class InputIt>
unordered_node_set(
InputIt first, InputIt last, size_type n, allocator_type const& a)
: unordered_node_set(first, last, n, hasher(), key_equal(), a)
{
}
template <class Iterator>
unordered_node_set(Iterator first, Iterator last, size_type n,
hasher const& h, allocator_type const& a)
: unordered_node_set(first, last, n, h, key_equal(), a)
{
}
unordered_node_set(unordered_node_set const& other) : table_(other.table_)
{
}
unordered_node_set(
unordered_node_set const& other, allocator_type const& a)
: table_(other.table_, a)
{
}
unordered_node_set(unordered_node_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_node_set(unordered_node_set&& other, allocator_type const& al)
: table_(std::move(other.table_), al)
{
}
unordered_node_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_node_set(ilist.begin(), ilist.end(), n, h, pred, a)
{
}
unordered_node_set(
std::initializer_list<value_type> il, allocator_type const& a)
: unordered_node_set(il, size_type(0), hasher(), key_equal(), a)
{
}
unordered_node_set(std::initializer_list<value_type> init, size_type n,
allocator_type const& a)
: unordered_node_set(init, n, hasher(), key_equal(), a)
{
}
unordered_node_set(std::initializer_list<value_type> init, size_type n,
hasher const& h, allocator_type const& a)
: unordered_node_set(init, n, h, key_equal(), a)
{
}
~unordered_node_set() = default;
unordered_node_set& operator=(unordered_node_set const& other)
{
table_ = other.table_;
return *this;
}
unordered_node_set& operator=(unordered_node_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));
}
template <class K>
BOOST_FORCEINLINE typename std::enable_if<
detail::transparent_non_iterable<K, unordered_node_set>::value,
std::pair<iterator, bool> >::type
insert(K&& k)
{
return table_.try_emplace(std::forward<K>(k));
}
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 K>
BOOST_FORCEINLINE typename std::enable_if<
detail::transparent_non_iterable<K, unordered_node_set>::value,
iterator>::type
insert(const_iterator, K&& k)
{
return table_.try_emplace(std::forward<K>(k)).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());
}
insert_return_type insert(node_type&& nh)
{
if (nh.empty()) {
return {end(), false, node_type{}};
}
BOOST_ASSERT(get_allocator() == nh.get_allocator());
auto itp = table_.insert(std::move(nh.element()));
if (itp.second) {
nh.reset();
return {itp.first, true, node_type{}};
} else {
return {itp.first, false, std::move(nh)};
}
}
iterator insert(const_iterator, node_type&& nh)
{
if (nh.empty()) {
return end();
}
BOOST_ASSERT(get_allocator() == nh.get_allocator());
auto itp = table_.insert(std::move(nh.element()));
if (itp.second) {
nh.reset();
return itp.first;
} else {
return itp.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;
}
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_node_set>::value,
size_type>::type
erase(K const& key)
{
return table_.erase(key);
}
void swap(unordered_node_set& rhs) noexcept(
noexcept(std::declval<table_type&>().swap(std::declval<table_type&>())))
{
table_.swap(rhs.table_);
}
node_type extract(const_iterator pos)
{
BOOST_ASSERT(pos != end());
node_type nh;
auto elem = table_.extract(pos);
nh.emplace(std::move(elem), get_allocator());
return nh;
}
node_type extract(key_type const& key)
{
auto pos = find(key);
return pos != end() ? extract(pos) : node_type();
}
template <class K>
typename std::enable_if<
boost::unordered::detail::transparent_non_iterable<K,
unordered_node_set>::value,
node_type>::type
extract(K const& key)
{
auto pos = find(key);
return pos != end() ? extract(pos) : node_type();
}
template <class H2, class P2>
void merge(unordered_node_set<key_type, H2, P2, allocator_type>& source)
{
table_.merge(source.table_);
}
template <class H2, class P2>
void merge(unordered_node_set<key_type, H2, P2, allocator_type>&& source)
{
table_.merge(std::move(source.table_));
}
/// Lookup
///
BOOST_FORCEINLINE size_type count(key_type const& key) const
{
auto pos = table_.find(key);
return pos != table_.end() ? 1 : 0;
}
template <class K>
BOOST_FORCEINLINE 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);
}
BOOST_FORCEINLINE bool contains(key_type const& key) const
{
return this->find(key) != this->end();
}
template <class K>
BOOST_FORCEINLINE 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) {}
size_type max_load() const noexcept { return table_.max_load(); }
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_node_set<Key, Hash, KeyEqual, Allocator> const& lhs,
unordered_node_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_node_set<Key, Hash, KeyEqual, Allocator> const& lhs,
unordered_node_set<Key, Hash, KeyEqual, Allocator> const& rhs)
{
return !(lhs == rhs);
}
template <class Key, class Hash, class KeyEqual, class Allocator>
void swap(unordered_node_set<Key, Hash, KeyEqual, Allocator>& lhs,
unordered_node_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_node_set<Key, Hash, KeyEqual, Allocator>::size_type
erase_if(unordered_node_set<Key, Hash, KeyEqual, Allocator>& set, Pred pred)
{
return erase_if(set.table_, pred);
}
#if defined(BOOST_MSVC)
#pragma warning(pop) /* C4714 */
#endif
#if BOOST_UNORDERED_TEMPLATE_DEDUCTION_GUIDES
template <class InputIterator,
class Hash =
boost::hash<typename std::iterator_traits<InputIterator>::value_type>,
class Pred =
std::equal_to<typename std::iterator_traits<InputIterator>::value_type>,
class Allocator = std::allocator<
typename std::iterator_traits<InputIterator>::value_type>,
class = boost::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
class = boost::enable_if_t<detail::is_hash_v<Hash> >,
class = boost::enable_if_t<detail::is_pred_v<Pred> >,
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
unordered_node_set(InputIterator, InputIterator,
std::size_t = boost::unordered::detail::foa::default_bucket_count,
Hash = Hash(), Pred = Pred(), Allocator = Allocator())
-> unordered_node_set<
typename std::iterator_traits<InputIterator>::value_type, Hash, Pred,
Allocator>;
template <class T, class Hash = boost::hash<T>,
class Pred = std::equal_to<T>, class Allocator = std::allocator<T>,
class = boost::enable_if_t<detail::is_hash_v<Hash> >,
class = boost::enable_if_t<detail::is_pred_v<Pred> >,
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
unordered_node_set(std::initializer_list<T>,
std::size_t = boost::unordered::detail::foa::default_bucket_count,
Hash = Hash(), Pred = Pred(), Allocator = Allocator())
-> unordered_node_set<T, Hash, Pred, Allocator>;
template <class InputIterator, class Allocator,
class = boost::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
unordered_node_set(InputIterator, InputIterator, std::size_t, Allocator)
-> unordered_node_set<
typename std::iterator_traits<InputIterator>::value_type,
boost::hash<typename std::iterator_traits<InputIterator>::value_type>,
std::equal_to<typename std::iterator_traits<InputIterator>::value_type>,
Allocator>;
template <class InputIterator, class Hash, class Allocator,
class = boost::enable_if_t<detail::is_hash_v<Hash> >,
class = boost::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
unordered_node_set(
InputIterator, InputIterator, std::size_t, Hash, Allocator)
-> unordered_node_set<
typename std::iterator_traits<InputIterator>::value_type, Hash,
std::equal_to<typename std::iterator_traits<InputIterator>::value_type>,
Allocator>;
template <class T, class Allocator,
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
unordered_node_set(std::initializer_list<T>, std::size_t, Allocator)
-> unordered_node_set<T, boost::hash<T>, std::equal_to<T>, Allocator>;
template <class T, class Hash, class Allocator,
class = boost::enable_if_t<detail::is_hash_v<Hash> >,
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
unordered_node_set(std::initializer_list<T>, std::size_t, Hash, Allocator)
-> unordered_node_set<T, Hash, std::equal_to<T>, Allocator>;
template <class InputIterator, class Allocator,
class = boost::enable_if_t<detail::is_input_iterator_v<InputIterator> >,
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
unordered_node_set(InputIterator, InputIterator, Allocator)
-> unordered_node_set<
typename std::iterator_traits<InputIterator>::value_type,
boost::hash<typename std::iterator_traits<InputIterator>::value_type>,
std::equal_to<typename std::iterator_traits<InputIterator>::value_type>,
Allocator>;
template <class T, class Allocator,
class = boost::enable_if_t<detail::is_allocator_v<Allocator> > >
unordered_node_set(std::initializer_list<T>, Allocator)
-> unordered_node_set<T, boost::hash<T>, std::equal_to<T>, Allocator>;
#endif
} // namespace unordered
} // namespace boost
#endif
@@ -0,0 +1,49 @@
// Copyright (C) 2023 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_NODE_SET_FWD_HPP_INCLUDED
#define BOOST_UNORDERED_NODE_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_node_set;
template <class Key, class Hash, class KeyEqual, class Allocator>
bool operator==(
unordered_node_set<Key, Hash, KeyEqual, Allocator> const& lhs,
unordered_node_set<Key, Hash, KeyEqual, Allocator> const& rhs);
template <class Key, class Hash, class KeyEqual, class Allocator>
bool operator!=(
unordered_node_set<Key, Hash, KeyEqual, Allocator> const& lhs,
unordered_node_set<Key, Hash, KeyEqual, Allocator> const& rhs);
template <class Key, class Hash, class KeyEqual, class Allocator>
void swap(unordered_node_set<Key, Hash, KeyEqual, Allocator>& lhs,
unordered_node_set<Key, Hash, KeyEqual, Allocator>& rhs)
noexcept(noexcept(lhs.swap(rhs)));
} // namespace unordered
using boost::unordered::unordered_node_set;
using boost::unordered::swap;
using boost::unordered::operator==;
using boost::unordered::operator!=;
} // namespace boost
#endif
@@ -15,6 +15,7 @@
#pragma once
#endif
#include <boost/unordered/detail/requires_cxx11.hpp>
#include <boost/core/explicit_operator_bool.hpp>
#include <boost/functional/hash.hpp>
#include <boost/move/move.hpp>
+6 -1
View File
@@ -1,6 +1,6 @@
# Copyright 2006-2008 Daniel James.
# Copyright 2022 Christian Mazakas
# Copyright 2022-2023 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)
@@ -26,6 +26,7 @@ project
<toolset>gcc-4.4:<cxxflags>-Wno-strict-aliasing
<toolset>gcc-4.4:<cxxflags>-fno-deduce-init-list
<toolset>clang-14:<cxxflags>-Wunused-template
<toolset>gcc:<warnings-as-errors>on
<toolset>clang:<warnings-as-errors>on
@@ -94,6 +95,7 @@ run exception/erase_exception_tests.cpp ;
run exception/rehash_exception_tests.cpp ;
run exception/swap_exception_tests.cpp : : : <define>BOOST_UNORDERED_SWAP_METHOD=2 ;
run exception/merge_exception_tests.cpp ;
run exception/less_tests.cpp ;
run unordered/narrow_cast_tests.cpp ;
run quick.cpp ;
@@ -140,6 +142,9 @@ build_foa erase_if ;
build_foa scary_tests ;
build_foa init_type_insert_tests ;
build_foa max_load_tests ;
build_foa extract_tests ;
build_foa node_handle_tests ;
build_foa uses_allocator ;
run unordered/hash_is_avalanching_test.cpp ;
+18 -2
View File
@@ -25,8 +25,24 @@ typedef boost::unordered_flat_set<
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)
typedef boost::unordered_node_set<test::exception::object,
test::exception::hash, test::exception::equal_to,
test::exception::allocator<test::exception::object> >
test_node_set;
typedef boost::unordered_node_map<test::exception::object,
test::exception::object, test::exception::hash, test::exception::equal_to,
test::exception::allocator2<test::exception::object> >
test_node_map;
typedef boost::unordered_node_set<
std::pair<test::exception::object, test::exception::object>,
test::exception::hash, test::exception::equal_to,
test::exception::allocator<test::exception::object> >
test_pair_node_set;
#define CONTAINER_SEQ (test_set)(test_map)(test_node_set)(test_node_map)
#define CONTAINER_PAIR_SEQ (test_pair_set)(test_map)(test_pair_node_set)(test_node_map)
#else
typedef boost::unordered_set<test::exception::object, test::exception::hash,
test::exception::equal_to,
+25 -7
View File
@@ -1,6 +1,6 @@
// Copyright 2006-2009 Daniel James.
// Copyright 2022 Christian Mazakas.
// Copyright 2022-2023 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"
@@ -229,10 +229,12 @@ using test::generate_collisions;
#ifdef BOOST_UNORDERED_FOA_TESTS
test_set* test_set_;
test_map* test_map_;
test_node_set* test_node_set_;
test_node_map* test_node_map_;
// clang-format off
UNORDERED_TEST(insert_exception_test,
((test_set_)(test_map_))
((test_set_)(test_map_)(test_node_set_)(test_node_map_))
((insert_lvalue)(insert_lvalue_begin)(insert_lvalue_end)
(insert_lvalue_pos)(insert_single_item_range)
(emplace_lvalue)(emplace_lvalue_begin)(emplace_lvalue_end)
@@ -242,7 +244,7 @@ UNORDERED_TEST(insert_exception_test,
)
UNORDERED_TEST(insert_rehash_exception_test,
((test_set_)(test_map_))
((test_set_)(test_map_)(test_node_set_)(test_node_map_))
((insert_lvalue)(insert_lvalue_begin)(insert_lvalue_end)
(insert_lvalue_pos)(insert_single_item_range)
(emplace_lvalue)(emplace_lvalue_begin)(emplace_lvalue_end)
@@ -314,15 +316,16 @@ struct pair_emplace2_type : inserter_base
#ifdef BOOST_UNORDERED_FOA_TESTS
test_pair_set* test_pair_set_;
test_pair_node_set* test_pair_node_set_;
// clang-format off
UNORDERED_TEST(insert_exception_test,
((test_pair_set_)(test_map_))
((test_pair_set_)(test_map_)(test_pair_node_set_)(test_node_map_))
((pair_emplace)(pair_emplace2))
((default_generator)(limited_range)(generate_collisions))
)
UNORDERED_TEST(insert_rehash_exception_test,
((test_pair_set_)(test_map_))
((test_pair_set_)(test_map_)(test_pair_node_set_)(test_node_map_))
((pair_emplace)(pair_emplace2))
((default_generator)(limited_range)(generate_collisions))
)
@@ -399,6 +402,20 @@ struct map_insert_or_assign_type : map_inserter_base
}
} map_insert_or_assign;
#ifdef BOOST_UNORDERED_FOA_TESTS
// clang-format off
UNORDERED_TEST(insert_exception_test,
((test_map_)(test_node_map_))
((try_emplace)(try_emplace2)(map_insert_operator)(map_insert_or_assign))
((default_generator)(limited_range)(generate_collisions))
)
UNORDERED_TEST(insert_rehash_exception_test,
((test_map_)(test_node_map_))
((try_emplace)(try_emplace2)(map_insert_operator)(map_insert_or_assign))
((default_generator)(limited_range)(generate_collisions))
)
// clang-format on
#else
// clang-format off
UNORDERED_TEST(insert_exception_test,
((test_map_))
@@ -411,6 +428,7 @@ UNORDERED_TEST(insert_rehash_exception_test,
((default_generator)(limited_range)(generate_collisions))
)
// clang-format on
#endif
// Range insert tests
@@ -459,12 +477,12 @@ 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_))
((test_set_)(test_map_)(test_node_set_)(test_node_map_))
((default_generator)(limited_range)(generate_collisions))
)
UNORDERED_TEST(insert_range_rehash_exception_test,
((test_set_)(test_map_))
((test_set_)(test_map_)(test_node_set_)(test_node_map_))
((default_generator)(limited_range)(generate_collisions))
)
// clang-format on
+50
View File
@@ -0,0 +1,50 @@
// Copyright 2023 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"
#include "../helpers/helpers.hpp"
#include "../helpers/invariants.hpp"
#include "../helpers/random_values.hpp"
#include "../helpers/strong.hpp"
#include "../helpers/tracker.hpp"
#include <vector>
UNORDERED_AUTO_TEST (less_osx_regression) {
DISABLE_EXCEPTIONS;
typedef test_pair_set::value_type value_type;
typedef test::exception::object object;
std::vector<value_type> v;
v.push_back(value_type(object(12, 98), object(88, 13)));
v.push_back(value_type(object(24, 71), object(62, 84)));
v.push_back(value_type(object(30, 0), object(5, 73)));
v.push_back(value_type(object(34, 64), object(79, 58)));
v.push_back(value_type(object(36, 95), object(64, 23)));
v.push_back(value_type(object(42, 89), object(68, 44)));
v.push_back(value_type(object(42, 26), object(93, 64)));
v.push_back(value_type(object(86, 86), object(16, 62)));
v.push_back(value_type(object(86, 86), object(75, 23)));
v.push_back(value_type(object(92, 37), object(41, 90)));
BOOST_TEST_EQ(v.size(), 10u);
std::set<value_type, test::exception::less> s;
s.insert(v.begin(), v.end());
BOOST_TEST_EQ(s.size(), v.size());
test::ordered<test_pair_set> tracker;
test_pair_set x;
for (std::vector<value_type>::iterator it = v.begin(); it != v.end();
++it) {
x.insert(*it);
}
tracker.insert(v.begin(), v.end());
tracker.compare(x);
}
RUN_TESTS()
+41 -1
View File
@@ -1,6 +1,6 @@
// Copyright 2017-2018 Daniel James.
// Copyright 2022 Christian Mazakas.
// Copyright 2022-2023 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)
@@ -64,6 +64,12 @@ boost::unordered_flat_set<test::exception::object, test::exception::hash,
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_;
boost::unordered_node_set<test::exception::object, test::exception::hash,
test::exception::equal_to,
test::exception::allocator<test::exception::object> >* test_node_set_;
boost::unordered_node_map<test::exception::object, test::exception::object,
test::exception::hash, test::exception::equal_to,
test::exception::allocator2<test::exception::object> >* test_node_map_;
// clang-format off
UNORDERED_MULTI_TEST(set_merge, merge_exception_test,
@@ -99,6 +105,40 @@ UNORDERED_MULTI_TEST(map_merge_collisions, merge_exception_test,
((generate_collisions))
((generate_collisions))
)
UNORDERED_MULTI_TEST(node_set_merge, merge_exception_test,
((test_node_set_))
((test_node_set_))
(/* (0x0000)(0x6400) */(0x0064)/* (0x0a64)(0x3232) */)
((0x0000)(0x0001)(0x0102))
((default_generator)(limited_range))
((default_generator)(limited_range))
)
UNORDERED_MULTI_TEST(node_map_merge, merge_exception_test,
((test_node_map_))
((test_node_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(node_set_merge_collisions, merge_exception_test,
((test_node_set_))
((test_node_set_))
((0x0a0a))
((0x0202)(0x0100)(0x0201))
((generate_collisions))
((generate_collisions))
)
UNORDERED_MULTI_TEST(node_map_merge_collisions, merge_exception_test,
((test_node_map_))
((test_node_map_))
((0x0a0a))
((0x0000)(0x0002)(0x0102))
((generate_collisions))
((generate_collisions))
)
// clang-format on
#else
boost::unordered_set<test::exception::object, test::exception::hash,
test::exception::equal_to,
+7 -1
View File
@@ -247,8 +247,14 @@ using unordered_flat_set = boost::unordered_flat_set<int, boost::hash<int>,
std::equal_to<int>, test::allocator1<int> >;
using unordered_flat_map = boost::unordered_flat_map<int, int, boost::hash<int>,
std::equal_to<int>, test::allocator1<std::pair<int const, int> > >;
using unordered_node_set = boost::unordered_node_set<int, boost::hash<int>,
std::equal_to<int>, test::allocator1<int> >;
using unordered_node_map = boost::unordered_node_map<int, int, boost::hash<int>,
std::equal_to<int>, test::allocator1<std::pair<int const, int> > >;
#define SWAP_CONTAINER_SEQ (unordered_flat_set)(unordered_flat_map)
#define SWAP_CONTAINER_SEQ \
(unordered_flat_set)(unordered_flat_map) \
(unordered_node_set)(unordered_node_map)
#else
+2 -3
View File
@@ -42,9 +42,8 @@ namespace test {
value_list values2(x2.begin(), x2.end());
values1.sort();
values2.sort();
BOOST_TEST(values1.size() == values2.size() &&
test::equal(values1.begin(), values1.end(), values2.begin(),
test::equivalent));
BOOST_TEST_ALL_WITH(values1.begin(), values1.end(), values2.begin(),
values2.end(), test::equivalent);
}
template <class X1, class X2, class T>
+2
View File
@@ -11,6 +11,8 @@
#ifdef BOOST_UNORDERED_FOA_TESTS
#include <boost/unordered/unordered_flat_set.hpp>
#include <boost/unordered/unordered_flat_map.hpp>
#include <boost/unordered/unordered_node_map.hpp>
#include <boost/unordered/unordered_node_set.hpp>
#include <boost/unordered/detail/implementation.hpp>
#else
#include <boost/unordered_set.hpp>
+1 -1
View File
@@ -262,7 +262,7 @@ namespace test {
if (less_impl(x1.first, x2.first)) {
return true;
}
if (!less_impl(x1.first, x2.first)) {
if (less_impl(x2.first, x1.first)) {
return false;
}
return less_impl(x1.second, x2.second);
+50 -3
View File
@@ -1,6 +1,6 @@
// Copyright 2006-2009 Daniel James.
// Copyright 2022 Christian Mazakas.
// Copyright 2022-2023 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)
@@ -209,40 +209,75 @@ namespace assign_tests {
#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_node_map<test::object, test::object, test::hash,
test::equal_to, std::allocator<test::object> >* test_node_map_std_alloc;
boost::unordered_flat_set<test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_set;
boost::unordered_node_set<test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_node_set;
boost::unordered_flat_map<test::object, test::object, test::hash,
test::equal_to, test::allocator2<test::object> >* test_map;
boost::unordered_node_map<test::object, test::object, test::hash,
test::equal_to, test::allocator2<test::object> >* test_node_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_node_set<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::propagate_assign> >*
test_node_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_node_map<test::object, test::object, test::hash,
test::equal_to,
test::cxx11_allocator<test::object, test::propagate_assign> >*
test_node_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_node_set<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_assign> >*
test_node_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;
boost::unordered_node_map<test::object, test::object, test::hash,
test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_assign> >*
test_node_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));
BOOST_TEST(!is_propagate(test_node_set));
BOOST_TEST(is_propagate(test_node_set_prop_assign));
BOOST_TEST(!is_propagate(test_node_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))(
((test_map_std_alloc)(test_node_map_std_alloc)
(test_set)(test_node_set)
(test_map)(test_node_map)
(test_set_prop_assign)(test_node_set_prop_assign)
(test_map_prop_assign)(test_node_map_prop_assign)
(test_set_no_prop_assign)(test_node_set_no_prop_assign)
(test_map_no_prop_assign)(test_node_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))(
((test_set)(test_node_set)
(test_map)(test_node_map)
(test_set_prop_assign)(test_node_set_prop_assign)
(test_map_prop_assign)(test_node_map_prop_assign)
(test_set_no_prop_assign)(test_node_set_no_prop_assign)
(test_map_no_prop_assign)(test_node_map_no_prop_assign))(
(default_generator)(generate_collisions)(limited_range)))
#else
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
@@ -315,6 +350,12 @@ namespace assign_tests {
std::initializer_list<std::pair<int const, int> > init;
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_map<int, int> x1;
boost::unordered_node_map<int, int> x2;
x2[25] = 3;
x2[16] = 10;
BOOST_TEST(!x2.empty());
x2 = init;
BOOST_TEST(x2.empty());
#else
boost::unordered_map<int, int> x1;
#endif
@@ -333,6 +374,12 @@ namespace assign_tests {
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_set<int> x;
boost::unordered_node_set<int> y;
y.insert(10);
y.insert(20);
y = {1, 2, -10};
BOOST_TEST(y.find(10) == y.end());
BOOST_TEST(y.find(-10) != y.end());
#else
boost::unordered_set<int> x;
#endif
+21 -10
View File
@@ -1,6 +1,6 @@
// Copyright 2007-2009 Daniel James.
// Copyright 2022 Christian Mazakas.
// Copyright 2022-2023 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)
@@ -11,16 +11,12 @@
namespace at_tests {
UNORDERED_AUTO_TEST (at_tests) {
template <class X> static void at_tests(X*)
{
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
X x;
X const& x_const(x);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Check empty container" << std::endl;
@@ -64,6 +60,21 @@ namespace at_tests {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Finished" << std::endl;
}
}
#ifdef BOOST_UNORDERED_FOA_TESTS
static boost::unordered_flat_map<std::string, int>* test_map;
static boost::unordered_node_map<std::string, int>* test_node_map;
// clang-format off
UNORDERED_TEST(at_tests, ((test_map)(test_node_map)))
// clang-format on
#else
static boost::unordered_map<std::string, int>* test_map;
// clang-format off
UNORDERED_TEST(at_tests, ((test_map)))
// clang-format on
#endif
} // namespace at_tests
RUN_TESTS()
+144 -136
View File
@@ -1,6 +1,6 @@
// Copyright 2006-2009 Daniel James.
// Copyright 2022 Christian Mazakas.
// Copyright 2022-2023 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)
@@ -35,6 +35,22 @@ template class instantiate_flat_map<test::minimal::assignable const,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<int> >;
template <typename K, typename T, typename H, typename P, typename A>
class instantiate_node_map
{
typedef boost::unordered_node_map<K, T, H, P, A> container;
container x;
};
template class instantiate_node_map<int, int, boost::hash<int>,
std::equal_to<int>, test::minimal::allocator<int> >;
template class instantiate_node_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
@@ -55,149 +71,101 @@ INSTANTIATE(multimap)<test::minimal::assignable, test::minimal::assignable,
test::minimal::allocator<int> >;
#endif
UNORDERED_AUTO_TEST (test0) {
template <template <class Key, class T, class H = boost::hash<Key>,
class P = std::equal_to<Key>,
class Allocator = std::allocator<std::pair<Key const, T> > >
class Map>
static void test0_impl()
{
test::minimal::constructor_param x;
typedef std::pair<test::minimal::assignable const, test::minimal::assignable>
value_type;
value_type value(x, x);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_map.\n";
Map<int, int> int_map;
#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>,
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>,
test::minimal::cxx11_allocator<std::pair<int const, int> > >
int_map2;
boost::unordered_map<test::minimal::assignable, test::minimal::assignable,
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;
#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;
boost::unordered_multimap<int, int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<std::pair<int const, int> > >
int_multimap2;
boost::unordered_multimap<test::minimal::assignable,
test::minimal::assignable, test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<value_type> >
multimap;
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);
UNORDERED_AUTO_TEST (test0) {
#ifdef BOOST_UNORDERED_FOA_TESTS
test0_impl<boost::unordered_flat_map>();
test0_impl<boost::unordered_node_map>();
#else
test0_impl<boost::unordered_map>();
test0_impl<boost::unordered_multimap>();
#endif
}
UNORDERED_AUTO_TEST (equality_tests) {
template <template <class Key, class T, class H = boost::hash<Key>,
class P = std::equal_to<Key>,
class Allocator = std::allocator<std::pair<Key const, T> > >
class Map>
static void equality_tests_impl()
{
typedef std::pair<test::minimal::copy_constructible_equality_comparable const,
test::minimal::copy_constructible_equality_comparable>
value_type;
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_map<int, int> int_map;
Map<int, int> int_map;
boost::unordered_flat_map<int, int, boost::hash<int>, std::equal_to<int>,
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,
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>,
test::minimal::cxx11_allocator<std::pair<int const, int> > >
int_map2;
boost::unordered_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;
#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>,
test::minimal::cxx11_allocator<std::pair<int const, int> > >
int_multimap2;
boost::unordered_multimap<
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> >
multimap;
equality_test(int_multimap);
equality_test(int_multimap2);
equality_test(multimap);
UNORDERED_AUTO_TEST (equality_tests) {
#ifdef BOOST_UNORDERED_FOA_TESTS
equality_tests_impl<boost::unordered_flat_map>();
equality_tests_impl<boost::unordered_node_map>();
#else
equality_tests_impl<boost::unordered_map>();
equality_tests_impl<boost::unordered_multimap>();
#endif
}
UNORDERED_AUTO_TEST (test1) {
template <template <class Key, class T, class H = boost::hash<Key>,
class P = std::equal_to<Key>,
class Allocator = std::allocator<std::pair<Key const, T> > >
class Map>
static void test1_unique_impl()
{
boost::hash<int> hash;
std::equal_to<int> equal_to;
int value = 0;
std::pair<int const, int> map_value(0, 0);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_map.\n";
Map<int, int> map;
#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>,
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);
@@ -208,27 +176,53 @@ UNORDERED_AUTO_TEST (test1) {
unordered_map_test(map2, value, value);
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";
template <template <class Key, class T, class H = boost::hash<Key>,
class P = std::equal_to<Key>,
class Allocator = std::allocator<std::pair<Key const, T> > >
class Map>
static void test1_equivalent_impl()
{
boost::unordered_multimap<int, int> multimap;
boost::hash<int> hash;
std::equal_to<int> equal_to;
int value = 0;
std::pair<int const, int> map_value(0, 0);
boost::unordered_multimap<int, int, boost::hash<int>, std::equal_to<int>,
Map<int, int> map;
Map<int, int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<std::pair<int const, int> > >
multimap2;
map2;
unordered_equivalent_test(multimap, map_value);
unordered_map_test(multimap, value, value);
unordered_copyable_test(multimap, value, map_value, hash, equal_to);
unordered_equivalent_test(map, map_value);
unordered_map_test(map, value, value);
unordered_copyable_test(map, value, map_value, hash, equal_to);
unordered_equivalent_test(multimap2, map_value);
unordered_map_test(multimap2, value, value);
unordered_copyable_test(multimap2, value, map_value, hash, equal_to);
unordered_equivalent_test(map2, map_value);
unordered_map_test(map2, value, value);
unordered_copyable_test(map2, value, map_value, hash, equal_to);
}
#endif
UNORDERED_AUTO_TEST (test1) {
#ifdef BOOST_UNORDERED_FOA_TESTS
test1_unique_impl<boost::unordered_flat_map>();
test1_unique_impl<boost::unordered_node_map>();
#else
test1_unique_impl<boost::unordered_map>();
test1_equivalent_impl<boost::unordered_multimap>();
#endif
}
UNORDERED_AUTO_TEST (test2) {
template <template <class Key, class T, class H = boost::hash<Key>,
class P = std::equal_to<Key>,
class Allocator = std::allocator<std::pair<Key const, T> > >
class Map>
static void test2_unique_impl()
{
test::minimal::constructor_param x;
test::minimal::assignable assignable(x);
@@ -240,60 +234,66 @@ UNORDERED_AUTO_TEST (test2) {
map_value_type;
map_value_type map_value(assignable, assignable);
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,
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,
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";
template <template <class Key, class T, class H = boost::hash<Key>,
class P = std::equal_to<Key>,
class Allocator = std::allocator<std::pair<Key const, T> > >
class Map>
static void test2_equivalent_impl()
{
test::minimal::constructor_param x;
boost::unordered_multimap<test::minimal::assignable,
test::minimal::assignable, test::minimal::hash<test::minimal::assignable>,
test::minimal::assignable assignable(x);
test::minimal::copy_constructible copy_constructible(x);
test::minimal::hash<test::minimal::assignable> hash(x);
test::minimal::equal_to<test::minimal::assignable> equal_to(x);
typedef std::pair<test::minimal::assignable const, test::minimal::assignable>
map_value_type;
map_value_type map_value(assignable, assignable);
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> >
multimap;
map;
unordered_equivalent_test(multimap, map_value);
unordered_map_test(multimap, assignable, assignable);
unordered_copyable_test(multimap, assignable, map_value, hash, equal_to);
unordered_map_member_test(multimap, map_value);
unordered_equivalent_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);
}
#endif
UNORDERED_AUTO_TEST (test2) {
#ifdef BOOST_UNORDERED_FOA_TESTS
test2_unique_impl<boost::unordered_flat_map>();
test2_unique_impl<boost::unordered_node_map>();
#else
test2_unique_impl<boost::unordered_map>();
test2_equivalent_impl<boost::unordered_multimap>();
#endif
}
@@ -316,9 +316,17 @@ 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());
{
boost::unordered_flat_map<lwg2059_key, int> x;
x.emplace(lwg2059_key(10), 5);
x.erase(x.begin());
}
{
boost::unordered_node_map<lwg2059_key, int> x;
x.emplace(lwg2059_key(10), 5);
x.erase(x.begin());
}
#else
{
boost::unordered_map<lwg2059_key, int> x;
+187 -200
View File
@@ -1,6 +1,6 @@
// Copyright 2006-2009 Daniel James.
// Copyright 2022 Christian Mazakas.
// Copyright 2022-2023 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)
@@ -35,6 +35,21 @@ template class instantiate_flat_set<test::minimal::assignable const,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<int> >;
template <typename T, typename H, typename P, typename A>
class instantiate_node_set
{
typedef boost::unordered_node_set<T, H, P, A> container;
container x;
};
template class instantiate_node_set<int, boost::hash<int>, std::equal_to<int>,
test::minimal::allocator<int> >;
template class instantiate_node_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) \
@@ -56,153 +71,106 @@ INSTANTIATE(multiset)<test::minimal::assignable,
#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;
template <class X> static void type_traits_impl()
{
BOOST_STATIC_ASSERT(boost::is_same<int const&,
std::iterator_traits<iterator>::reference>::value);
typename std::iterator_traits<typename X::iterator>::reference>::value);
}
UNORDERED_AUTO_TEST (test0) {
UNORDERED_AUTO_TEST (type_traits) {
#ifdef BOOST_UNORDERED_FOA_TESTS
type_traits_impl<boost::unordered_flat_set<int> >();
type_traits_impl<boost::unordered_node_set<int> >();
#else
type_traits_impl<boost::unordered_set<int> >();
type_traits_impl<boost::unordered_multiset<int> >();
#endif
}
template <template <class T, class H = boost::hash<T>,
class P = std::equal_to<T>, class A = std::allocator<T> >
class Set>
static void test0_impl()
{
test::minimal::constructor_param x;
test::minimal::assignable assignable(x);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_set.\n";
Set<int> int_set;
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_set<int> int_set;
boost::unordered_flat_set<int, boost::hash<int>, std::equal_to<int>,
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>,
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>,
test::minimal::cxx11_allocator<int> >
int_set2;
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
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;
boost::unordered_multiset<int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<int> >
int_multiset2;
boost::unordered_multiset<test::minimal::assignable,
test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<test::minimal::assignable> >
multiset;
container_test(int_multiset, 0);
container_test(int_multiset2, 0);
container_test(multiset, assignable);
UNORDERED_AUTO_TEST (test0) {
#ifdef BOOST_UNORDERED_FOA_TESTS
test0_impl<boost::unordered_flat_set>();
test0_impl<boost::unordered_node_set>();
#else
test0_impl<boost::unordered_set>();
test0_impl<boost::unordered_multiset>();
#endif
}
UNORDERED_AUTO_TEST (equality_tests) {
template <template <class T, class H = boost::hash<T>,
class P = std::equal_to<T>, class A = std::allocator<T> >
class Set>
static void equality_tests_impl()
{
typedef test::minimal::copy_constructible_equality_comparable value_type;
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_set<int> int_set;
Set<int> int_set;
boost::unordered_flat_set<int, boost::hash<int>, std::equal_to<int>,
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,
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>,
test::minimal::cxx11_allocator<int> >
int_set2;
boost::unordered_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;
#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>,
test::minimal::cxx11_allocator<int> >
int_multiset2;
boost::unordered_multiset<
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> >
multiset;
equality_test(int_multiset);
equality_test(int_multiset2);
equality_test(multiset);
UNORDERED_AUTO_TEST (equality_tests) {
#ifdef BOOST_UNORDERED_FOA_TESTS
equality_tests_impl<boost::unordered_flat_set>();
equality_tests_impl<boost::unordered_node_set>();
#else
equality_tests_impl<boost::unordered_set>();
equality_tests_impl<boost::unordered_multiset>();
#endif
}
UNORDERED_AUTO_TEST (test1) {
template <template <class T, class H = boost::hash<T>,
class P = std::equal_to<T>, class A = std::allocator<T> >
class Set>
static void test1_unique_impl()
{
boost::hash<int> hash;
std::equal_to<int> equal_to;
int value = 0;
Set<int> set;
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>,
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);
@@ -211,27 +179,49 @@ UNORDERED_AUTO_TEST (test1) {
unordered_unique_test(set2, value);
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;
template <template <class T, class H = boost::hash<T>,
class P = std::equal_to<T>, class A = std::allocator<T> >
class Set>
static void test1_equivalent_impl()
{
boost::unordered_multiset<int> multiset;
boost::hash<int> hash;
std::equal_to<int> equal_to;
int value = 0;
Set<int> set;
boost::unordered_multiset<int, boost::hash<int>, std::equal_to<int>,
Set<int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<int> >
multiset2;
set2;
unordered_equivalent_test(multiset, value);
unordered_set_test(multiset, value);
unordered_copyable_test(multiset, value, value, hash, equal_to);
unordered_equivalent_test(set, value);
unordered_set_test(set, value);
unordered_copyable_test(set, value, value, hash, equal_to);
unordered_equivalent_test(multiset2, value);
unordered_set_test(multiset2, value);
unordered_copyable_test(multiset2, value, value, hash, equal_to);
unordered_equivalent_test(set2, value);
unordered_set_test(set2, value);
unordered_copyable_test(set2, value, value, hash, equal_to);
}
#endif
UNORDERED_AUTO_TEST (test1) {
#ifdef BOOST_UNORDERED_FOA_TESTS
test1_unique_impl<boost::unordered_flat_set>();
test1_unique_impl<boost::unordered_node_set>();
#else
test1_unique_impl<boost::unordered_set>();
test1_equivalent_impl<boost::unordered_multiset>();
#endif
}
UNORDERED_AUTO_TEST (test2) {
template <template <class T, class H = boost::hash<T>,
class P = std::equal_to<T>, class A = std::allocator<T> >
class Set>
static void test2_unique_impl()
{
test::minimal::constructor_param x;
test::minimal::assignable assignable(x);
@@ -239,155 +229,144 @@ UNORDERED_AUTO_TEST (test2) {
test::minimal::hash<test::minimal::assignable> hash(x);
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>,
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";
template <template <class T, class H = boost::hash<T>,
class P = std::equal_to<T>, class A = std::allocator<T> >
class Set>
static void test2_equivalent_impl()
{
test::minimal::constructor_param x;
boost::unordered_multiset<test::minimal::assignable,
test::minimal::hash<test::minimal::assignable>,
test::minimal::assignable assignable(x);
test::minimal::copy_constructible copy_constructible(x);
test::minimal::hash<test::minimal::assignable> hash(x);
test::minimal::equal_to<test::minimal::assignable> equal_to(x);
Set<test::minimal::assignable, test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<test::minimal::assignable> >
multiset;
set;
unordered_equivalent_test(multiset, assignable);
unordered_set_test(multiset, assignable);
unordered_copyable_test(multiset, assignable, assignable, hash, equal_to);
unordered_set_member_test(multiset, assignable);
unordered_equivalent_test(set, assignable);
unordered_set_test(set, assignable);
unordered_copyable_test(set, assignable, assignable, hash, equal_to);
unordered_set_member_test(set, assignable);
}
#endif
UNORDERED_AUTO_TEST (test2) {
#ifdef BOOST_UNORDERED_FOA_TESTS
test2_unique_impl<boost::unordered_flat_set>();
test2_unique_impl<boost::unordered_node_set>();
#else
test2_unique_impl<boost::unordered_set>();
test2_equivalent_impl<boost::unordered_multiset>();
#endif
}
UNORDERED_AUTO_TEST (movable1_tests) {
template <template <class T, class H = boost::hash<T>,
class P = std::equal_to<T>, class A = std::allocator<T> >
class Set>
static void movable1_tests_impl()
{
test::minimal::constructor_param x;
test::minimal::movable1 movable1(x);
test::minimal::hash<test::minimal::movable1> hash(x);
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>,
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
// TODO: find out why Daniel had this commented out and if we need it and the
// corresponding equivalent impl
//
// 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,
test::minimal::hash<test::minimal::movable1>,
test::minimal::equal_to<test::minimal::movable1>,
test::minimal::allocator<test::minimal::movable1> >
multiset;
// unordered_equivalent_test(multiset, movable1);
unordered_set_test(multiset, movable1);
unordered_movable_test(multiset, movable1, movable1, hash, equal_to);
UNORDERED_AUTO_TEST (movable1_tests) {
#ifdef BOOST_UNORDERED_FOA_TESTS
movable1_tests_impl<boost::unordered_flat_set>();
movable1_tests_impl<boost::unordered_node_set>();
#else
movable1_tests_impl<boost::unordered_set>();
movable1_tests_impl<boost::unordered_multiset>();
#endif
}
UNORDERED_AUTO_TEST (movable2_tests) {
template <template <class T, class H = boost::hash<T>,
class P = std::equal_to<T>, class A = std::allocator<T> >
class Set>
static void movable2_tests_impl()
{
test::minimal::constructor_param x;
test::minimal::movable2 movable2(x);
test::minimal::hash<test::minimal::movable2> hash(x);
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>,
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";
UNORDERED_AUTO_TEST (movable2_tests) {
boost::unordered_multiset<test::minimal::movable2,
test::minimal::hash<test::minimal::movable2>,
test::minimal::equal_to<test::minimal::movable2>,
test::minimal::allocator<test::minimal::movable2> >
multiset;
// unordered_equivalent_test(multiset, movable2);
unordered_set_test(multiset, movable2);
unordered_movable_test(multiset, movable2, movable2, hash, equal_to);
#ifdef BOOST_UNORDERED_FOA_TESTS
movable2_tests_impl<boost::unordered_flat_set>();
movable2_tests_impl<boost::unordered_node_set>();
#else
movable2_tests_impl<boost::unordered_set>();
movable2_tests_impl<boost::unordered_multiset>();
#endif
}
UNORDERED_AUTO_TEST (destructible_tests) {
template <template <class T, class H = boost::hash<T>,
class P = std::equal_to<T>, class A = std::allocator<T> >
class Set>
static void destructible_tests_impl()
{
test::minimal::constructor_param x;
test::minimal::destructible destructible(x);
test::minimal::hash<test::minimal::destructible> hash(x);
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,
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,
test::minimal::hash<test::minimal::destructible>,
test::minimal::equal_to<test::minimal::destructible> >
multiset;
unordered_destructible_test(multiset);
UNORDERED_AUTO_TEST (destructible_tests) {
#ifdef BOOST_UNORDERED_FOA_TESTS
destructible_tests_impl<boost::unordered_flat_set>();
destructible_tests_impl<boost::unordered_node_set>();
#else
destructible_tests_impl<boost::unordered_set>();
destructible_tests_impl<boost::unordered_multiset>();
#endif
}
@@ -410,9 +389,17 @@ 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());
{
boost::unordered_flat_set<lwg2059_key> x;
x.emplace(lwg2059_key(10));
x.erase(x.begin());
}
{
boost::unordered_node_set<lwg2059_key> x;
x.emplace(lwg2059_key(10));
x.erase(x.begin());
}
#else
{
boost::unordered_set<lwg2059_key> x;
+14 -5
View File
@@ -1,6 +1,6 @@
// Copyright 2006-2010 Daniel James.
// Copyright (C) 2022 Christian Mazakas
// Copyright (C) 2022-2023 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)
@@ -655,23 +655,27 @@ namespace constructor_tests {
boost::unordered_flat_set<test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_set;
boost::unordered_node_set<test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_node_set;
boost::unordered_flat_map<test::object, test::object, test::hash,
test::equal_to, test::allocator2<test::object> >* test_map;
boost::unordered_node_map<test::object, test::object, test::hash,
test::equal_to, test::allocator2<test::object> >* test_node_map;
UNORDERED_TEST(constructor_tests1,
((test_map_std_alloc)(test_set)(test_map))(
((test_map_std_alloc)(test_set)(test_node_set)(test_map)(test_node_map))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(constructor_tests2,
((test_set)(test_map))(
((test_set)(test_node_set)(test_map)(test_node_map))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(map_constructor_test,
((test_map_std_alloc)(test_map))(
((test_map_std_alloc)(test_map)(test_node_map))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(no_alloc_default_construct_test,
((test_set)(test_map))(
((test_set)(test_node_set)(test_map)(test_node_map))(
(default_generator)(generate_collisions)(limited_range)))
#else
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
@@ -709,6 +713,8 @@ namespace constructor_tests {
std::initializer_list<int> init;
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_set<int> x1 = init;
boost::unordered_node_set<int> x2 = init;
BOOST_TEST(x2.empty());
#else
boost::unordered_set<int> x1 = init;
#endif
@@ -722,6 +728,9 @@ namespace constructor_tests {
UNORDERED_AUTO_TEST (test_initializer_list) {
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_set<int> x1 = {2, 10, 45, -5};
boost::unordered_node_set<int> x2 = {2, 10, 45, -5};
BOOST_TEST(x2.find(10) != x2.end());
BOOST_TEST(x2.find(46) == x2.end());
#else
boost::unordered_set<int> x1 = {2, 10, 45, -5};
#endif
+35 -1
View File
@@ -1,4 +1,4 @@
// Copyright 2021-2022 Christian Mazakas.
// Copyright 2021-2023 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)
@@ -137,6 +137,24 @@ void test_map()
typedef boost::unordered_flat_map<key, int, hasher, key_equal>
non_transparent_map3;
typedef boost::unordered_node_map<key, int, transparent_hasher,
transparent_key_equal>
transparent_node_map;
typedef boost::unordered_node_map<key, int, transparent_hasher, key_equal>
non_transparent_node_map1;
typedef boost::unordered_node_map<key, int, hasher, transparent_key_equal>
non_transparent_node_map2;
typedef boost::unordered_node_map<key, int, hasher, key_equal>
non_transparent_node_map3;
test_map_transparent_contains<transparent_node_map>();
test_map_non_transparent_contains<non_transparent_node_map1>();
test_map_non_transparent_contains<non_transparent_node_map2>();
test_map_non_transparent_contains<non_transparent_node_map3>();
#else
typedef boost::unordered_map<key, int, transparent_hasher,
transparent_key_equal>
@@ -254,6 +272,22 @@ void test_set()
non_transparent_set2;
typedef boost::unordered_flat_set<key, hasher, key_equal>
non_transparent_set3;
typedef boost::unordered_node_set<key, transparent_hasher,
transparent_key_equal>
transparent_node_set;
typedef boost::unordered_node_set<key, transparent_hasher, key_equal>
non_transparent_node_set1;
typedef boost::unordered_node_set<key, hasher, transparent_key_equal>
non_transparent_node_set2;
typedef boost::unordered_node_set<key, hasher, key_equal>
non_transparent_node_set3;
test_set_transparent_contains<transparent_node_set>();
test_set_non_transparent_contains<non_transparent_node_set1>();
test_set_non_transparent_contains<non_transparent_node_set2>();
test_set_non_transparent_contains<non_transparent_node_set3>();
#else
typedef boost::unordered_set<key, transparent_hasher, transparent_key_equal>
transparent_set;
+73 -12
View File
@@ -1,18 +1,18 @@
// Copyright 2006-2009 Daniel James.
// Copyright (C) 2022 Christian Mazakas
// Copyright (C) 2022-2023 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/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 "../helpers/random_values.hpp"
#include "../helpers/test.hpp"
#include "../helpers/tracker.hpp"
#include "../objects/cxx11_allocator.hpp"
#include "../objects/test.hpp"
test::seed_t initialize_seed(9063);
@@ -482,31 +482,82 @@ namespace copy_tests {
allocator<std::pair<int const, int> > >*
test_map_trivially_copyable_no_construct;
boost::unordered_node_set<test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_node_set;
boost::unordered_node_map<test::object, test::object, test::hash,
test::equal_to, test::allocator1<test::object> >* test_node_map;
boost::unordered_node_set<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::select_copy> >*
test_node_set_select_copy;
boost::unordered_node_map<test::object, test::object, test::hash,
test::equal_to, test::cxx11_allocator<test::object, test::select_copy> >*
test_node_map_select_copy;
boost::unordered_node_set<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_select_copy> >*
test_node_set_no_select_copy;
boost::unordered_node_map<test::object, test::object, test::hash,
test::equal_to, test::cxx11_allocator<test::object, test::no_select_copy> >*
test_node_map_no_select_copy;
boost::unordered_node_set<int, test::hash, test::equal_to,
test::allocator1<int> >* test_node_set_trivially_copyable;
boost::unordered_node_map<int, int, test::hash, test::equal_to,
test::allocator1<std::pair<int const, int> > >*
test_node_map_trivially_copyable;
boost::unordered_node_set<int, test::hash, test::equal_to,
std::allocator<int> >* test_node_set_trivially_copyable_std_allocator;
boost::unordered_node_map<int, int, test::hash, test::equal_to,
std::allocator<std::pair<int const, int> > >*
test_node_map_trivially_copyable_std_allocator;
boost::unordered_node_set<int, test::hash, test::equal_to, allocator<int> >*
test_node_set_trivially_copyable_no_construct;
boost::unordered_node_map<int, int, test::hash, test::equal_to,
allocator<std::pair<int const, int> > >*
test_node_map_trivially_copyable_no_construct;
// clang-format off
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)
(test_set_trivially_copyable)(test_map_trivially_copyable))
(test_set_trivially_copyable)(test_map_trivially_copyable)
(test_node_set)(test_node_map)(test_node_set_select_copy)(test_node_map_select_copy)
(test_node_set_no_select_copy)(test_node_map_no_select_copy)
(test_node_set_trivially_copyable)(test_node_map_trivially_copyable))
((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)
(test_set_trivially_copyable)(test_map_trivially_copyable))
(test_set_trivially_copyable)(test_map_trivially_copyable)
(test_node_set)(test_node_map)(test_node_set_select_copy)(test_node_map_select_copy)
(test_node_set_no_select_copy)(test_node_map_no_select_copy)
(test_node_set_trivially_copyable)(test_node_map_trivially_copyable))
((default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(copy_construct_tests_std_allocator1,
((test_set_trivially_copyable_std_allocator)
(test_map_trivially_copyable_std_allocator)
(test_set_trivially_copyable_no_construct)
(test_map_trivially_copyable_no_construct))
(test_map_trivially_copyable_no_construct)
(test_node_set_trivially_copyable_std_allocator)
(test_node_map_trivially_copyable_std_allocator)
(test_node_set_trivially_copyable_no_construct)
(test_node_map_trivially_copyable_no_construct))
((default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(copy_construct_tests_std_allocator2,
((test_set_trivially_copyable_std_allocator)
(test_map_trivially_copyable_std_allocator)
(test_set_trivially_copyable_no_construct)
(test_map_trivially_copyable_no_construct))
(test_map_trivially_copyable_no_construct)
(test_node_set_trivially_copyable_std_allocator)
(test_node_map_trivially_copyable_std_allocator)
(test_node_set_trivially_copyable_no_construct)
(test_node_map_trivially_copyable_no_construct))
((default_generator)(generate_collisions)(limited_range)))
// clang-format on
#else
@@ -545,13 +596,23 @@ namespace copy_tests {
test::equal_to, test::cxx11_allocator<test::object, test::no_select_copy> >*
test_multimap_no_select_copy;
// clang-format off
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)))
// clang-format on
#endif
} // namespace copy_tests
+74 -44
View File
@@ -179,18 +179,13 @@ namespace emplace_tests {
};
UNORDERED_AUTO_TEST (emplace_set) {
template <class X> static void emplace_set(X*)
{
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 X container;
typedef typename container::iterator iterator;
typedef std::pair<iterator, bool> return_type;
container x(10);
iterator i1;
@@ -225,7 +220,7 @@ namespace emplace_tests {
BOOST_TEST(r1.first == x.find(v2));
BOOST_TEST_EQ(check_.instances(), 4);
#ifdef BOOST_UNORDERED_FOA_TESTS
BOOST_TEST_EQ(check_.constructions(), 6);
BOOST_TEST_EQ(check_.constructions(), 6);
#else
BOOST_TEST_EQ(check_.constructions(), 4);
#endif
@@ -294,6 +289,21 @@ namespace emplace_tests {
BOOST_TEST(x.count(v4) == 1);
}
#ifdef BOOST_UNORDERED_FOA_TESTS
static boost::unordered_flat_set<emplace_value, boost::hash<emplace_value> >*
test_set;
static boost::unordered_node_set<emplace_value, boost::hash<emplace_value> >*
test_node_set;
UNORDERED_TEST(emplace_set, ((test_set)(test_node_set)))
#else
static boost::unordered_set<emplace_value, boost::hash<emplace_value> >*
test_set;
UNORDERED_TEST(emplace_set, ((test_set)))
#endif
#ifndef BOOST_UNORDERED_FOA_TESTS
UNORDERED_AUTO_TEST (emplace_multiset) {
test::check_instances check_;
@@ -374,18 +384,12 @@ namespace emplace_tests {
}
#endif
UNORDERED_AUTO_TEST (emplace_map) {
template <class X> static void emplace_map(X*)
{
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 X container;
typedef typename container::iterator iterator;
typedef std::pair<iterator, bool> return_type;
container x(10);
return_type r1, r2;
@@ -393,7 +397,9 @@ namespace emplace_tests {
#ifdef BOOST_UNORDERED_FOA_TESTS
// 5/8 args + duplicate
emplace_value k1(5, "", 'b', 4, 5);
BOOST_TEST_EQ(check_.constructions(), 1);
emplace_value m1(8, "xxx", 'z', 4, 5, 6, 7, 8);
BOOST_TEST_EQ(check_.constructions(), 2);
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);
@@ -485,18 +491,18 @@ namespace emplace_tests {
BOOST_TEST_EQ(check_.instances(), 8);
BOOST_TEST_EQ(check_.constructions(), 10);
BOOST_TEST(r1.first ==
x.emplace_hint(r1.first, boost::unordered::piecewise_construct,
boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9),
boost::make_tuple(15, "jkjk")));
BOOST_TEST(r1.first ==
x.emplace_hint(r2.first, boost::unordered::piecewise_construct,
boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9),
boost::make_tuple(275, "xxx", 'm', 6)));
BOOST_TEST(r1.first ==
x.emplace_hint(x.end(), boost::unordered::piecewise_construct,
boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9),
boost::make_tuple(-10, "blah blah", '\0')));
BOOST_TEST(r1.first == x.emplace_hint(r1.first,
boost::unordered::piecewise_construct,
boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9),
boost::make_tuple(15, "jkjk")));
BOOST_TEST(r1.first == x.emplace_hint(r2.first,
boost::unordered::piecewise_construct,
boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9),
boost::make_tuple(275, "xxx", 'm', 6)));
BOOST_TEST(
r1.first == x.emplace_hint(x.end(), boost::unordered::piecewise_construct,
boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9),
boost::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);
@@ -504,6 +510,21 @@ namespace emplace_tests {
#endif
}
#ifdef BOOST_UNORDERED_FOA_TESTS
static boost::unordered_flat_map<emplace_value, emplace_value,
boost::hash<emplace_value> >* test_map;
static boost::unordered_node_map<emplace_value, emplace_value,
boost::hash<emplace_value> >* test_node_map;
UNORDERED_TEST(emplace_map, ((test_map)(test_node_map)))
#else
static boost::unordered_map<emplace_value, emplace_value,
boost::hash<emplace_value> >* test_map;
UNORDERED_TEST(emplace_map, ((test_map)))
#endif
#ifndef BOOST_UNORDERED_FOA_TESTS
UNORDERED_AUTO_TEST (emplace_multimap) {
test::check_instances check_;
@@ -571,14 +592,13 @@ namespace emplace_tests {
}
#endif
UNORDERED_AUTO_TEST (try_emplace) {
template <class X> static void try_emplace(X*)
{
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 X container;
typedef typename container::iterator iterator;
typedef std::pair<iterator, bool> return_type;
container x(10);
return_type r1, r2, r3;
@@ -615,12 +635,22 @@ namespace emplace_tests {
BOOST_TEST_EQ(check_.constructions(), 4);
BOOST_TEST(r2.first == x.try_emplace(r2.first, k2, 808709, "what"));
BOOST_TEST(
r2.first ==
x.try_emplace(r2.first, k2, 10, "xxx", 'a', 4, 5, 6, 7, 8, 9, 10));
BOOST_TEST(r2.first == x.try_emplace(r2.first, k2, 10, "xxx", 'a', 4, 5, 6,
7, 8, 9, 10));
BOOST_TEST(r2.first->second == m2);
BOOST_TEST_EQ(x.size(), 2u);
}
#ifdef BOOST_UNORDERED_FOA_TESTS
static boost::unordered_flat_map<int, emplace_value>* test_int_map;
static boost::unordered_node_map<int, emplace_value>* test_int_node_map;
UNORDERED_TEST(try_emplace, ((test_int_map)(test_int_node_map)))
#else
static boost::unordered_map<int, emplace_value>* test_int_map;
UNORDERED_TEST(try_emplace, ((test_int_map)))
#endif
}
RUN_TESTS()
+131 -6
View File
@@ -1,14 +1,18 @@
// Copyright 2008-2009 Daniel James.
// Copyright 2022 Christian Mazakas.
// Copyright 2022-2023 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/unordered.hpp"
#include "../helpers/test.hpp"
#include <boost/preprocessor/seq.hpp>
#include <list>
#include "../helpers/test.hpp"
// TODO: this test needs to be someday cleaned up to not be so heavily
// macro-generated
//
namespace equality_tests {
struct mod_compare
@@ -33,6 +37,12 @@ namespace equality_tests {
using boost_unordered_map =
boost::unordered_flat_map<int, int, mod_compare, mod_compare>;
using boost_unordered_node_set =
boost::unordered_node_set<int, mod_compare, mod_compare>;
using boost_unordered_node_map =
boost::unordered_node_map<int, int, mod_compare, mod_compare>;
#define UNORDERED_EQUALITY_MULTISET_TEST(seq1, op, seq2) \
{ \
}
@@ -64,14 +74,46 @@ namespace equality_tests {
}
#endif
#ifdef BOOST_UNORDERED_FOA_TESTS
#define UNORDERED_EQUALITY_SET_TEST(seq1, op, seq2) \
{ \
boost_unordered_set set1, set2; \
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); \
} \
{ \
boost_unordered_node_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); \
}
#else
#define UNORDERED_EQUALITY_SET_TEST(seq1, op, seq2) \
{ \
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); \
}
#endif
#ifdef BOOST_UNORDERED_FOA_TESTS
#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); \
} \
\
{ \
boost_unordered_node_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); \
}
#else
#define UNORDERED_EQUALITY_MAP_TEST(seq1, op, seq2) \
{ \
boost_unordered_map map1, map2; \
@@ -79,6 +121,7 @@ namespace equality_tests {
BOOST_PP_SEQ_FOR_EACH(UNORDERED_MAP_INSERT, map2, seq2) \
BOOST_TEST(map1 op map2); \
}
#endif
#define UNORDERED_SET_INSERT(r, set, item) set.insert(item);
#define UNORDERED_MAP_INSERT(r, map, item) \
@@ -86,10 +129,51 @@ namespace equality_tests {
UNORDERED_AUTO_TEST (equality_size_tests) {
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_set<int> x1, x2;
{
boost::unordered_flat_set<int> x1, x2;
BOOST_TEST(x1 == x2);
BOOST_TEST(!(x1 != x2));
x1.insert(1);
BOOST_TEST(x1 != x2);
BOOST_TEST(!(x1 == x2));
BOOST_TEST(x2 != x1);
BOOST_TEST(!(x2 == x1));
x2.insert(1);
BOOST_TEST(x1 == x2);
BOOST_TEST(!(x1 != x2));
x2.insert(2);
BOOST_TEST(x1 != x2);
BOOST_TEST(!(x1 == x2));
BOOST_TEST(x2 != x1);
BOOST_TEST(!(x2 == x1));
}
{
boost::unordered_node_set<int> x1, x2;
BOOST_TEST(x1 == x2);
BOOST_TEST(!(x1 != x2));
x1.insert(1);
BOOST_TEST(x1 != x2);
BOOST_TEST(!(x1 == x2));
BOOST_TEST(x2 != x1);
BOOST_TEST(!(x2 == x1));
x2.insert(1);
BOOST_TEST(x1 == x2);
BOOST_TEST(!(x1 != x2));
x2.insert(2);
BOOST_TEST(x1 != x2);
BOOST_TEST(!(x1 == x2));
BOOST_TEST(x2 != x1);
BOOST_TEST(!(x2 == x1));
}
#else
boost::unordered_set<int> x1, x2;
#endif
BOOST_TEST(x1 == x2);
BOOST_TEST(!(x1 != x2));
@@ -108,6 +192,7 @@ namespace equality_tests {
BOOST_TEST(!(x1 == x2));
BOOST_TEST(x2 != x1);
BOOST_TEST(!(x2 == x1));
#endif
}
UNORDERED_AUTO_TEST (equality_key_value_tests) {
@@ -156,6 +241,45 @@ namespace equality_tests {
// different hash functions but the same equality predicate.
UNORDERED_AUTO_TEST (equality_different_hash_test) {
#ifdef BOOST_UNORDERED_FOA_TESTS
{
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);
set1.insert(1);
set2.insert(2);
BOOST_TEST(set1 != set2);
set1.insert(2);
set2.insert(1);
BOOST_TEST(set1 == set2);
set1.insert(10);
set2.insert(20);
BOOST_TEST(set1 != set2);
set1.insert(20);
set2.insert(10);
BOOST_TEST(set1 == set2);
}
{
typedef boost_unordered_node_set set;
set set1(0, mod_compare(false), mod_compare(false));
set set2(0, mod_compare(true), mod_compare(true));
BOOST_TEST(set1 == set2);
set1.insert(1);
set2.insert(2);
BOOST_TEST(set1 != set2);
set1.insert(2);
set2.insert(1);
BOOST_TEST(set1 == set2);
set1.insert(10);
set2.insert(20);
BOOST_TEST(set1 != set2);
set1.insert(20);
set2.insert(10);
BOOST_TEST(set1 == set2);
}
#else
typedef boost_unordered_set set;
set set1(0, mod_compare(false), mod_compare(false));
set set2(0, mod_compare(true), mod_compare(true));
@@ -172,7 +296,8 @@ namespace equality_tests {
set1.insert(20);
set2.insert(10);
BOOST_TEST(set1 == set2);
#endif
}
}
} // namespace equality_tests
RUN_TESTS()
+22 -3
View File
@@ -1,6 +1,6 @@
// Copyright 2006-2009 Daniel James.
// Copyright 2022 Christian Mazakas.
// Copyright 2022-2023 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)
@@ -36,9 +36,21 @@ UNORDERED_AUTO_TEST (set_tests) {
#ifdef BOOST_UNORDERED_FOA_TESTS
typedef boost::unordered_flat_set<int> set;
test_equal_insertion<set>(values[0], values[0] + 1);
test_equal_insertion<set>(values[1], values[1] + 2);
test_equal_insertion<set>(values[2], values[2] + 2);
test_equal_insertion<set>(values[3], values[3] + 2);
test_equal_insertion<set>(values[4], values[4] + 3);
typedef boost::unordered_node_set<int> node_set;
test_equal_insertion<node_set>(values[0], values[0] + 1);
test_equal_insertion<node_set>(values[1], values[1] + 2);
test_equal_insertion<node_set>(values[2], values[2] + 2);
test_equal_insertion<node_set>(values[3], values[3] + 2);
test_equal_insertion<node_set>(values[4], values[4] + 3);
#else
typedef boost::unordered_set<int> set;
#endif
test_equal_insertion<set>(values[0], values[0] + 1);
test_equal_insertion<set>(values[1], values[1] + 2);
@@ -52,6 +64,8 @@ UNORDERED_AUTO_TEST (set_tests) {
test_equal_insertion<multiset>(values[2], values[2] + 2);
test_equal_insertion<multiset>(values[3], values[3] + 2);
test_equal_insertion<multiset>(values[4], values[4] + 3);
#endif
}
UNORDERED_AUTO_TEST (map_tests) {
@@ -65,11 +79,16 @@ UNORDERED_AUTO_TEST (map_tests) {
v[2].push_back(std::pair<int const, int>(9, 13));
v[2].push_back(std::pair<int const, int>(432, 24));
for (int i = 0; i < 5; ++i)
#ifdef BOOST_UNORDERED_FOA_TESTS
for (int i = 0; i < 5; ++i)
test_equal_insertion<boost::unordered_flat_map<int, int> >(
v[i].begin(), v[i].end());
for (int i2 = 0; i2 < 5; ++i2)
test_equal_insertion<boost::unordered_node_map<int, int> >(
v[i2].begin(), v[i2].end());
#else
for (int i = 0; i < 5; ++i)
test_equal_insertion<boost::unordered_map<int, int> >(
v[i].begin(), v[i].end());
+2
View File
@@ -110,6 +110,8 @@ 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> >();
test_map_erase_if<boost::unordered_node_map<std::string, int> >();
test_set_erase_if<boost::unordered_node_set<int> >();
#else
test_map_erase_if<boost::unordered_map<std::string, int> >();
test_map_erase_if<boost::unordered_multimap<std::string, int> >();
+9 -2
View File
@@ -270,10 +270,16 @@ namespace erase_tests {
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_node_set<test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_node_set;
boost::unordered_node_map<test::object, test::object, test::hash,
test::equal_to, test::allocator1<test::object> >* test_node_map;
// clang-format off
UNORDERED_TEST(
erase_tests1, ((test_set)(test_map))(
erase_tests1, ((test_set)(test_map)(test_node_set)(test_node_map))(
(default_generator)(generate_collisions)(limited_range)))
// clang-format on
#else
boost::unordered_set<test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_set;
@@ -284,10 +290,11 @@ namespace erase_tests {
boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to, test::allocator2<test::object> >* test_multimap;
// clang-format off
UNORDERED_TEST(
erase_tests1, ((test_set)(test_multiset)(test_map)(test_multimap))(
(default_generator)(generate_collisions)(limited_range)))
// clang-format on
#endif
}
+17 -10
View File
@@ -1,14 +1,10 @@
// Copyright 2016 Daniel James.
// Copyright 2023 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 "../helpers/equivalent.hpp"
#include "../helpers/helpers.hpp"
@@ -113,6 +109,19 @@ namespace extract_tests {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "\n";
}
using test::default_generator;
using test::generate_collisions;
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_node_map<test::object, test::object, test::hash,
test::equal_to, test::allocator1<test::object> >* test_node_map;
boost::unordered_node_set<test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_node_set;
UNORDERED_TEST(extract_tests1,
((test_node_map)(test_node_set))((default_generator)(generate_collisions)))
#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,
@@ -122,12 +131,10 @@ namespace extract_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;
UNORDERED_TEST(
extract_tests1, ((test_set)(test_multiset)(test_map)(test_multimap))(
(default_generator)(generate_collisions)))
}
#endif
} // namespace extract_tests
RUN_TESTS()
+6 -2
View File
@@ -1,6 +1,6 @@
// Copyright 2006-2009 Daniel James.
// Copyright (C) 2022 Christian Mazakas
// Copyright (C) 2022-2023 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)
@@ -138,9 +138,13 @@ namespace find_tests {
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;
boost::unordered_node_set<test::object, test::hash, test::equal_to,
test::allocator2<test::object> >* test_node_set;
boost::unordered_node_map<test::object, test::object, test::hash, test::equal_to,
test::allocator2<test::object> >* test_node_map;
UNORDERED_TEST(
find_tests1, ((test_set)(test_map))(
find_tests1, ((test_set)(test_map)(test_node_set)(test_node_map))(
(default_generator)(generate_collisions)(limited_range)))
#else
boost::unordered_set<test::object, test::hash, test::equal_to,
+43 -1
View File
@@ -1,6 +1,6 @@
// Copyright 2008-2009 Daniel James.
// Copyright 2022 Christian Mazakas.
// Copyright 2022-2023 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)
@@ -8,6 +8,7 @@
#include "../helpers/prefix.hpp"
#ifdef BOOST_UNORDERED_FOA_TESTS
#include <boost/unordered/unordered_flat_map_fwd.hpp>
#include <boost/unordered/unordered_node_map_fwd.hpp>
#include <boost/unordered/detail/implementation.hpp>
#else
#include <boost/unordered/unordered_map_fwd.hpp>
@@ -23,6 +24,13 @@ void call_swap(
swap(x, y);
}
template <typename T>
void call_swap(
boost::unordered_node_map<T, T>& x, boost::unordered_node_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)
@@ -30,6 +38,13 @@ bool call_equals(
return x == y;
}
template <typename T>
bool call_equals(
boost::unordered_node_map<T, T>& x, boost::unordered_node_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)
@@ -37,7 +52,15 @@ bool call_not_equals(
return x != y;
}
template <typename T>
bool call_not_equals(
boost::unordered_node_map<T, T>& x, boost::unordered_node_map<T, T>& y)
{
return x != y;
}
#include <boost/unordered/unordered_flat_map.hpp>
#include <boost/unordered/unordered_node_map.hpp>
#else
template <typename T>
void call_swap(boost::unordered_map<T, T>& x, boost::unordered_map<T, T>& y)
@@ -85,6 +108,7 @@ bool call_not_equals(
#ifdef BOOST_UNORDERED_FOA_TESTS
typedef boost::unordered_flat_map<int, int> int_map;
typedef boost::unordered_node_map<int, int> int_node_map;
#else
typedef boost::unordered_map<int, int> int_map;
typedef boost::unordered_multimap<int, int> int_multimap;
@@ -106,6 +130,24 @@ UNORDERED_AUTO_TEST (use_map_fwd_declared_function) {
BOOST_TEST(call_not_equals(x, y));
}
#ifdef BOOST_UNORDERED_FOA_TESTS
UNORDERED_AUTO_TEST (use_node_map_fwd_declared_function) {
int_node_map x, y;
x[1] = 2;
y[2] = 1;
call_swap(x, y);
BOOST_TEST(y.find(1) != y.end() && y.find(1)->second == 2);
BOOST_TEST(y.find(2) == y.end());
BOOST_TEST(x.find(1) == x.end());
BOOST_TEST(x.find(2) != x.end() && x.find(2)->second == 1);
BOOST_TEST(!call_equals(x, y));
BOOST_TEST(call_not_equals(x, y));
}
#endif
#ifndef BOOST_UNORDERED_FOA_TESTS
UNORDERED_AUTO_TEST (use_multimap_fwd_declared_function) {
int_multimap x, y;
+58 -2
View File
@@ -1,6 +1,6 @@
// Copyright 2008-2009 Daniel James.
// Copyright 2022 Christian Mazakas.
// Copyright 2022-2023 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)
@@ -8,6 +8,7 @@
#include "../helpers/prefix.hpp"
#ifdef BOOST_UNORDERED_FOA_TESTS
#include <boost/unordered/unordered_flat_set_fwd.hpp>
#include <boost/unordered/unordered_node_set_fwd.hpp>
#include <boost/unordered/detail/implementation.hpp>
#else
#include <boost/unordered/unordered_set_fwd.hpp>
@@ -31,12 +32,22 @@ template <class Value, class Hash, class Pred, class Alloc>
true_type is_unordered_set_impl(
boost::unordered_flat_set<Value, Hash, Pred, Alloc>*);
template <class Value, class Hash, class Pred, class Alloc>
true_type is_unordered_set_impl(
boost::unordered_node_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>
void call_swap(boost::unordered_node_set<T>& x, boost::unordered_node_set<T>& y)
{
swap(x, y);
}
template <typename T>
bool call_equals(
boost::unordered_flat_set<T>& x, boost::unordered_flat_set<T>& y)
@@ -44,12 +55,26 @@ bool call_equals(
return x == y;
}
template <typename T>
bool call_equals(
boost::unordered_node_set<T>& x, boost::unordered_node_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;
}
template <typename T>
bool call_not_equals(
boost::unordered_node_set<T>& x, boost::unordered_node_set<T>& y)
{
return x != y;
}
#else
template <class Value, class Hash, class Pred, class Alloc>
true_type is_unordered_set_impl(
@@ -100,6 +125,7 @@ bool call_not_equals(
#ifdef BOOST_UNORDERED_FOA_TESTS
typedef boost::unordered_flat_set<int> int_set;
typedef boost::unordered_node_set<int> int_node_set;
#else
typedef boost::unordered_set<int> int_set;
typedef boost::unordered_multiset<int> int_multiset;
@@ -107,10 +133,15 @@ typedef boost::unordered_multiset<int> int_multiset;
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
BOOST_TEST(
sizeof(is_unordered_set_impl((int_node_set*)0)) == sizeof(true_type));
#endif
}
#ifdef BOOST_UNORDERED_FOA_TESTS
#include <boost/unordered/unordered_flat_set.hpp>
#include <boost/unordered/unordered_node_set.hpp>
#else
#include <boost/unordered_set.hpp>
#endif
@@ -118,10 +149,17 @@ UNORDERED_AUTO_TEST (use_fwd_declared_trait_without_definition) {
UNORDERED_AUTO_TEST (use_fwd_declared_trait) {
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));
}
#ifdef BOOST_UNORDERED_FOA_TESTS
UNORDERED_AUTO_TEST (use_node_fwd_declared_trait) {
int_node_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));
}
#endif
UNORDERED_AUTO_TEST (use_set_fwd_declared_function) {
int_set x, y;
x.insert(1);
@@ -138,6 +176,24 @@ UNORDERED_AUTO_TEST (use_set_fwd_declared_function) {
BOOST_TEST(call_not_equals(x, y));
}
#ifdef BOOST_UNORDERED_FOA_TESTS
UNORDERED_AUTO_TEST (use_node_set_fwd_declared_function) {
int_node_set x, y;
x.insert(1);
y.insert(2);
call_swap(x, y);
BOOST_TEST(y.find(1) != y.end());
BOOST_TEST(y.find(2) == y.end());
BOOST_TEST(x.find(1) == x.end());
BOOST_TEST(x.find(2) != x.end());
BOOST_TEST(!call_equals(x, y));
BOOST_TEST(call_not_equals(x, y));
}
#endif
#ifndef BOOST_UNORDERED_FOA_TESTS
UNORDERED_AUTO_TEST (use_multiset_fwd_declared_function) {
int_multiset x, y;
+9 -8
View File
@@ -1,6 +1,6 @@
// Copyright 2009 Daniel James.
// Copyright 2022 Christian Mazakas.
// Copyright 2022-2023 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)
@@ -13,11 +13,12 @@ namespace x {
{
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_map<D, D> x;
boost::unordered_node_map<D, D> y;
#else
boost::unordered_map<D, D> x;
#endif
};
}
} // namespace x
namespace incomplete_test {
// Declare, but don't define some types.
@@ -33,11 +34,11 @@ namespace incomplete_test {
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,
typedef boost::unordered_flat_set<value, hash, equals, allocator<value> > set;
typedef boost::unordered_node_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> >
typedef boost::unordered_node_set<value, hash, equals, allocator<value> >
multiset;
#else
typedef boost::unordered_map<value, value, hash, equals,
@@ -97,7 +98,7 @@ namespace incomplete_test {
};
struct struct2
{
boost::unordered_flat_map<struct2, struct2, hash, equals,
boost::unordered_node_map<struct2, struct2, hash, equals,
allocator<std::pair<struct2 const, struct2> > >
x;
};
@@ -107,7 +108,7 @@ namespace incomplete_test {
};
struct struct4
{
boost::unordered_flat_set<struct4, hash, equals, allocator<struct4> > x;
boost::unordered_node_set<struct4, hash, equals, allocator<struct4> > x;
};
#else
struct struct1
@@ -195,7 +196,7 @@ namespace incomplete_test {
bool operator==(struct2 const&, struct2 const&) { return true; }
bool operator==(struct3 const&, struct3 const&) { return true; }
bool operator==(struct4 const&, struct4 const&) { return true; }
}
} // namespace incomplete_test
int main()
{
+209 -16
View File
@@ -7,9 +7,16 @@
#error "This test is only for the FOA-style conatiners"
#endif
#include "../helpers/test.hpp"
#include "../helpers/unordered.hpp"
#include "../helpers/test.hpp"
#include <boost/config.hpp>
#if defined(BOOST_LIBSTDCXX_VERSION)
#if BOOST_LIBSTDCXX_VERSION < 60000
#define BOOST_UNORDERED_NO_INIT_TYPE_TESTS
#endif
#endif
struct move_only
{
@@ -26,18 +33,49 @@ struct move_only
}
};
namespace std{
namespace std {
template <> struct hash<move_only>
{
std::size_t operator()(move_only const& mo) const noexcept
template <> struct hash<move_only>
{
return std::hash<int>()(mo.x_);
std::size_t operator()(move_only const& mo) const noexcept
{
return std::hash<int>()(mo.x_);
}
};
} // namespace std
#ifndef BOOST_UNORDERED_NO_INIT_TYPE_TESTS
struct immovable
{
int x_ = -1;
immovable() = default;
immovable(int x) : x_{x} {}
immovable(immovable const&) = delete;
immovable(immovable&&) = delete;
friend bool operator==(immovable const& lhs, immovable const& rhs)
{
return lhs.x_ == rhs.x_;
}
};
namespace std {
template <> struct hash<immovable>
{
std::size_t operator()(immovable const& im) const noexcept
{
return std::hash<int>()(im.x_);
}
};
} // namespace std
#endif
struct raii_tracker
{
static unsigned move_constructs;
@@ -68,15 +106,15 @@ struct raii_tracker
}
};
namespace std{
namespace std {
template <> struct hash<raii_tracker>
{
std::size_t operator()(raii_tracker const& rt) const noexcept
template <> struct hash<raii_tracker>
{
return std::hash<int>()(rt.x_);
}
};
std::size_t operator()(raii_tracker const& rt) const noexcept
{
return std::hash<int>()(rt.x_);
}
};
} // namespace std
@@ -90,9 +128,7 @@ static void test_move_only()
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,
"");
static_assert(std::is_same<std::pair<move_only, int>, init_type>::value, "");
map.insert(std::make_pair(move_only(1), v));
map.insert({move_only(2), v});
@@ -235,10 +271,167 @@ static void test_insert_hint_tracking()
BOOST_TEST_EQ(raii_tracker::move_constructs, 7u + 2u * map.size());
}
static void test_immovable()
{
#ifndef BOOST_UNORDERED_NO_INIT_TYPE_TESTS
int const v = 128;
boost::unordered_node_map<immovable, int, std::hash<immovable> > map;
using init_type = decltype(map)::init_type;
static_assert(std::is_same<std::pair<immovable, int>, init_type>::value, "");
map.emplace(1, v);
map.emplace(2, v);
BOOST_TEST_EQ(map.size(), 2u);
map.rehash(1024);
BOOST_TEST_GE(map.bucket_count(), 1024u);
#endif
}
static void test_insert_node_tracking()
{
raii_tracker::reset_counts();
BOOST_TEST_EQ(raii_tracker::copy_constructs, 0u);
BOOST_TEST_EQ(raii_tracker::move_constructs, 0u);
boost::unordered_node_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);
}
static void test_insert_hint_node_tracking()
{
raii_tracker::reset_counts();
BOOST_TEST_EQ(raii_tracker::copy_constructs, 0u);
BOOST_TEST_EQ(raii_tracker::move_constructs, 0u);
boost::unordered_node_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);
}
int main()
{
test_move_only();
test_insert_tracking();
test_insert_hint_tracking();
test_immovable();
test_insert_node_tracking();
test_insert_hint_node_tracking();
return boost::report_errors();
}
+23 -14
View File
@@ -1,6 +1,6 @@
// Copyright 2016 Daniel James.
// Copyright 2022 Christian Mazakas.
// Copyright 2022-2023 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)
@@ -88,12 +88,11 @@ 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
template <class X> static void insert_hint_unique(X*)
{
typedef X container;
container x;
x.insert(x.cbegin(), 10);
BOOST_TEST_EQ(x.size(), 1u);
@@ -101,12 +100,10 @@ namespace insert_hint {
test::check_equivalent_keys(x);
}
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
template <class X> static void insert_hint_unique_single(X*)
{
typedef X container;
container x;
x.insert(10);
@@ -121,6 +118,18 @@ namespace insert_hint {
BOOST_TEST_EQ(x.count(20), 1u);
test::check_equivalent_keys(x);
}
}
#ifdef BOOST_UNORDERED_FOA_TESTS
static boost::unordered_flat_set<int>* test_set;
static boost::unordered_node_set<int>* test_node_set;
UNORDERED_TEST(insert_hint_unique, ((test_set)(test_node_set)))
UNORDERED_TEST(insert_hint_unique_single, ((test_set)(test_node_set)))
#else
static boost::unordered_set<int>* test_set;
UNORDERED_TEST(insert_hint_unique, ((test_set)))
UNORDERED_TEST(insert_hint_unique_single, ((test_set)))
#endif
} // namespace insert_hint
RUN_TESTS()
+312 -149
View File
@@ -1,6 +1,6 @@
// Copyright 2006-2010 Daniel James.
// Copyright (C) 2022 Christian Mazakas
// Copyright (C) 2022-2023 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)
@@ -17,6 +17,7 @@
#include "../helpers/input_iterator.hpp"
#include "../helpers/helpers.hpp"
#include <boost/move/core.hpp>
#include <vector>
namespace insert_tests {
@@ -693,6 +694,69 @@ namespace insert_tests {
BOOST_TEST_EQ(x.size(), 1000u);
}
struct pointer_constructible
{
int x;
pointer_constructible(int x_) : x(x_) {}
pointer_constructible(pointer_constructible const& p) : x(p.x) {}
pointer_constructible(pointer_constructible* const&) : x(-1) {}
pointer_constructible(BOOST_RV_REF(pointer_constructible*)) : x(-1) {}
};
struct pointer_constructible_hash
{
typedef void is_transparent;
std::size_t operator()(pointer_constructible const& p) const
{
return boost::hash<int>()(p.x);
}
};
struct pointer_constructible_equal_to
{
typedef void is_transparent;
bool operator()(
pointer_constructible const& lhs, pointer_constructible const& rhs) const
{
return lhs.x == rhs.x;
}
};
template <class X>
static void set_tests2(X*)
{
X set, set2;
pointer_constructible pc(1337);
pointer_constructible* const addr_pc = &pc;
set.insert(pc); // 1337
set.insert(&pc); // -1
set.insert(addr_pc); // -1
BOOST_TEST_EQ(set.size(), 2u);
BOOST_TEST(set.find(pc) != set.end());
BOOST_TEST(set.find(-1) != set.end());
BOOST_TEST(set.find(-2) == set.end());
set2 = set;
BOOST_TEST_EQ(set2.size(), 2u);
BOOST_TEST(set2.find(pc) != set2.end());
BOOST_TEST(set2.find(-1) != set2.end());
BOOST_TEST(set2.find(-2) == set2.end());
set.rehash(set.bucket_count() + 1);
BOOST_TEST_EQ(set.size(), 2u);
BOOST_TEST(set.find(pc) != set.end());
BOOST_TEST(set.find(-1) != set.end());
BOOST_TEST(set.find(-2) == set.end());
}
template <class X>
void try_emplace_tests(X*, test::random_generator generator)
{
@@ -892,45 +956,62 @@ namespace insert_tests {
#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_node_set<test::movable, test::hash, test::equal_to,
std::allocator<test::movable> >* test_node_set_std_alloc;
boost::unordered_flat_set<test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_set;
boost::unordered_node_set<test::movable, test::hash, test::equal_to,
test::allocator1<test::object> >* test_node_set;
boost::unordered_flat_map<test::movable, test::movable, test::hash,
test::equal_to, test::allocator2<test::movable> >* test_map;
boost::unordered_node_map<test::movable, test::movable, test::hash,
test::equal_to, test::allocator2<test::movable> >* test_node_map;
boost::unordered_flat_set<pointer_constructible, pointer_constructible_hash,
pointer_constructible_equal_to, test::allocator1<pointer_constructible> >*
test_pc_set;
boost::unordered_node_set<pointer_constructible, pointer_constructible_hash,
pointer_constructible_equal_to, test::allocator1<pointer_constructible> >*
test_pc_node_set;
UNORDERED_TEST(unique_insert_tests1,
((test_set_std_alloc)(test_set)(test_map))(
((test_set_std_alloc)(test_node_set_std_alloc)
(test_set)(test_node_set)(test_map)(test_node_map))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(
insert_tests2, ((test_set)(test_map))(
insert_tests2, ((test_set)(test_node_set)(test_map)(test_node_map))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(unique_emplace_tests1,
((test_set_std_alloc)(test_set)(test_map))(
((test_set_std_alloc)(test_set)(test_node_set)(test_map)(test_node_map))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(move_emplace_tests,
((test_set_std_alloc)(test_set)(test_map))(
((test_set_std_alloc)(test_set)(test_node_set)(test_map)(test_node_map))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(default_emplace_tests,
((test_set_std_alloc)(test_set)(test_map))(
((test_set_std_alloc)(test_set)(test_node_set)(test_map)(test_node_map))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(map_tests,
((test_map))((default_generator)(generate_collisions)(limited_range)))
((test_map)(test_node_map))
((default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(
map_tests2, ((test_map))((default_generator)(generate_collisions)))
map_tests2, ((test_map)(test_node_map))((default_generator)(generate_collisions)))
UNORDERED_TEST(map_insert_range_test1,
((test_map))((default_generator)(generate_collisions)(limited_range)))
((test_map)(test_node_map))((default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(map_insert_range_test2,
((test_map))((default_generator)(generate_collisions)(limited_range)))
((test_map)(test_node_map))((default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(
set_tests, ((test_set_std_alloc)(test_set))((default_generator)))
set_tests, ((test_set_std_alloc)(test_set)(test_node_set))((default_generator)))
UNORDERED_TEST(set_tests2, ((test_pc_set)(test_pc_node_set)))
#else
boost::unordered_set<test::movable, test::hash, test::equal_to,
std::allocator<test::movable> >* test_set_std_alloc;
@@ -946,6 +1027,10 @@ namespace insert_tests {
boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to, test::allocator1<test::object> >* test_multimap;
boost::unordered_set<pointer_constructible, pointer_constructible_hash,
pointer_constructible_equal_to, test::allocator1<pointer_constructible> >*
test_pc_set;
UNORDERED_TEST(unique_insert_tests1,
((test_set_std_alloc)(test_set)(test_map))(
(default_generator)(generate_collisions)(limited_range)))
@@ -990,6 +1075,8 @@ namespace insert_tests {
UNORDERED_TEST(
set_tests, ((test_set_std_alloc)(test_set)(test_multiset))((default_generator)))
UNORDERED_TEST(set_tests2, ((test_pc_set)))
#endif
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
@@ -1009,23 +1096,19 @@ 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
template <template <class Key, class Hash = boost::hash<Key>,
class Pred = std::equal_to<Key>, class Allocator = std::allocator<Key> >
class Set>
static void insert_initializer_list_set_impl()
{
Set<int> set;
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
Set<initialize_from_two_ints> set2;
#if defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 5))
set2.insert({{1, 2}});
#else
@@ -1053,6 +1136,16 @@ namespace insert_tests {
BOOST_TEST(set2.find({8, 7}) == set2.end());
}
UNORDERED_AUTO_TEST (insert_initializer_list_set) {
#ifdef BOOST_UNORDERED_FOA_TESTS
insert_initializer_list_set_impl<boost::unordered_flat_set>();
insert_initializer_list_set_impl<boost::unordered_node_set>();
#else
insert_initializer_list_set_impl<boost::unordered_set>();
boost::unordered_set<int> set;
#endif
}
#ifndef BOOST_UNORDERED_FOA_TESTS
#if !BOOST_WORKAROUND(BOOST_MSVC, == 1800)
@@ -1074,18 +1167,31 @@ namespace insert_tests {
#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({});
template <class X> static void insert_initializer_list_map(X*)
{
X map;
BOOST_TEST(map.empty());
map.insert({{"a", "b"}, {"a", "b"}, {"d", ""}});
BOOST_TEST_EQ(map.size(), 2u);
}
#ifdef BOOST_UNORDERED_FOA_TESTS
static boost::unordered_flat_map<std::string, std::string>* test_str_map;
static boost::unordered_node_map<std::string, std::string>* test_str_node_map;
// clang-format off
UNORDERED_TEST(insert_initializer_list_map,
((test_str_map)(test_str_node_map)))
// clang-format on
#else
static boost::unordered_map<std::string, std::string>* test_str_map;
// clang-format off
UNORDERED_TEST(insert_initializer_list_map, ((test_str_map)))
// clang-format on
#endif
#ifndef BOOST_UNORDERED_FOA_TESTS
UNORDERED_AUTO_TEST (insert_initializer_list_multimap) {
boost::unordered_multimap<std::string, std::string> multimap;
@@ -1124,65 +1230,72 @@ 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
template <class X> static void map_emplace_test(X*)
{
X x;
#if !BOOST_UNORDERED_SUN_WORKAROUNDS1
x.emplace();
BOOST_TEST(
x.find(0) != x.end() && x.find(0)->second == overloaded_constructor());
x.emplace();
BOOST_TEST(
x.find(0) != x.end() && x.find(0)->second == overloaded_constructor());
#endif
x.emplace(2, 3);
BOOST_TEST(
x.find(2) != x.end() && x.find(2)->second == overloaded_constructor(3));
x.emplace(2, 3);
BOOST_TEST(
x.find(2) != x.end() && x.find(2)->second == overloaded_constructor(3));
x.try_emplace(5);
BOOST_TEST(
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,
test::allocator1<std::pair<int const, overloaded_constructor> > >
x;
#if !BOOST_UNORDERED_SUN_WORKAROUNDS1
x.emplace();
BOOST_TEST(
x.find(0) != x.end() && x.find(0)->second == overloaded_constructor());
#endif
x.emplace(2, 3);
BOOST_TEST(
x.find(2) != x.end() && x.find(2)->second == overloaded_constructor(3));
}
#endif
x.try_emplace(5);
BOOST_TEST(
x.find(5) != x.end() && x.find(5)->second == overloaded_constructor());
}
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;
#ifndef BOOST_UNORDERED_FOA_TESTS
template <class X> static void multimap_emplace_test(X*)
{
X x;
#if !BOOST_UNORDERED_SUN_WORKAROUNDS1
x.emplace();
BOOST_TEST(
x.find(0) != x.end() && x.find(0)->second == overloaded_constructor());
#endif
x.emplace(2, 3);
BOOST_TEST(
x.find(2) != x.end() && x.find(2)->second == overloaded_constructor(3));
}
#endif
#ifdef BOOST_UNORDERED_FOA_TESTS
static boost::unordered_flat_map<int, overloaded_constructor, test::hash,
test::equal_to,
test::allocator1<std::pair<int const, overloaded_constructor> > >*
test_oc_map;
static boost::unordered_node_map<int, overloaded_constructor, test::hash,
test::equal_to,
test::allocator1<std::pair<int const, overloaded_constructor> > >*
test_oc_node_map;
UNORDERED_TEST(map_emplace_test, ((test_oc_map)(test_oc_node_map)))
#else
static boost::unordered_map<int, overloaded_constructor, test::hash,
test::equal_to,
test::allocator1<std::pair<int const, overloaded_constructor> > >*
test_oc_map;
static boost::unordered_multimap<int, overloaded_constructor, test::hash,
test::equal_to,
test::allocator1<std::pair<int const, overloaded_constructor> > >*
test_oc_multimap;
UNORDERED_TEST(map_emplace_test, ((test_oc_map)))
UNORDERED_TEST(multimap_emplace_test, ((test_oc_multimap)))
#endif
template <class X> static void set_emplace_test(X*)
{
X x;
overloaded_constructor check;
#if !BOOST_UNORDERED_SUN_WORKAROUNDS1
x.emplace();
BOOST_TEST(x.find(check) != x.end() && *x.find(check) == check);
@@ -1209,6 +1322,18 @@ namespace insert_tests {
BOOST_TEST(x.find(check) != x.end() && *x.find(check) == check);
}
#ifdef BOOST_UNORDERED_FOA_TESTS
static boost::unordered_flat_set<overloaded_constructor>* test_oc_set;
static boost::unordered_node_set<overloaded_constructor>* test_oc_node_set;
UNORDERED_TEST(set_emplace_test, ((test_oc_set)(test_oc_node_set)))
#else
static boost::unordered_set<overloaded_constructor>* test_oc_set;
static boost::unordered_multiset<overloaded_constructor>* test_oc_multiset;
UNORDERED_TEST(set_emplace_test, ((test_oc_set)(test_oc_multiset)))
#endif
struct derived_from_piecewise_construct_t
: boost::unordered::piecewise_construct_t
{
@@ -1358,6 +1483,14 @@ namespace insert_tests {
#ifndef BOOST_UNORDERED_FOA_TESTS
static 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> > >* test_pw_oc_map;
static boost::unordered_set<std::pair<overloaded_constructor,
overloaded_constructor> >* test_pair_oc_set;
#define PIECEWISE_TEST_NAME boost_tuple_piecewise_tests
#define PIECEWISE_NAMESPACE boost::unordered
#define TUPLE_NAMESPACE boost
@@ -1389,6 +1522,14 @@ namespace insert_tests {
#if !defined(BOOST_NO_CXX11_HDR_TUPLE) && \
BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT
#ifdef BOOST_UNORDERED_FOA_TESTS
static boost::unordered_flat_set<std::pair<overloaded_constructor,
overloaded_constructor> >* test_pair_oc_set;
static boost::unordered_node_set<std::pair<overloaded_constructor,
overloaded_constructor> >* test_pair_oc_node_set;
#endif
#define PIECEWISE_TEST_NAME std_piecewise_tests
#define PIECEWISE_NAMESPACE std
#define TUPLE_NAMESPACE std
@@ -1402,27 +1543,17 @@ RUN_TESTS_QUIET()
#else // PIECEWISE_TEST_NAME
UNORDERED_AUTO_TEST (PIECEWISE_TEST_NAME) {
#define MAP_PIECEWISE_TEST BOOST_PP_CAT(map_, PIECEWISE_TEST_NAME)
#define SET_PIECEWISE_TEST BOOST_PP_CAT(set_, PIECEWISE_TEST_NAME)
template <class X>
static void MAP_PIECEWISE_TEST(X*)
{
#if EMULATING_PIECEWISE_CONSTRUCTION
test::detail::disable_construction_tracking _scoped;
#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 x;
x.emplace(PIECEWISE_NAMESPACE::piecewise_construct,
TUPLE_NAMESPACE::make_tuple(), TUPLE_NAMESPACE::make_tuple());
@@ -1466,70 +1597,102 @@ UNORDERED_AUTO_TEST (PIECEWISE_TEST_NAME) {
x.find(overloaded_constructor(2, 3))->second ==
overloaded_constructor(4, 5, 6));
}
#ifndef BOOST_UNORDERED_FOA_TESTS
template <class X>
static void SET_PIECEWISE_TEST(X*)
{
boost::unordered_multimap<overloaded_constructor, overloaded_constructor,
boost::hash<overloaded_constructor>,
std::equal_to<overloaded_constructor>,
test::allocator1<
std::pair<overloaded_constructor const, overloaded_constructor> > >
x;
#if EMULATING_PIECEWISE_CONSTRUCTION
test::detail::disable_construction_tracking _scoped;
#endif
X x;
std::pair<overloaded_constructor, overloaded_constructor> check;
x.emplace(PIECEWISE_NAMESPACE::piecewise_construct,
TUPLE_NAMESPACE::make_tuple(), TUPLE_NAMESPACE::make_tuple());
BOOST_TEST(
x.find(overloaded_constructor()) != x.end() &&
x.find(overloaded_constructor())->second == overloaded_constructor());
BOOST_TEST(x.find(check) != x.end() && *x.find(check) == check);
x.emplace(convertible_to_piecewise(), TUPLE_NAMESPACE::make_tuple(1),
TUPLE_NAMESPACE::make_tuple());
BOOST_TEST(
x.find(overloaded_constructor(1)) != x.end() &&
x.find(overloaded_constructor(1))->second == overloaded_constructor());
x.emplace(piecewise_rvalue(), TUPLE_NAMESPACE::make_tuple(2, 3),
TUPLE_NAMESPACE::make_tuple(4, 5, 6));
BOOST_TEST(x.find(overloaded_constructor(2, 3)) != x.end() &&
x.find(overloaded_constructor(2, 3))->second ==
overloaded_constructor(4, 5, 6));
derived_from_piecewise_construct_t d;
x.emplace(
d, TUPLE_NAMESPACE::make_tuple(9, 3, 1), TUPLE_NAMESPACE::make_tuple(10));
BOOST_TEST(x.find(overloaded_constructor(9, 3, 1)) != x.end() &&
x.find(overloaded_constructor(9, 3, 1))->second ==
overloaded_constructor(10));
x.clear();
x.emplace(PIECEWISE_NAMESPACE::piecewise_construct,
TUPLE_NAMESPACE::make_tuple(1), TUPLE_NAMESPACE::make_tuple(2, 3));
check =
std::make_pair(overloaded_constructor(1), overloaded_constructor(2, 3));
BOOST_TEST(x.find(check) != x.end() && *x.find(check) == check);
}
#endif
}
UNORDERED_AUTO_TEST (BOOST_PP_CAT(PIECEWISE_TEST_NAME, 2)) {
#if defined(BOOST_UNORDERED_FOA_TESTS)
static 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> > >* test_pw_oc_map;
static boost::unordered_node_map<overloaded_constructor,
overloaded_constructor, boost::hash<overloaded_constructor>,
std::equal_to<overloaded_constructor>,
test::allocator1<std::pair<overloaded_constructor const,
overloaded_constructor> > >* test_pw_oc_node_map;
// clang-format off
UNORDERED_TEST(MAP_PIECEWISE_TEST, ((test_pw_oc_map)(test_pw_oc_node_map)))
// clang-format on
#else
// clang-format off
UNORDERED_TEST(MAP_PIECEWISE_TEST, ((test_pw_oc_map)))
// clang-format on
#endif
#ifndef BOOST_UNORDERED_FOA_TESTS
UNORDERED_AUTO_TEST (BOOST_PP_CAT(multimap_, PIECEWISE_TEST_NAME)) {
{
#if EMULATING_PIECEWISE_CONSTRUCTION
test::detail::disable_construction_tracking _scoped;
test::detail::disable_construction_tracking _scoped;
#endif
boost::unordered_multimap<overloaded_constructor, overloaded_constructor,
boost::hash<overloaded_constructor>,
std::equal_to<overloaded_constructor>,
test::allocator1<
std::pair<overloaded_constructor const, overloaded_constructor> > >
x;
x.emplace(PIECEWISE_NAMESPACE::piecewise_construct,
TUPLE_NAMESPACE::make_tuple(), TUPLE_NAMESPACE::make_tuple());
BOOST_TEST(
x.find(overloaded_constructor()) != x.end() &&
x.find(overloaded_constructor())->second == overloaded_constructor());
x.emplace(convertible_to_piecewise(), TUPLE_NAMESPACE::make_tuple(1),
TUPLE_NAMESPACE::make_tuple());
BOOST_TEST(
x.find(overloaded_constructor(1)) != x.end() &&
x.find(overloaded_constructor(1))->second == overloaded_constructor());
x.emplace(piecewise_rvalue(), TUPLE_NAMESPACE::make_tuple(2, 3),
TUPLE_NAMESPACE::make_tuple(4, 5, 6));
BOOST_TEST(x.find(overloaded_constructor(2, 3)) != x.end() &&
x.find(overloaded_constructor(2, 3))->second ==
overloaded_constructor(4, 5, 6));
derived_from_piecewise_construct_t d;
x.emplace(d, TUPLE_NAMESPACE::make_tuple(9, 3, 1),
TUPLE_NAMESPACE::make_tuple(10));
BOOST_TEST(x.find(overloaded_constructor(9, 3, 1)) != x.end() &&
x.find(overloaded_constructor(9, 3, 1))->second ==
overloaded_constructor(10));
}
}
#endif
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_set<
std::pair<overloaded_constructor, overloaded_constructor> >
x;
// clang-format off
UNORDERED_TEST(SET_PIECEWISE_TEST,
((test_pair_oc_set)(test_pair_oc_node_set)))
// clang-format on
#else
boost::unordered_set<
std::pair<overloaded_constructor, overloaded_constructor> >
x;
// clang-format off
UNORDERED_TEST(SET_PIECEWISE_TEST, ((test_pair_oc_set)))
// clang-format on
#endif
std::pair<overloaded_constructor, overloaded_constructor> check;
x.emplace(PIECEWISE_NAMESPACE::piecewise_construct,
TUPLE_NAMESPACE::make_tuple(), TUPLE_NAMESPACE::make_tuple());
BOOST_TEST(x.find(check) != x.end() && *x.find(check) == check);
x.clear();
x.emplace(PIECEWISE_NAMESPACE::piecewise_construct,
TUPLE_NAMESPACE::make_tuple(1), TUPLE_NAMESPACE::make_tuple(2, 3));
check =
std::make_pair(overloaded_constructor(1), overloaded_constructor(2, 3));
BOOST_TEST(x.find(check) != x.end() && *x.find(check) == check);
}
#undef PIECEWISE_TEST_NAME
#undef PIECEWISE_NAMESPACE
+6 -3
View File
@@ -1,20 +1,23 @@
// Copyright 2006-2009 Daniel James.
// Copyright 2022 Christian Mazakas.
// Copyright 2022-2023 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/unordered.hpp"
#ifdef BOOST_UNORDERED_FOA_TESTS
void foo(boost::unordered_flat_set<int>&, boost::unordered_flat_map<int, int>&);
void foo(boost::unordered_flat_set<int>&, boost::unordered_flat_map<int, int>&,
boost::unordered_node_set<int>&, boost::unordered_node_map<int, int>&);
int main()
{
boost::unordered_flat_set<int> x1;
boost::unordered_flat_map<int, int> x2;
boost::unordered_node_set<int> x3;
boost::unordered_node_map<int, int> x4;
foo(x1, x2);
foo(x1, x2, x3, x4);
return 0;
}
+6 -3
View File
@@ -1,14 +1,15 @@
// Copyright 2006-2009 Daniel James.
// Copyright 2022 Christian Mazakas.
// Copyright 2022-2023 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/unordered.hpp"
#ifdef BOOST_UNORDERED_FOA_TESTS
void foo(
boost::unordered_flat_set<int>& x1, boost::unordered_flat_map<int, int>& x2)
void foo(boost::unordered_flat_set<int>& x1,
boost::unordered_flat_map<int, int>& x2, boost::unordered_node_set<int>& x3,
boost::unordered_node_map<int, int>& x4)
{
#if BOOST_WORKAROUND(BOOST_CODEGEARC, BOOST_TESTED_AT(0x0613))
struct dummy
@@ -20,6 +21,8 @@ void foo(
x1.insert(1);
x2[2] = 2;
x3.insert(3);
x4.insert(std::make_pair(4, 5));
}
#else
void foo(boost::unordered_set<int>& x1, boost::unordered_map<int, int>& x2,
+8 -3
View File
@@ -1,6 +1,6 @@
// Copyright 2006-2009 Daniel James.
// Copyright 2022 Christian Mazakas.
// Copyright 2022-2023 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)
@@ -86,12 +86,17 @@ namespace load_factor_tests {
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_set<int>* int_set_ptr;
boost::unordered_flat_map<int, int>* int_map_ptr;
boost::unordered_node_set<int>* int_node_set_ptr;
boost::unordered_node_map<int, int>* int_node_map_ptr;
UNORDERED_TEST(set_load_factor_tests, ((int_set_ptr)(int_map_ptr)))
// clang-format off
UNORDERED_TEST(set_load_factor_tests,
((int_set_ptr)(int_map_ptr)(int_node_set_ptr)(int_node_map_ptr)))
UNORDERED_TEST(load_factor_insert_tests,
((int_set_ptr)(int_map_ptr))(
((int_set_ptr)(int_map_ptr)(int_node_set_ptr)(int_node_map_ptr))(
(default_generator)(generate_collisions)(limited_range)))
// clang-format on
#else
boost::unordered_set<int>* int_set_ptr;
boost::unordered_multiset<int>* int_multiset_ptr;
+21 -1
View File
@@ -1,3 +1,8 @@
// Copyright 2022-2023 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 "max_load_tests is currently only supported by open-addressed containers"
#else
@@ -69,9 +74,24 @@ boost::unordered_flat_map<test::object, test::object, test::hash,
test::allocator1<std::pair<test::object const, test::object> > >*
test_map_tracking;
boost::unordered_node_set<int>* int_node_set_ptr;
boost::unordered_node_map<test::movable, test::movable, test::hash,
test::equal_to, test::allocator2<test::movable> >* test_node_map_ptr;
boost::unordered_node_set<test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_node_set_tracking;
boost::unordered_node_map<test::object, test::object, test::hash,
test::equal_to,
test::allocator1<std::pair<test::object const, test::object> > >*
test_node_map_tracking;
// clang-format off
UNORDERED_TEST(max_load_tests,
((int_set_ptr)(test_map_ptr)(test_set_tracking)(test_map_tracking))(
((int_set_ptr)(test_map_ptr)(test_set_tracking)(test_map_tracking)
(int_node_set_ptr)(test_node_map_ptr)
(test_node_set_tracking)(test_node_map_tracking))(
(sequential)))
// clang-format on
#endif
RUN_TESTS()
+90 -17
View File
@@ -1,6 +1,6 @@
// Copyright 2016 Daniel James.
// Copyright 2022 Christian Mazakas.
// Copyright 2022-2023 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)
@@ -16,14 +16,9 @@
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
template <class X> static void merge_set(X*)
{
X x, y;
x.merge(y);
BOOST_TEST(x.empty());
@@ -237,22 +232,23 @@ namespace merge_tests {
using test::generate_collisions;
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_set<int>* int_set;
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_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;
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_set, ((int_set)))
UNORDERED_TEST(merge_empty_test,
((test_set_std_alloc))
((test_set_std_alloc))
@@ -308,7 +304,82 @@ UNORDERED_TEST(merge_into_unique_keys_test,
((0)(1)(2))
((default_generator)(generate_collisions)))
// clang-format on
boost::unordered_node_set<int>* int_node_set;
boost::unordered_node_set<test::movable, test::hash, test::equal_to,
std::allocator<test::movable> >* test_node_set_std_alloc;
boost::unordered_node_map<test::object, test::object, test::hash,
test::equal_to, std::allocator<test::object> >* test_node_map_std_alloc;
boost::unordered_node_set<test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_node_set;
boost::unordered_node_map<test::movable, test::movable, test::hash,
test::equal_to, test::allocator2<test::movable> >* test_node_map;
// clang-format off
UNORDERED_TEST(merge_set, ((int_node_set)))
UNORDERED_TEST(merge_empty_test,
((test_node_set_std_alloc))
((test_node_set_std_alloc))
((default_generator)(generate_collisions)))
UNORDERED_TEST(merge_empty_test,
((test_node_map_std_alloc))
((test_node_map_std_alloc))
((default_generator)(generate_collisions)))
UNORDERED_TEST(merge_empty_test,
((test_node_set))
((test_node_set))
((default_generator)(generate_collisions)))
UNORDERED_TEST(merge_empty_test,
((test_node_map))
((test_node_map))
((default_generator)(generate_collisions)))
UNORDERED_TEST(merge_into_empty_test,
((test_node_set_std_alloc))
((default_generator)(generate_collisions)))
UNORDERED_TEST(merge_into_empty_test,
((test_node_map_std_alloc))
((default_generator)(generate_collisions)))
UNORDERED_TEST(merge_into_empty_test,
((test_node_set))
((default_generator)(generate_collisions)))
UNORDERED_TEST(merge_into_empty_test,
((test_node_map))
((default_generator)(generate_collisions)))
UNORDERED_TEST(merge_into_unique_keys_test,
((test_node_set_std_alloc))
((test_node_set_std_alloc))
((0)(1)(2))
((0)(1)(2))
((default_generator)(generate_collisions)))
UNORDERED_TEST(merge_into_unique_keys_test,
((test_node_map_std_alloc))
((test_node_map_std_alloc))
((0)(1)(2))
((0)(1)(2))
((default_generator)(generate_collisions)))
UNORDERED_TEST(merge_into_unique_keys_test,
((test_node_set))
((test_node_set))
((0)(1)(2))
((0)(1)(2))
((default_generator)(generate_collisions)))
UNORDERED_TEST(merge_into_unique_keys_test,
((test_node_map))
((test_node_map))
((0)(1)(2))
((0)(1)(2))
((default_generator)(generate_collisions)))
// clang-format on
#else
boost::unordered_set<int>* int_set;
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,
@@ -330,6 +401,8 @@ UNORDERED_TEST(merge_into_unique_keys_test,
test::equal_to, test::allocator2<test::movable> >* test_multimap;
// clang-format off
UNORDERED_TEST(merge_set, ((int_set)))
UNORDERED_TEST(merge_empty_test,
((test_set_std_alloc)(test_multiset_std_alloc))
((test_set_std_alloc)(test_multiset_std_alloc))
@@ -412,6 +485,6 @@ UNORDERED_TEST(merge_into_equiv_keys_test,
// clang-format on
#endif
}
} // namespace merge_tests
RUN_TESTS()
+55 -5
View File
@@ -1,6 +1,6 @@
// Copyright 2008-2009 Daniel James.
// Copyright 2022 Christian Mazakas.
// Copyright 2022-2023 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)
@@ -408,18 +408,68 @@ namespace move_tests {
test::cxx11_allocator<std::pair<test::object const, test::object>,
test::no_propagate_move> >* test_map_no_prop_move;
boost::unordered_node_map<test::object, test::object, test::hash,
test::equal_to,
std::allocator<std::pair<test::object const, test::object> > >*
test_node_map_std_alloc;
boost::unordered_node_set<test::object, test::hash, test::equal_to,
test::allocator2<test::object> >* test_node_set;
boost::unordered_node_map<test::object, test::object, test::hash,
test::equal_to,
test::allocator1<std::pair<test::object const, test::object> > >*
test_node_map;
boost::unordered_node_set<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::propagate_move> >*
test_node_set_prop_move;
boost::unordered_node_map<test::object, test::object, test::hash,
test::equal_to,
test::cxx11_allocator<std::pair<test::object const, test::object>,
test::propagate_move> >* test_node_map_prop_move;
boost::unordered_node_set<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_move> >*
test_node_set_no_prop_move;
boost::unordered_node_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_node_map_no_prop_move;
// clang-format off
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))(
((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)
(test_node_map_std_alloc)(test_node_set)(test_node_map)
(test_node_set_prop_move)(test_node_map_prop_move)
(test_node_set_no_prop_move)(test_node_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))(
((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)
(test_node_map_std_alloc)(test_node_set)(test_node_map)
(test_node_set_prop_move)(test_node_map_prop_move)
(test_node_set_no_prop_move)(test_node_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))(
((test_set)(test_map)
(test_set_prop_move)(test_map_prop_move)
(test_set_no_prop_move)(test_map_no_prop_move)
(test_node_set)(test_node_map)
(test_node_set_prop_move)(test_node_map_prop_move)
(test_node_set_no_prop_move)(test_node_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))(
((test_set)(test_map)
(test_set_prop_move)(test_map_prop_move)
(test_set_no_prop_move)(test_map_no_prop_move)
(test_node_set)(test_node_map)
(test_node_set_prop_move)(test_node_map_prop_move)
(test_node_set_no_prop_move)(test_node_map_no_prop_move))(
(default_generator)(generate_collisions)(limited_range)))
// clang-format on
#else
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
std::allocator<std::pair<test::object const, test::object> > >*
+214 -34
View File
@@ -1,12 +1,12 @@
// Copyright 2016 Daniel James.
// Copyright 2023 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/helpers.hpp"
#include "../helpers/metafunctions.hpp"
@@ -17,15 +17,19 @@
#include <set>
#include <string>
UNORDERED_AUTO_TEST (example1) {
typedef boost::unordered_map<int, std::string>::insert_return_type
insert_return_type;
template <template <class Key, class T, class Hash = boost::hash<Key>,
class Pred = std::equal_to<Key>,
class Allocator = std::allocator<std::pair<Key const, T> > >
class Map>
static void example1()
{
typedef typename Map<int, std::string>::insert_return_type insert_return_type;
boost::unordered_map<int, std::string> src;
Map<int, std::string> src;
src.emplace(1, "one");
src.emplace(2, "two");
src.emplace(3, "buckle my shoe");
boost::unordered_map<int, std::string> dst;
Map<int, std::string> dst;
dst.emplace(3, "three");
dst.insert(src.extract(src.find(1)));
@@ -42,12 +46,16 @@ UNORDERED_AUTO_TEST (example1) {
BOOST_TEST(r.node.mapped() == "buckle my shoe");
}
UNORDERED_AUTO_TEST (example2) {
boost::unordered_set<int> src;
template <template <class Key, class Hash = boost::hash<Key>,
class Pred = std::equal_to<Key>, class Allocator = std::allocator<Key> >
class Set>
static void example2()
{
Set<int> src;
src.insert(1);
src.insert(3);
src.insert(5);
boost::unordered_set<int> dst;
Set<int> dst;
dst.insert(2);
dst.insert(4);
dst.insert(5);
@@ -57,14 +65,18 @@ UNORDERED_AUTO_TEST (example2) {
// dst == {1, 2, 3, 4, 5}
}
UNORDERED_AUTO_TEST (example3) {
typedef boost::unordered_set<int>::iterator iterator;
template <template <class Key, class Hash = boost::hash<Key>,
class Pred = std::equal_to<Key>, class Allocator = std::allocator<Key> >
class Set>
static void example3()
{
typedef typename Set<int>::iterator iterator;
boost::unordered_set<int> src;
Set<int> src;
src.insert(1);
src.insert(3);
src.insert(5);
boost::unordered_set<int> dst;
Set<int> dst;
dst.insert(2);
dst.insert(4);
dst.insert(5);
@@ -88,16 +100,24 @@ UNORDERED_AUTO_TEST (example3) {
BOOST_TEST(it == dst2.end());
}
UNORDERED_AUTO_TEST (failed_insertion_with_hint) {
template <template <class Key, class T, class Hash = boost::hash<Key>,
class Pred = std::equal_to<Key>,
class Allocator = std::allocator<std::pair<Key const, T> > >
class Map,
template <class Key, class Hash = boost::hash<Key>,
class Pred = std::equal_to<Key>, class Allocator = std::allocator<Key> >
class Set>
static void failed_insertion_with_hint()
{
{
boost::unordered_set<int> src;
boost::unordered_set<int> dst;
Set<int> src;
Set<int> dst;
src.emplace(10);
src.emplace(20);
dst.emplace(10);
dst.emplace(20);
boost::unordered_set<int>::node_type nh = src.extract(10);
typename Set<int>::node_type nh = src.extract(10);
BOOST_TEST(dst.insert(dst.find(10), boost::move(nh)) == dst.find(10));
BOOST_TEST(nh);
@@ -116,14 +136,14 @@ UNORDERED_AUTO_TEST (failed_insertion_with_hint) {
}
{
boost::unordered_map<int, int> src;
boost::unordered_map<int, int> dst;
Map<int, int> src;
Map<int, int> dst;
src.emplace(10, 30);
src.emplace(20, 5);
dst.emplace(10, 20);
dst.emplace(20, 2);
boost::unordered_map<int, int>::node_type nh = src.extract(10);
typename Map<int, int>::node_type nh = src.extract(10);
BOOST_TEST(dst.insert(dst.find(10), boost::move(nh)) == dst.find(10));
BOOST_TEST(nh);
BOOST_TEST(!nh.empty());
@@ -231,20 +251,38 @@ template <typename Container> void node_handle_tests_impl(Container& c)
BOOST_TEST(!n4);
}
UNORDERED_AUTO_TEST (node_handle_tests) {
boost::unordered_set<int> x1;
template <template <class Key, class T, class Hash = boost::hash<Key>,
class Pred = std::equal_to<Key>,
class Allocator = std::allocator<std::pair<Key const, T> > >
class Map,
template <class Key, class Hash = boost::hash<Key>,
class Pred = std::equal_to<Key>, class Allocator = std::allocator<Key> >
class Set>
static void node_handle_tests()
{
Set<int> x1;
x1.emplace(100);
x1.emplace(140);
x1.emplace(-55);
node_handle_tests_impl(x1);
boost::unordered_map<int, std::string> x2;
Map<int, std::string> x2;
x2.emplace(10, "ten");
x2.emplace(-23, "twenty");
x2.emplace(-76, "thirty");
node_handle_tests_impl(x2);
}
#ifdef BOOST_UNORDERED_FOA_TESTS
template <class X> typename X::iterator insert_empty_node(X& x)
{
typedef typename X::node_type node_type;
return x.insert(node_type()).position;
}
#else
template <class Key, class T, class Hash, class KeyEqual, class Allocator>
typename boost::unordered_map<Key, T, Hash, KeyEqual, Allocator>::iterator
insert_empty_node(boost::unordered_map<Key, T, Hash, KeyEqual, Allocator>& c)
@@ -288,8 +326,10 @@ insert_empty_node(boost::unordered_multiset<T, Hash, KeyEqual, Allocator>& c)
return c.insert(node_type());
}
#endif
template <typename Container1, typename Container2>
void insert_node_handle_unique(Container1& c1, Container2& c2)
static void insert_node_handle_unique(Container1& c1, Container2& c2)
{
typedef typename Container1::node_type node_type;
typedef typename Container1::value_type value_type;
@@ -297,8 +337,12 @@ void insert_node_handle_unique(Container1& c1, Container2& c2)
(boost::is_same<node_type, typename Container2::node_type>::value));
typedef typename Container1::iterator iterator1;
typedef typename Container2::iterator iterator2;
typedef typename Container2::insert_return_type insert_return_type2;
Container1 c1_copy(c1);
Container2 c2_copy;
iterator1 r1 = insert_empty_node(c1);
insert_return_type2 r2 = c2.insert(node_type());
BOOST_TEST(r1 == c1.end());
@@ -327,10 +371,28 @@ void insert_node_handle_unique(Container1& c1, Container2& c2)
node_handle_compare(r.node, v);
}
}
while (!c1_copy.empty()) {
value_type v = *c1_copy.begin();
value_type const* v_ptr = boost::to_address(c1_copy.begin());
std::size_t count = c2_copy.count(test::get_key<Container1>(v));
iterator2 pos =
c2_copy.insert(c2_copy.begin(), c1_copy.extract(c1_copy.begin()));
if (!count) {
BOOST_TEST_EQ(c2_copy.count(test::get_key<Container1>(v)), count + 1);
BOOST_TEST(pos != c2.end());
BOOST_TEST(boost::to_address(pos) == v_ptr);
} else {
BOOST_TEST_EQ(c2_copy.count(test::get_key<Container1>(v)), count);
BOOST_TEST(pos != c2_copy.end());
BOOST_TEST(
test::get_key<Container2>(*pos) == test::get_key<Container2>(v));
}
}
}
template <typename Container1, typename Container2>
void insert_node_handle_unique2(Container1& c1, Container2& c2)
static void insert_node_handle_unique2(Container1& c1, Container2& c2)
{
typedef typename Container1::node_type node_type;
typedef typename Container1::value_type value_type;
@@ -362,6 +424,130 @@ void insert_node_handle_unique2(Container1& c1, Container2& c2)
}
}
struct hash_thing
{
std::size_t operator()(int x) const
{
return static_cast<std::size_t>(x * 13 + 5);
}
};
#ifdef BOOST_UNORDERED_FOA_TESTS
UNORDERED_AUTO_TEST (examples) {
example1<boost::unordered_node_map>();
example2<boost::unordered_node_set>();
example3<boost::unordered_node_set>();
failed_insertion_with_hint<boost::unordered_node_map,
boost::unordered_node_set>();
node_handle_tests<boost::unordered_node_map, boost::unordered_node_set>();
}
UNORDERED_AUTO_TEST (insert_node_handle_unique_tests) {
{
boost::unordered_node_set<int> x1;
boost::unordered_node_set<int> x2;
x1.emplace(100);
x1.emplace(140);
x1.emplace(-55);
x2.emplace(140);
insert_node_handle_unique(x1, x2);
BOOST_TEST(x2.size() == 3);
}
{
boost::unordered_node_set<int> x1;
boost::unordered_node_set<int> x2;
x1.emplace(100);
x1.emplace(140);
x1.emplace(-55);
x2.emplace(140);
insert_node_handle_unique(x1, x2);
BOOST_TEST(x2.size() == 3);
}
{
boost::unordered_node_map<int, int, hash_thing> x1;
boost::unordered_node_map<int, int> x2;
x1.emplace(67, 50);
x1.emplace(23, 45);
x1.emplace(18, 19);
x2.emplace(23, 50);
x2.emplace(12, 49);
insert_node_handle_unique(x1, x2);
BOOST_TEST(x2.size() == 4);
}
{
boost::unordered_node_map<int, int, hash_thing> x1;
boost::unordered_node_map<int, int> x2;
x1.emplace(67, 50);
x1.emplace(23, 45);
x1.emplace(18, 19);
x2.emplace(23, 50);
x2.emplace(12, 49);
insert_node_handle_unique(x1, x2);
BOOST_TEST(x2.size() == 4);
}
}
UNORDERED_AUTO_TEST (insert_node_handle_unique_tests2) {
{
boost::unordered_node_set<int> x1;
boost::unordered_node_set<int> x2;
x1.emplace(100);
x1.emplace(140);
x1.emplace(-55);
x2.emplace(140);
insert_node_handle_unique2(x1, x2);
BOOST_TEST(x2.size() == 3);
}
{
boost::unordered_node_set<int> x1;
boost::unordered_node_set<int> x2;
x1.emplace(100);
x1.emplace(140);
x1.emplace(-55);
x2.emplace(140);
insert_node_handle_unique2(x1, x2);
BOOST_TEST(x2.size() == 3);
}
{
boost::unordered_node_map<int, int, hash_thing> x1;
boost::unordered_node_map<int, int> x2;
x1.emplace(67, 50);
x1.emplace(23, 45);
x1.emplace(18, 19);
x2.emplace(23, 50);
x2.emplace(12, 49);
insert_node_handle_unique2(x1, x2);
BOOST_TEST(x2.size() == 4);
}
{
boost::unordered_node_map<int, int, hash_thing> x1;
boost::unordered_node_map<int, int> x2;
x1.emplace(67, 50);
x1.emplace(23, 45);
x1.emplace(18, 19);
x2.emplace(23, 50);
x2.emplace(12, 49);
insert_node_handle_unique2(x1, x2);
BOOST_TEST(x2.size() == 4);
}
}
#else
UNORDERED_AUTO_TEST (examples) {
example1<boost::unordered_map>();
example2<boost::unordered_set>();
example3<boost::unordered_set>();
failed_insertion_with_hint<boost::unordered_map, boost::unordered_set>();
node_handle_tests<boost::unordered_map, boost::unordered_set>();
}
template <typename Container1, typename Container2>
void insert_node_handle_equiv(Container1& c1, Container2& c2)
{
@@ -389,14 +575,6 @@ void insert_node_handle_equiv(Container1& c1, Container2& c2)
}
}
struct hash_thing
{
std::size_t operator()(int x) const
{
return static_cast<std::size_t>(x * 13 + 5);
}
};
UNORDERED_AUTO_TEST (insert_node_handle_unique_tests) {
{
boost::unordered_set<int> x1;
@@ -547,4 +725,6 @@ UNORDERED_AUTO_TEST (insert_node_handle_unique_tests2) {
}
}
#endif
RUN_TESTS()
+61 -32
View File
@@ -1,13 +1,13 @@
// Copyright 2013 Daniel James.
// Copyright 2022 Christian Mazakas.
// Copyright 2022-2023 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/unordered.hpp"
#include "../helpers/test.hpp"
#include "../helpers/fwd.hpp"
#include "../helpers/test.hpp"
#if defined(BOOST_MSVC)
#pragma warning(push)
@@ -203,6 +203,10 @@ namespace noexcept_tests {
boost::unordered_flat_set<int> >::value));
BOOST_TEST((boost::is_nothrow_move_constructible<
boost::unordered_flat_map<int, int> >::value));
BOOST_TEST((boost::is_nothrow_move_constructible<
boost::unordered_node_set<int> >::value));
BOOST_TEST((boost::is_nothrow_move_constructible<
boost::unordered_node_map<int, int> >::value));
#else
BOOST_TEST((boost::is_nothrow_move_constructible<
boost::unordered_set<int> >::value));
@@ -222,6 +226,13 @@ namespace noexcept_tests {
BOOST_TEST(
(!boost::is_nothrow_move_constructible<boost::unordered_flat_set<int,
boost::hash<int>, equal_to_possible_exception> >::value));
BOOST_TEST(
(!boost::is_nothrow_move_constructible<
boost::unordered_node_set<int, hash_possible_exception> >::value));
BOOST_TEST(
(!boost::is_nothrow_move_constructible<boost::unordered_node_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));
@@ -231,31 +242,22 @@ namespace noexcept_tests {
#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
template <class X> static void test_nothrow_move_when_noexcept(X*)
{
if (have_is_nothrow_move) {
BOOST_TEST(boost::is_nothrow_move_constructible<throwing_set>::value);
BOOST_TEST(boost::is_nothrow_move_constructible<X>::value);
}
throwing_test_exception = false;
throwing_set x1;
X x1;
x1.insert(10);
x1.insert(50);
try {
throwing_test_exception = true;
throwing_set x2 = boost::move(x1);
X x2 = boost::move(x1);
BOOST_TEST(x2.size() == 2);
BOOST_TEST(*x2.begin() == 10 || *x2.begin() == 50);
BOOST_TEST(have_is_nothrow_move);
@@ -327,24 +329,16 @@ 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
template <class X> static void test_nothrow_swap_when_noexcept(X*)
{
if (have_is_nothrow_swap) {
BOOST_TEST(boost::is_nothrow_swappable<throwing_set>::value);
BOOST_TEST(boost::is_nothrow_swappable<X>::value);
}
throwing_test_exception = false;
throwing_set x1;
throwing_set x2;
X x1;
X x2;
x1.insert(10);
x1.insert(50);
for (int i = 0; i < 100; ++i) {
@@ -365,7 +359,7 @@ namespace noexcept_tests {
throwing_test_exception = false;
}
}
} // namespace noexcept_tests
#if defined(BOOST_MSVC)
#pragma warning(pop)
@@ -401,6 +395,7 @@ template <class T> class allocator2
{
BOOST_COPYABLE_AND_MOVABLE(allocator2)
allocator2 operator=(BOOST_COPY_ASSIGN_REF(allocator2));
public:
typedef T value_type;
typedef boost::true_type propagate_on_container_move_assignment;
@@ -431,21 +426,53 @@ UNORDERED_AUTO_TEST (prelim_allocator_checks) {
BOOST_TEST(boost::allocator_is_always_equal<allocator2<int> >::type::value);
BOOST_TEST(boost::allocator_propagate_on_container_move_assignment<
allocator2<int> >::type::value);
allocator2<int> >::type::value);
}
using test::default_generator;
#ifdef BOOST_UNORDERED_FOA_TESTS
boost::unordered_flat_set<int, noexcept_tests::hash_nothrow_move_construct,
noexcept_tests::equal_to_nothrow_move_construct>* throwing_set;
boost::unordered_flat_set<int, noexcept_tests::hash_nothrow_swap,
noexcept_tests::equal_to_nothrow_swap>* throwing_set2;
boost::unordered_flat_set<int, noexcept_tests::hash_nothrow_swap,
noexcept_tests::equal_to_nothrow_swap, allocator1<int> >* throwing_set_alloc1;
boost::unordered_flat_set<int, noexcept_tests::hash_nothrow_swap,
noexcept_tests::equal_to_nothrow_swap, allocator2<int> >* throwing_set_alloc2;
boost::unordered_node_set<int, noexcept_tests::hash_nothrow_move_construct,
noexcept_tests::equal_to_nothrow_move_construct>* throwing_node_set;
boost::unordered_node_set<int, noexcept_tests::hash_nothrow_swap,
noexcept_tests::equal_to_nothrow_swap>* throwing_node_set2;
boost::unordered_node_set<int, noexcept_tests::hash_nothrow_swap,
noexcept_tests::equal_to_nothrow_swap, allocator1<int> >*
throwing_node_set_alloc1;
boost::unordered_node_set<int, noexcept_tests::hash_nothrow_swap,
noexcept_tests::equal_to_nothrow_swap, allocator2<int> >*
throwing_node_set_alloc2;
// clang-format off
UNORDERED_TEST(
test_nothrow_move_when_noexcept, ((throwing_set)(throwing_node_set)))
UNORDERED_TEST(
test_nothrow_swap_when_noexcept, ((throwing_set2)(throwing_node_set2)))
UNORDERED_TEST(test_nothrow_move_assign_when_noexcept,
((throwing_set_alloc1)(throwing_set_alloc2))((default_generator)))
((throwing_set_alloc1)(throwing_set_alloc2)
(throwing_node_set_alloc1)(throwing_node_set_alloc2))(
(default_generator)))
// clang-format on
#else
boost::unordered_set<int, noexcept_tests::hash_nothrow_move_construct,
noexcept_tests::equal_to_nothrow_move_construct>* throwing_set;
boost::unordered_set<int, noexcept_tests::hash_nothrow_swap,
noexcept_tests::equal_to_nothrow_swap>* throwing_set2;
boost::unordered_set<int, noexcept_tests::hash_nothrow_move_assign,
noexcept_tests::equal_to_nothrow_move_assign, allocator1<int> >*
throwing_set_alloc1;
@@ -454,6 +481,8 @@ boost::unordered_set<int, noexcept_tests::hash_nothrow_move_assign,
noexcept_tests::equal_to_nothrow_move_assign, allocator2<int> >*
throwing_set_alloc2;
UNORDERED_TEST(test_nothrow_move_when_noexcept, ((throwing_set)))
UNORDERED_TEST(test_nothrow_swap_when_noexcept, ((throwing_set2)))
UNORDERED_TEST(test_nothrow_move_assign_when_noexcept,
((throwing_set_alloc1)(throwing_set_alloc2))((default_generator)))
#endif
+37 -2
View File
@@ -1,5 +1,5 @@
// Copyright (C) 2022 Christian Mazakas
// Copyright (C) 2022-2023 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)
@@ -335,12 +335,14 @@ namespace move_tests {
static_cast<typename T::size_type>(std::distance(y.begin(), y.end())));
}
#ifndef BOOST_UNORDERED_FOA_TESTS
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())));
}
#endif
template <class T> static void merge(T& y, test::random_values<T> const& v)
{
@@ -375,6 +377,7 @@ namespace move_tests {
static_cast<typename T::size_type>(std::distance(y.begin(), y.end())));
}
#ifndef BOOST_UNORDERED_FOA_TESTS
template <class T> static void buckets(T& y, test::random_values<T> const& v)
{
(void)y.begin(0);
@@ -384,6 +387,7 @@ namespace move_tests {
(void)y.bucket_size(0);
(void)y.bucket(get_key(*v.begin()));
}
#endif
template <class T>
static void double_move_construct(T& y, test::random_values<T> const&)
@@ -607,9 +611,38 @@ namespace move_tests {
test::cxx11_allocator<std::pair<test::object const, test::object>,
test::no_propagate_move> >* test_map_no_prop_move;
boost::unordered_node_set<test::object, test::hash, test::equal_to,
test::allocator2<test::object> >* test_node_set;
boost::unordered_node_map<test::object, test::object, test::hash,
test::equal_to,
test::allocator1<std::pair<test::object const, test::object> > >*
test_node_map;
boost::unordered_node_set<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::propagate_move> >*
test_node_set_prop_move;
boost::unordered_node_map<test::object, test::object, test::hash,
test::equal_to,
test::cxx11_allocator<std::pair<test::object const, test::object>,
test::propagate_move> >* test_node_map_prop_move;
boost::unordered_node_set<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_move> >*
test_node_set_no_prop_move;
boost::unordered_node_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_node_map_no_prop_move;
// clang-format off
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))(
((test_set)(test_map)(test_set_prop_move)(test_map_prop_move)
(test_set_no_prop_move)(test_map_no_prop_move)
(test_node_set)(test_node_map)
(test_node_set_prop_move)(test_node_map_prop_move)
(test_node_set_no_prop_move)(test_node_map_no_prop_move))(
(default_generator)(generate_collisions)(limited_range)))
// clang-format on
#else
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
std::allocator<std::pair<test::object const, test::object> > >*
@@ -654,12 +687,14 @@ namespace move_tests {
test::cxx11_allocator<std::pair<test::object const, test::object>,
test::no_propagate_move> >* test_multimap_no_prop_move;
// clang-format off
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)))
// clang-format on
#endif
}
+92 -21
View File
@@ -1,6 +1,6 @@
// Copyright 2006-2009 Daniel James.
// Copyright 2022 Christian Mazakas.
// Copyright 2022-2023 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)
@@ -437,6 +437,35 @@ namespace rehash_tests {
tracker.compare(x);
}
template <class X>
void rehash_node_stability(X*, test::random_generator generator)
{
typedef typename X::value_type value_type;
std::set<value_type const*> elements;
test::random_values<X> v(1000, generator);
test::ordered<X> tracker;
tracker.insert_range(v.begin(), v.end());
X x(v.begin(), v.end());
typedef typename X::iterator iterator;
for (iterator pos = x.begin(); pos != x.end(); ++pos) {
elements.insert(boost::addressof(*pos));
}
x.rehash(2 * x.bucket_count());
for (iterator pos = x.begin(); pos != x.end(); ++pos) {
if (!BOOST_TEST(
elements.find(boost::addressof(*pos)) != elements.end())) {
break;
}
}
tracker.compare(x);
}
template <class X> void rehash_test1(X*, test::random_generator generator)
{
test::random_values<X> v(1000, generator);
@@ -581,32 +610,67 @@ namespace rehash_tests {
monotonic_allocator<std::pair<test::object const, test::object> > >*
test_map_monotonic;
UNORDERED_TEST(rehash_empty_test1, ((int_set_ptr)(test_map_ptr)))
boost::unordered_node_set<int>* int_node_set_ptr;
boost::unordered_node_map<test::movable, test::movable, test::hash,
test::equal_to, test::allocator2<test::movable> >* test_node_map_ptr;
boost::unordered_node_set<test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_node_set_tracking;
boost::unordered_node_map<test::object, test::object, test::hash,
test::equal_to,
test::allocator1<std::pair<test::object const, test::object> > >*
test_node_map_tracking;
boost::unordered_node_set<test::object, test::hash, test::equal_to,
monotonic_allocator<test::object> >* test_node_set_monotonic;
boost::unordered_node_map<test::object, test::object, test::hash,
test::equal_to,
monotonic_allocator<std::pair<test::object const, test::object> > >*
test_node_map_monotonic;
// clang-format off
UNORDERED_TEST(rehash_empty_test1,
((int_set_ptr)(test_map_ptr)
(int_node_set_ptr)(test_node_map_ptr)))
UNORDERED_TEST(rehash_empty_test2,
((int_set_ptr)(test_map_ptr))(
((int_set_ptr)(test_map_ptr)
(int_node_set_ptr)(test_node_map_ptr))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(rehash_empty_test3,
((int_set_ptr)(test_map_ptr))(
((int_set_ptr)(test_map_ptr)
(int_node_set_ptr)(test_node_map_ptr))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(rehash_test1,
((int_set_ptr)(test_map_ptr)
(int_node_set_ptr)(test_node_map_ptr))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(reserve_empty_test1,
((int_set_ptr)(test_map_ptr)(int_node_set_ptr)(test_node_map_ptr)))
UNORDERED_TEST(reserve_empty_test2,
((int_set_ptr)(test_map_ptr)(int_node_set_ptr)(test_node_map_ptr)))
UNORDERED_TEST(reserve_test1,
((int_set_ptr)(test_map_ptr)(int_node_set_ptr)(test_node_map_ptr))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(reserve_test2,
((int_set_ptr)(test_map_ptr)(int_node_set_ptr)(test_node_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))(
((test_set_tracking)(test_map_tracking)
(test_node_set_tracking)(test_node_map_tracking))(
(default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(
rehash_nonempty_tracking, ((test_set_tracking)(test_map_tracking))(
(default_generator)(limited_range)))
UNORDERED_TEST(rehash_stability, ((test_set_monotonic)(test_map_monotonic))(
(default_generator)(limited_range)))
UNORDERED_TEST(rehash_nonempty_tracking,
((test_set_tracking)(test_map_tracking)
(test_node_set_tracking)(test_node_map_tracking))(
(default_generator)(limited_range)))
UNORDERED_TEST(rehash_stability,
((test_set_monotonic)(test_map_monotonic)
(test_node_set_monotonic)(test_node_map_monotonic))(
(default_generator)(limited_range)))
UNORDERED_TEST(rehash_node_stability,
((int_node_set_ptr)(test_node_map_ptr)
(test_node_set_tracking)(test_node_map_tracking))(
(default_generator)(generate_collisions)(limited_range)))
// clang-format on
#else
boost::unordered_set<int>* int_set_ptr;
boost::unordered_multiset<test::object, test::hash, test::equal_to,
@@ -639,6 +703,7 @@ namespace rehash_tests {
monotonic_allocator<std::pair<test::object const, test::object> > >*
test_multimap_monotonic;
// clang-format off
UNORDERED_TEST(rehash_empty_test1,
((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr)))
UNORDERED_TEST(rehash_empty_test2,
@@ -669,6 +734,12 @@ namespace rehash_tests {
UNORDERED_TEST(rehash_stability,
((test_set_monotonic)(test_multiset_monotonic)(test_map_monotonic)(test_multimap_monotonic))(
(default_generator)(limited_range)))
UNORDERED_TEST(rehash_node_stability,
((int_set_ptr)(test_map_ptr)(test_set_tracking)(test_map_tracking)
(test_multiset_ptr)(int_multimap_ptr)
(test_multiset_tracking)(test_multimap_tracking))(
(default_generator)(generate_collisions)(limited_range)))
// clang-format on
#endif
} // namespace rehash_tests
+83 -89
View File
@@ -1,4 +1,4 @@
// Copyright 2021-2022 Christian Mazakas.
// Copyright 2021-2023 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)
@@ -45,7 +45,8 @@ template <typename T> struct A
template <class T> int A<T>::count = 0;
template <class UnorderedContainer> void bucket_count_constructor()
template <class UnorderedContainer>
void bucket_count_constructor(UnorderedContainer*)
{
BOOST_TEST_EQ(num_allocations, 0u);
BOOST_TEST_EQ(total_allocation, 0u);
@@ -64,7 +65,8 @@ template <class UnorderedContainer> void bucket_count_constructor()
num_allocations = 0;
}
template <class UnorderedContainer> void range_bucket_constructor()
template <class UnorderedContainer>
void range_bucket_constructor(UnorderedContainer*)
{
BOOST_TEST_EQ(num_allocations, 0u);
BOOST_TEST_EQ(total_allocation, 0u);
@@ -85,7 +87,7 @@ template <class UnorderedContainer> void range_bucket_constructor()
num_allocations = 0;
}
template <class UnorderedContainer> void reserve_tests()
template <class UnorderedContainer> void reserve_tests(UnorderedContainer*)
{
BOOST_TEST_EQ(num_allocations, 0u);
BOOST_TEST_EQ(total_allocation, 0u);
@@ -124,7 +126,7 @@ template <class UnorderedContainer> void reserve_tests()
num_allocations = 0;
}
template <class UnorderedContainer> void rehash_tests()
template <class UnorderedContainer> void rehash_tests(UnorderedContainer*)
{
BOOST_TEST_EQ(num_allocations, 0u);
BOOST_TEST_EQ(total_allocation, 0u);
@@ -172,7 +174,7 @@ template <class UnorderedContainer> void rehash_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);
((prev_count + count) / 14 + 2) * 16);
#else
std::size_t const estimated_bucket_group_size =
3 * sizeof(void*) + sizeof(std::size_t);
@@ -191,89 +193,81 @@ template <class UnorderedContainer> void rehash_tests()
num_allocations = 0;
}
UNORDERED_AUTO_TEST (unordered_set_reserve) {
{
// prove Allocator invariants
// from cppref:
// Given:
// * A, an Allocator type for type T
// * B, the corresponding Allocator type for some cv-unqualified object type
// U (as obtained by rebinding A)
//
// Expression:
// A a(b)
//
// Return Type:
// Constructs `a` such that `B(a)==b` and `A(b)==a`.
// (Note: This implies that all allocators related by rebind maintain each
// other's resources, such as memory pools.)
//
//
typedef boost::allocator_rebind<A<int>, float>::type alloc_rebound;
alloc_rebound b;
A<int> a(b);
BOOST_ASSERT(alloc_rebound(a) == b);
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;
typedef boost::unordered_multiset<int, boost::hash<int>, std::equal_to<int>,
A<int> >
unordered_multiset;
typedef boost::unordered_map<int, int, boost::hash<int>, std::equal_to<int>,
A<std::pair<int const, int> > >
unordered_map;
typedef boost::unordered_multimap<int, int, boost::hash<int>,
std::equal_to<int>, A<std::pair<int const, int> > >
unordered_multimap;
bucket_count_constructor<unordered_set>();
bucket_count_constructor<unordered_map>();
bucket_count_constructor<unordered_multiset>();
bucket_count_constructor<unordered_multimap>();
range_bucket_constructor<unordered_set>();
range_bucket_constructor<unordered_map>();
range_bucket_constructor<unordered_multiset>();
range_bucket_constructor<unordered_multimap>();
reserve_tests<unordered_set>();
reserve_tests<unordered_map>();
reserve_tests<unordered_multiset>();
reserve_tests<unordered_multimap>();
rehash_tests<unordered_set>();
rehash_tests<unordered_map>();
rehash_tests<unordered_multiset>();
rehash_tests<unordered_multimap>();
#endif
UNORDERED_AUTO_TEST (allocator_check) {
// prove Allocator invariants
// from cppref:
// Given:
// * A, an Allocator type for type T
// * B, the corresponding Allocator type for some cv-unqualified object type
// U (as obtained by rebinding A)
//
// Expression:
// A a(b)
//
// Return Type:
// Constructs `a` such that `B(a)==b` and `A(b)==a`.
// (Note: This implies that all allocators related by rebind maintain each
// other's resources, such as memory pools.)
//
//
typedef boost::allocator_rebind<A<int>, float>::type alloc_rebound;
alloc_rebound b;
A<int> a(b);
BOOST_ASSERT(alloc_rebound(a) == b);
BOOST_ASSERT(A<int>(b) == a);
}
#ifdef BOOST_UNORDERED_FOA_TESTS
static boost::unordered_flat_set<int*, boost::hash<int*>, std::equal_to<int*>,
A<int*> >* test_set;
static boost::unordered_flat_map<int*, int*, boost::hash<int*>,
std::equal_to<int*>, A<std::pair<int const*, int*> > >* test_map;
static boost::unordered_node_set<int*, boost::hash<int*>, std::equal_to<int*>,
A<int*> >* test_node_set;
static boost::unordered_node_map<int*, int*, boost::hash<int*>,
std::equal_to<int*>, A<std::pair<int const*, int*> > >* test_node_map;
// clang-format off
UNORDERED_TEST(bucket_count_constructor,
((test_set)(test_map)(test_node_set)(test_node_map)))
UNORDERED_TEST(range_bucket_constructor,
((test_set)(test_map)(test_node_set)(test_node_map)))
UNORDERED_TEST(reserve_tests,
((test_set)(test_map)(test_node_set)(test_node_map)))
UNORDERED_TEST(rehash_tests,
((test_set)(test_map)(test_node_set)(test_node_map)))
// clang-format on
#else
static boost::unordered_set<int, boost::hash<int>, std::equal_to<int>, A<int> >*
test_set;
static boost::unordered_multiset<int, boost::hash<int>, std::equal_to<int>,
A<int> >* test_multiset;
static boost::unordered_map<int, int, boost::hash<int>, std::equal_to<int>,
A<std::pair<int const, int> > >* test_map;
static boost::unordered_multimap<int, int, boost::hash<int>, std::equal_to<int>,
A<std::pair<int const, int> > >* test_multimap;
// clang-format off
UNORDERED_TEST(bucket_count_constructor,
((test_set)(test_map)(test_multiset)(test_multimap)))
UNORDERED_TEST(range_bucket_constructor,
((test_set)(test_map)(test_multiset)(test_multimap)))
UNORDERED_TEST(reserve_tests,
((test_set)(test_map)(test_multiset)(test_multimap)))
UNORDERED_TEST(rehash_tests,
((test_set)(test_map)(test_multiset)(test_multimap)))
// clang-format on
#endif
RUN_TESTS()

Some files were not shown because too many files have changed in this diff Show More