updated is_avalanching trait protocol

This commit is contained in:
joaquintides 2024-05-29 19:51:32 +02:00
parent 6745d67d62
commit f77bdb9b67
8 changed files with 74 additions and 18 deletions

View File

@ -1,5 +1,5 @@
// Copyright 2021 Peter Dimov.
// Copyright 2023 Joaquin M Lopez Munoz.
// Copyright 2023-2024 Joaquin M Lopez Munoz.
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
@ -25,6 +25,7 @@
#include <iostream>
#include <iomanip>
#include <chrono>
#include <type_traits>
using namespace std::chrono_literals;
@ -341,7 +342,7 @@ template<> struct fnv1a_hash_impl<64>
struct fnv1a_hash: fnv1a_hash_impl< std::numeric_limits<std::size_t>::digits >
{
using is_avalanching = void;
using is_avalanching = std::true_type;
};
template<class K, class V> using std_unordered_map_fnv1a =

View File

@ -18,6 +18,7 @@
#include <iostream>
#include <iomanip>
#include <chrono>
#include <type_traits>
using namespace std::chrono_literals;
@ -262,7 +263,7 @@ template<> struct fnv1a_hash_impl<64>
struct fnv1a_hash: fnv1a_hash_impl< std::numeric_limits<std::size_t>::digits >
{
using is_avalanching = void;
using is_avalanching = std::true_type;
};
template<class K, class V> using boost_unordered_flat_map_fnv1a =
@ -272,7 +273,7 @@ template<class K, class V> using boost_unordered_flat_map_fnv1a =
struct slightly_bad_hash
{
using is_avalanching = void;
using is_avalanching = std::true_type;
std::size_t operator()( std::string const& s ) const
{
@ -295,7 +296,7 @@ template<class K, class V> using boost_unordered_flat_map_slightly_bad_hash =
struct bad_hash
{
using is_avalanching = void;
using is_avalanching = std::true_type;
std::size_t operator()( std::string const& s ) const
{

View File

@ -1,5 +1,5 @@
// Copyright 2021 Peter Dimov.
// Copyright 2023 Joaquin M Lopez Munoz.
// Copyright 2023-2024 Joaquin M Lopez Munoz.
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
@ -26,6 +26,7 @@
#include <iostream>
#include <iomanip>
#include <chrono>
#include <type_traits>
using namespace std::chrono_literals;
@ -342,7 +343,7 @@ template<> struct fnv1a_hash_impl<64>
struct fnv1a_hash: fnv1a_hash_impl< std::numeric_limits<std::size_t>::digits >
{
using is_avalanching = void;
using is_avalanching = std::true_type;
};
template<class K, class V> using std_unordered_map_fnv1a =

View File

@ -10,6 +10,7 @@
* Added container `pmr` aliases when header `<memory_resource>` is available. The alias `boost::unordered::pmr::[container]` refers to `boost::unordered::[container]` with a `std::pmr::polymorphic_allocator` allocator type.
* Equipped open-addressing and concurrent containers to internally calculate and provide statistical metrics affected by the quality of the hash function. This functionality is enabled by the global macro `BOOST_UNORDERED_ENABLE_STATS`.
* Avalanching hash functions must now be marked via an `is_avalanching` typedef with an embedded `value` constant set to `true` (typically, defining `is_avalanching` as `std::true_type`). `using is_avalanching = void` is deprecated but allowed for backwards compatibility.
== Release 1.85.0

View File

@ -33,7 +33,7 @@ follows:
----
struct my_string_hash_function
{
using is_avalanching = void; // instruct Boost.Unordered to not use post-mixing
using is_avalanching = std::true_type; // instruct Boost.Unordered to not use post-mixing
std::size_t operator()(const std::string& x) const
{

View File

@ -32,9 +32,14 @@ large changes in the returned hash code &#8212;ideally, flipping one bit in the
the input value results in each bit of the hash code flipping with probability 50%. Approaching
this property is critical for the proper behavior of open-addressing hash containers.
`hash_is_avalanching<Hash>::value` is `true` if `Hash::is_avalanching` is a valid type,
and `false` otherwise.
Users can then declare a hash function `Hash` as avalanching either by embedding an `is_avalanching` typedef
`hash_is_avalanching<Hash>::value` is:
* `false` if `Hash::is_avalanching` is not present,
* `Hash::is_avalanching::value` if this is present and convertible at compile time to a `bool`,
* `true` if `Hash::is_avalanching` is `void` (this usage is deprecated).
The behavior is undefined if none of the three cases above is met.
Users can then declare a hash function `Hash` as avalanching either by embedding an appropriate `is_avalanching` typedef
into the definition of `Hash`, or directly by specializing `hash_is_avalanching<Hash>` to a class with
an embedded compile-time constant `value` set to `true`.

View File

@ -1,6 +1,6 @@
/* Hash function characterization.
*
* Copyright 2022 Joaquin M Lopez Munoz.
* Copyright 2022-2024 Joaquin M Lopez Munoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
@ -19,12 +19,28 @@ namespace unordered{
namespace detail{
template<typename Hash,typename=void>
struct hash_is_avalanching_impl: std::false_type{};
struct hash_is_avalanching_impl:std::false_type{};
template<typename IsAvalanching>
struct avalanching_value
{
static constexpr bool value=IsAvalanching::value;
};
/* may be explicitly marked as BOOST_DEPRECATED in the future */
template<> struct avalanching_value<void>
{
static constexpr bool value=true;
};
template<typename Hash>
struct hash_is_avalanching_impl<Hash,
boost::unordered::detail::void_t<typename Hash::is_avalanching> >:
std::true_type{};
struct hash_is_avalanching_impl<
Hash,
boost::unordered::detail::void_t<typename Hash::is_avalanching>
>:std::integral_constant<
bool,
avalanching_value<typename Hash::is_avalanching>::value
>{};
} /* namespace detail */
@ -32,8 +48,12 @@ struct hash_is_avalanching_impl<Hash,
* when actual characterization differs from default.
*/
/* hash_is_avalanching<Hash>::value is true when the type Hash::is_avalanching
* is present, false otherwise.
/* hash_is_avalanching<Hash>::value is:
* - false if Hash::is_avalanching is not present.
* - Hash::is_avalanching::value if this is present and constexpr-convertible
* to a bool.
* - true if Hash::is_avalanching is void (deprecated).
* UB otherwise.
*/
template<typename Hash>
struct hash_is_avalanching: detail::hash_is_avalanching_impl<Hash>::type{};

View File

@ -1,4 +1,5 @@
// Copyright 2022 Peter Dimov
// Copyright 2024 Joaquin M Lopez Munoz
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
@ -26,6 +27,7 @@ namespace unordered
#include <boost/unordered/hash_traits.hpp>
#include <boost/core/lightweight_test_trait.hpp>
#include <type_traits>
struct X1
{
@ -36,6 +38,27 @@ struct X2
typedef void is_avalanching;
};
struct X4
{
using is_avalanching = std::false_type;
};
struct X5
{
using is_avalanching = std::true_type;
};
struct X6
{
using is_avalanching = boost::false_type;
};
struct X7
{
using is_avalanching = boost::true_type;
};
int main()
{
using boost::unordered::hash_is_avalanching;
@ -43,6 +66,10 @@ int main()
BOOST_TEST_TRAIT_FALSE((hash_is_avalanching<X1>));
BOOST_TEST_TRAIT_TRUE((hash_is_avalanching<X2>));
BOOST_TEST_TRAIT_TRUE((hash_is_avalanching<X3>));
BOOST_TEST_TRAIT_FALSE((hash_is_avalanching<X4>));
BOOST_TEST_TRAIT_TRUE((hash_is_avalanching<X5>));
BOOST_TEST_TRAIT_FALSE((hash_is_avalanching<X6>));
BOOST_TEST_TRAIT_TRUE((hash_is_avalanching<X7>));
return boost::report_errors();
}