Compare commits
110 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e8af8dcc7d | |||
| ef791cbafd | |||
| b49fa571fb | |||
| 1bf193b8fc | |||
| 7faec20f26 | |||
| ced8b45add | |||
| 15c9bc40f7 | |||
| 9aedb95296 | |||
| e56cb4418c | |||
| 1ae21c6d1a | |||
| 82acad3794 | |||
| c50461528c | |||
| bd08e49255 | |||
| dbba3cec7b | |||
| 6c5b5b3186 | |||
| 47dd02a4b3 | |||
| 8429d1a6aa | |||
| 86d3f9f632 | |||
| 48e92afd92 | |||
| 5a5c31de35 | |||
| 088941dc7b | |||
| 5f6f1691e5 | |||
| 45d6c07be6 | |||
| 5c63cd2bdb | |||
| 86318c1e88 | |||
| 0ff1fa0f6e | |||
| d90bf0c438 | |||
| dc63438e22 | |||
| 0a3ac26f00 | |||
| c64ed1caa3 | |||
| efc33b18be | |||
| c189d8d5e8 | |||
| 886227db3b | |||
| 719eb90d03 | |||
| fadb686bc5 | |||
| aebefaef0d | |||
| 63a564e8ff | |||
| 16c1593368 | |||
| 53580a3070 | |||
| d26aeed68f | |||
| 73eefd2b5d | |||
| 3df600d069 | |||
| a1adacdfe2 | |||
| f405fa9118 | |||
| 7b5d6e7c29 | |||
| 7d0ba7178e | |||
| df5e2c3aca | |||
| 343e344582 | |||
| 34ed463bea | |||
| 5986f75d16 | |||
| b08810c0c4 | |||
| 7c608ae7bc | |||
| d51cee35d5 | |||
| d0289b4c7b | |||
| bc7ba9cb3b | |||
| 6b10c8a4d3 | |||
| b9805c7309 | |||
| 844460fd22 | |||
| a600278d27 | |||
| 4398ffe8c9 | |||
| eed1eeedeb | |||
| 8c0c230f78 | |||
| e96ec1e79a | |||
| be7dd51fab | |||
| 4dec95840b | |||
| d44fb36581 | |||
| 9d3bbe27db | |||
| 13ed4afc95 | |||
| b3f54e74a7 | |||
| d6374e2718 | |||
| 74156b6b06 | |||
| 965048d3e6 | |||
| 36dfe6b98b | |||
| e4e89bdbde | |||
| 85a9d8d81d | |||
| b21ad13bbb | |||
| f0d10308e3 | |||
| f240e587cb | |||
| 2a7dc9e40e | |||
| 99b8d0063b | |||
| c6aff9278a | |||
| 129497133e | |||
| eaa9ff0cec | |||
| fa735864a3 | |||
| 0ce180e19b | |||
| e578b7eee3 | |||
| 1844695b0c | |||
| 54b9adbdbc | |||
| 8b71656cd7 | |||
| a858ef5688 | |||
| 18395c8d21 | |||
| e68ec5c9a9 | |||
| d3b264345d | |||
| f1e1733c06 | |||
| 66ffbdb881 | |||
| f7f5466ed2 | |||
| 83410fcabe | |||
| 1ee91d494d | |||
| e8fe550d6c | |||
| 5b0fe7f655 | |||
| ba439437bf | |||
| aa6eef135e | |||
| 1dd085daaa | |||
| 2a8f50bcb7 | |||
| 866c58a879 | |||
| c9a75a56c2 | |||
| e1861aa3d9 | |||
| 242c7cb93a | |||
| 0597463902 | |||
| 14d80725eb |
@@ -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' };
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 46 KiB |
|
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 45 KiB |
|
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 46 KiB |
|
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 51 KiB |
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 46 KiB |
|
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 56 KiB |
|
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 51 KiB |
|
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 54 KiB |
|
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 45 KiB |
|
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 53 KiB |
|
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 52 KiB |
|
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 46 KiB |
|
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 56 KiB |
|
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 52 KiB |
|
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 52 KiB |
|
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 48 KiB |
|
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 55 KiB |
|
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 46 KiB |
|
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 52 KiB |
|
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 51 KiB |
|
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 52 KiB |
|
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 47 KiB |
|
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 51 KiB |
|
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 45 KiB |
|
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 51 KiB |
@@ -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^].
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
//-
|
||||
|
||||
@@ -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ín M López Muñoz
|
||||
Copyright (C) 2022-2023 Joaquín M López Muñ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)
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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^∕https://en.wikipedia.org/wiki/Golden_ratio[_φ_],
|
||||
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
|
||||
—this includes elements being ordered in exactly the same way for the same sequence of
|
||||
|
||||
@@ -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[]
|
||||
|
||||
@@ -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
|
||||
@@ -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,
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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 ;
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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());
|
||||
|
||||
|
||||
@@ -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> >();
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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()
|
||||
{
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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> > >*
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||