Feature/hash_is_avalanching (#40)

* added hash_is_avalanching

* launched CI after enabling GHA

* moved 1.89 entry from Change Log to Recent Changes

* segregated some tests into hash_is_avalanching_test3.cpp and gotten rid of Unordered dependency

* removed unneeded include

* stopped using external std::hash for testing

* typo

* removed left over include

* typo

* moved hash_is_avalanching from boost::container_hash to boost

* fixed specializations of boost::hash_is_avalanching
This commit is contained in:
joaquintides
2025-05-28 11:05:10 +02:00
committed by GitHub
parent d8f1075080
commit 0a000167b7
10 changed files with 172 additions and 23 deletions

View File

@@ -8,6 +8,10 @@ https://www.boost.org/LICENSE_1_0.txt
= Recent Changes = Recent Changes
:idprefix: recent_ :idprefix: recent_
== Boost 1.89.0
* Added the `hash_is_avalanching` trait class.
== Boost 1.84.0 == Boost 1.84.0
* {cpp}03 is no longer supported. * {cpp}03 is no longer supported.

View File

@@ -1,7 +1,7 @@
//// ////
Copyright 2005-2008 Daniel James Copyright 2005-2008 Daniel James
Copyright 2022 Christian Mazakas Copyright 2022 Christian Mazakas
Copyright 2022 Peter Dimov Copyright 2022, 2025 Peter Dimov
Distributed under the Boost Software License, Version 1.0. Distributed under the Boost Software License, Version 1.0.
https://www.boost.org/LICENSE_1_0.txt https://www.boost.org/LICENSE_1_0.txt
//// ////
@@ -44,6 +44,8 @@ template<class It> std::size_t hash_range( It first, It last );
template<class It> void hash_unordered_range( std::size_t& seed, It first, It last ); template<class It> void hash_unordered_range( std::size_t& seed, It first, It last );
template<class It> std::size_t hash_unordered_range( It first, It last ); template<class It> std::size_t hash_unordered_range( It first, It last );
template<class Hash> struct hash_is_avalanching;
} // namespace boost } // namespace boost
---- ----
@@ -572,6 +574,56 @@ where `x` is the currently contained value in `v`.
Throws: :: Throws: ::
`std::bad_variant_access` when `v.valueless_by_exception()` is `true`. `std::bad_variant_access` when `v.valueless_by_exception()` is `true`.
== <boost/container_hash/{zwsp}hash_is_avalanching.hpp>
Defines the trait `boost::hash_is_avalanching`.
[source]
----
namespace boost
{
template<class Hash> struct hash_is_avalanching;
} // namespace boost
----
=== hash_is_avalanching<Hash>
[source]
----
template<class Hash> struct hash_is_avalanching
{
static constexpr bool value = /* see below */;
};
----
`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),
* ill-formed otherwise.
A hash function is said to have the _avalanching property_ if small changes
in the input translate to large changes in the returned hash code
&#8212;ideally, flipping one bit in the representation of the input value results
in each bit of the hash code flipping with probability 50%. Libraries
such as link:../../../unordered/index.html[Boost.Unordered] consult this trait
to determine if the supplied hash function is of high quality.
`boost::hash` for `std::basic_string<Ch>` and `std::basic_string_view<Ch>`
has this trait set to `true` when `Ch` is an integral type (this includes
`std::string` and `std::string_view`, among others).
Users can set this trait for a particular `Hash` type by:
* Inserting the nested `is_avalanching` typedef in the class definition
if they have access to its source code.
* Writing a specialization of `boost::hash_is_avalanching`
for `Hash`.
Note that usage of this trait is not restricted to hash functions produced
with Boost.ContainerHash.
== <boost/container_hash/{zwsp}is_range.hpp> == <boost/container_hash/{zwsp}is_range.hpp>
Defines the trait `boost::container_hash::is_range`. Defines the trait `boost::container_hash::is_range`.

View File

@@ -1,5 +1,5 @@
// Copyright 2005-2014 Daniel James. // Copyright 2005-2014 Daniel James.
// Copyright 2021, 2022 Peter Dimov. // Copyright 2021, 2022, 2025 Peter Dimov.
// Distributed under the Boost Software License, Version 1.0. // Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt // https://www.boost.org/LICENSE_1_0.txt
@@ -11,6 +11,7 @@
#define BOOST_FUNCTIONAL_HASH_HASH_HPP #define BOOST_FUNCTIONAL_HASH_HASH_HPP
#include <boost/container_hash/hash_fwd.hpp> #include <boost/container_hash/hash_fwd.hpp>
#include <boost/container_hash/hash_is_avalanching.hpp>
#include <boost/container_hash/is_range.hpp> #include <boost/container_hash/is_range.hpp>
#include <boost/container_hash/is_contiguous_range.hpp> #include <boost/container_hash/is_contiguous_range.hpp>
#include <boost/container_hash/is_unordered_range.hpp> #include <boost/container_hash/is_unordered_range.hpp>
@@ -557,11 +558,8 @@ namespace boost
#endif #endif
// boost::unordered::hash_is_avalanching // hash_is_avalanching
namespace unordered
{
template<class T> struct hash_is_avalanching;
template<class Ch> struct hash_is_avalanching< boost::hash< std::basic_string<Ch> > >: std::is_integral<Ch> {}; template<class Ch> struct hash_is_avalanching< boost::hash< std::basic_string<Ch> > >: std::is_integral<Ch> {};
#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) #if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW)
@@ -569,7 +567,6 @@ namespace boost
template<class Ch> struct hash_is_avalanching< boost::hash< std::basic_string_view<Ch> > >: std::is_integral<Ch> {}; template<class Ch> struct hash_is_avalanching< boost::hash< std::basic_string_view<Ch> > >: std::is_integral<Ch> {};
#endif #endif
} // namespace unordered
} // namespace boost } // namespace boost

View File

@@ -1,5 +1,5 @@
// Copyright 2005-2009 Daniel James. // Copyright 2005-2009 Daniel James.
// Copyright 2021, 2022 Peter Dimov. // Copyright 2021, 2022, 2025 Peter Dimov.
// Distributed under the Boost Software License, Version 1.0. // Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt // https://www.boost.org/LICENSE_1_0.txt
@@ -32,6 +32,8 @@ template<class It> std::size_t hash_range( It, It );
template<class It> void hash_unordered_range( std::size_t&, It, It ); template<class It> void hash_unordered_range( std::size_t&, It, It );
template<class It> std::size_t hash_unordered_range( It, It ); template<class It> std::size_t hash_unordered_range( It, It );
template<class Hash> struct hash_is_avalanching;
} // namespace boost } // namespace boost
#endif // #ifndef BOOST_FUNCTIONAL_HASH_FWD_HPP #endif // #ifndef BOOST_FUNCTIONAL_HASH_FWD_HPP

View File

@@ -0,0 +1,57 @@
// Copyright 2025 Joaquin M Lopez Munoz.
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#ifndef BOOST_HASH_HASH_IS_AVALANCHING_HPP_INCLUDED
#define BOOST_HASH_HASH_IS_AVALANCHING_HPP_INCLUDED
#include <type_traits>
namespace boost
{
namespace hash_detail
{
template<class... Ts> struct make_void
{
using type = void;
};
template<class... Ts> using void_t = typename make_void<Ts...>::type;
template<class 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<class Hash, class = void> struct hash_is_avalanching_impl: std::false_type
{
};
template<class Hash> struct hash_is_avalanching_impl<Hash, void_t<typename Hash::is_avalanching> >:
std::integral_constant<bool, avalanching_value<typename Hash::is_avalanching>::value>
{
};
template<class Hash>
struct hash_is_avalanching_impl<Hash, typename std::enable_if< ((void)Hash::is_avalanching, true) >::type>
{
// Hash::is_avalanching is not a type: we don't define value to produce
// a compile error downstream
};
} // namespace hash_detail
template<class Hash> struct hash_is_avalanching: hash_detail::hash_is_avalanching_impl<Hash>::type
{
};
} // namespace boost
#endif // #ifndef BOOST_HASH_HASH_IS_AVALANCHING_HPP_INCLUDED

View File

@@ -1,4 +1,4 @@
# Copyright 2018, 2019, 2021, 2022 Peter Dimov # Copyright 2018, 2019, 2021, 2022, 2025 Peter Dimov
# Distributed under the Boost Software License, Version 1.0. # 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 accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt
@@ -7,6 +7,6 @@ include(BoostTestJamfile OPTIONAL RESULT_VARIABLE HAVE_BOOST_TEST)
if(HAVE_BOOST_TEST) if(HAVE_BOOST_TEST)
boost_test_jamfile(FILE Jamfile.v2 boost_test_jamfile(FILE Jamfile.v2
LINK_LIBRARIES Boost::container_hash Boost::core Boost::utility Boost::unordered) LINK_LIBRARIES Boost::container_hash Boost::core Boost::utility)
endif() endif()

View File

@@ -1,5 +1,5 @@
# Copyright 2005-2012 Daniel James. # Copyright 2005-2012 Daniel James.
# Copyright 2022 Peter Dimov # Copyright 2022, 2025 Peter Dimov
# Distributed under the Boost Software License, Version 1.0. # Distributed under the Boost Software License, Version 1.0.
# https://www.boost.org/LICENSE_1_0.txt # https://www.boost.org/LICENSE_1_0.txt
@@ -119,10 +119,9 @@ run is_described_class_test3.cpp
run described_class_test.cpp run described_class_test.cpp
: : : <warnings>extra ; : : : <warnings>extra ;
run hash_is_avalanching_test.cpp run hash_is_avalanching_test.cpp ;
/boost/unordered//boost_unordered ; run hash_is_avalanching_test2.cpp ;
run hash_is_avalanching_test2.cpp run hash_is_avalanching_test3.cpp ;
/boost/unordered//boost_unordered ;
run hash_integral_test2.cpp ; run hash_integral_test2.cpp ;

View File

@@ -1,10 +1,10 @@
// Copyright 2022 Peter Dimov. // Copyright 2022, 2025 Peter Dimov.
// Distributed under the Boost Software License, Version 1.0. // Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt // https://www.boost.org/LICENSE_1_0.txt
#include <boost/container_hash/hash.hpp> #include <boost/container_hash/hash.hpp>
#include <boost/container_hash/hash_is_avalanching.hpp>
#include <boost/core/lightweight_test_trait.hpp> #include <boost/core/lightweight_test_trait.hpp>
#include <boost/unordered/hash_traits.hpp>
#include <boost/config.hpp> #include <boost/config.hpp>
#include <string> #include <string>
@@ -12,7 +12,7 @@ enum my_char { min = 0, max = 255 };
int main() int main()
{ {
using boost::unordered::hash_is_avalanching; using boost::hash_is_avalanching;
BOOST_TEST_TRAIT_TRUE(( hash_is_avalanching< boost::hash<std::string> > )); BOOST_TEST_TRAIT_TRUE(( hash_is_avalanching< boost::hash<std::string> > ));
BOOST_TEST_TRAIT_TRUE(( hash_is_avalanching< boost::hash<std::wstring> > )); BOOST_TEST_TRAIT_TRUE(( hash_is_avalanching< boost::hash<std::wstring> > ));

View File

@@ -1,8 +1,9 @@
// Copyright 2022 Peter Dimov. // Copyright 2022, 2025 Peter Dimov.
// Distributed under the Boost Software License, Version 1.0. // Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt // https://www.boost.org/LICENSE_1_0.txt
#include <boost/container_hash/hash.hpp> #include <boost/container_hash/hash.hpp>
#include <boost/container_hash/hash_is_avalanching.hpp>
#include <boost/core/lightweight_test_trait.hpp> #include <boost/core/lightweight_test_trait.hpp>
#include <boost/config.hpp> #include <boost/config.hpp>
#include <boost/config/pragma_message.hpp> #include <boost/config/pragma_message.hpp>
@@ -14,14 +15,13 @@ int main() {}
#else #else
#include <boost/unordered/hash_traits.hpp>
#include <string_view> #include <string_view>
enum my_char { min = 0, max = 255 }; enum my_char { min = 0, max = 255 };
int main() int main()
{ {
using boost::unordered::hash_is_avalanching; using boost::hash_is_avalanching;
BOOST_TEST_TRAIT_TRUE(( hash_is_avalanching< boost::hash<std::string_view> > )); BOOST_TEST_TRAIT_TRUE(( hash_is_avalanching< boost::hash<std::string_view> > ));
BOOST_TEST_TRAIT_TRUE(( hash_is_avalanching< boost::hash<std::wstring_view> > )); BOOST_TEST_TRAIT_TRUE(( hash_is_avalanching< boost::hash<std::wstring_view> > ));

View File

@@ -0,0 +1,38 @@
// Copyright 2025 Joaquin M Lopez Munoz.
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/container_hash/hash_is_avalanching.hpp>
#include <boost/core/lightweight_test_trait.hpp>
#include <type_traits>
struct X
{
using is_avalanching = void;
};
struct Y
{
using is_avalanching = std::true_type;
};
struct Z
{
using is_avalanching = std::false_type;
};
struct W
{
};
int main()
{
using boost::hash_is_avalanching;
BOOST_TEST_TRAIT_TRUE(( hash_is_avalanching< X > ));
BOOST_TEST_TRAIT_TRUE(( hash_is_avalanching< Y > ));
BOOST_TEST_TRAIT_FALSE(( hash_is_avalanching< Z > ));
BOOST_TEST_TRAIT_FALSE(( hash_is_avalanching< W > ));
return boost::report_errors();
}