Files
container_hash/doc/hash/reference.adoc
2025-06-08 23:23:14 +03:00

807 lines
18 KiB
Plaintext

////
Copyright 2005-2008 Daniel James
Copyright 2022 Christian Mazakas
Copyright 2022, 2025 Peter Dimov
Distributed under the Boost Software License, Version 1.0.
https://www.boost.org/LICENSE_1_0.txt
////
[#reference]
= Reference
:idprefix: ref_
== <boost/container_hash/{zwsp}hash_fwd.hpp>
This header contains forward declarations for the library primitives.
These declarations are guaranteed to be relatively stable, that is,
best effort will be expended on their not changing from release to
release, allowing their verbatim copy into user headers that do not
wish to physically depend on Boost.ContainerHash.
[source]
----
namespace boost
{
namespace container_hash
{
template<class T> struct is_range;
template<class T> struct is_contiguous_range;
template<class T> struct is_unordered_range;
template<class T> struct is_described_class;
template<class T> struct is_tuple_like;
} // namespace container_hash
template<class T> struct hash;
template<class T> void hash_combine( std::size_t& seed, T const& v );
template<class It> void hash_range( std::size_t& seed, It first, It last );
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> std::size_t hash_unordered_range( It first, It last );
template<class Hash> struct hash_is_avalanching;
} // namespace boost
----
== <boost/container_hash/{zwsp}hash.hpp>
Defines `boost::hash`, and helper functions.
[source]
----
namespace boost
{
template<class T> struct hash;
template<class T> void hash_combine( std::size_t& seed, T const& v );
template<class It> void hash_range( std::size_t& seed, It first, It last );
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> std::size_t hash_unordered_range( It first, It last );
// Enabled only when T is an integral type
template<class T>
std::size_t hash_value( T v );
// Enabled only when T is an enumeration type
template<class T>
std::size_t hash_value( T v );
// Enabled only when T is a floating point type
template<class T>
std::size_t hash_value( T v );
template<class T>
std::size_t hash_value( T* const& v );
template<class T, std::size_t N>
std::size_t hash_value( T const (&v)[N] );
template<class T>
std::size_t hash_value( std::complex<T> const& v );
template<class A, class B>
std::size_t hash_value( std::pair<A, B> const& v );
// Enabled only when container_hash::is_tuple_like<T>::value is true
template<class T>
std::size_t hash_value( T const& v );
// Enabled only when container_hash::is_range<T>::value is true
template<class T>
std::size_t hash_value( T const& v );
// Enabled only when container_hash::is_contiguous_range<T>::value is true
template<class T>
std::size_t hash_value( T const& v );
// Enabled only when container_hash::is_unordered_range<T>::value is true
template<class T>
std::size_t hash_value( T const& v );
// Enabled only when container_hash::is_described_class<T>::value is true
template<class T>
std::size_t hash_value( T const& v );
template<class T>
std::size_t hash_value( std::shared_ptr<T> const& v );
template<class T, class D>
std::size_t hash_value( std::unique_ptr<T, D> const& v );
std::size_t hash_value( std::type_index const& v );
std::size_t hash_value( std::error_code const& v );
std::size_t hash_value( std::error_condition const& v );
template<class T>
std::size_t hash_value( std::optional<T> const& v );
std::size_t hash_value( std::monostate v );
template<class... T>
std::size_t hash_value( std::variant<T...> const& v );
} // namespace boost
----
=== hash<T>
[source]
----
template<class T> struct hash
{
std::size_t operator()( T const& v ) const;
};
----
==== operator()
[source]
----
std::size_t operator()( T const& v ) const;
----
Returns: :: `hash_value(v)`.
Throws: :: Only throws if `hash_value(v)` throws.
Remarks: :: The call to `hash_value` is unqualified, so that user-supplied
overloads will be found via argument dependent lookup.
=== hash_combine
[source]
----
template<class T> void hash_combine( std::size_t& seed, T const& v );
----
Called repeatedly to incrementally create a hash value from several variables.
Effects: :: Updates `seed` with a new hash value generated by
deterministically combining it with the result of `boost::hash<T>()(v)`.
Throws: :: Only throws if `boost::hash<T>()(v)` throws. On exception,
`seed` is not updated.
Remarks: ::
+
--
Equivalent to `seed = combine(seed, boost::hash<T>()(v))`,
where `combine(s, v)` is a mixing function that takes two arguments of
type `std::size_t` and returns `std::size_t`, with the following desirable
properties:
. For a constant `s`, when `v` takes all possible `size_t` values,
`combine(s, v)` should also take all possible `size_t` values, producing
a sequence that is close to random; that is, it should be a random
permutation.
+
This guarantees that for a given `seed`, `combine` does not introduce
hash collisions when none were produced by `boost::hash<T>(v)`; that is,
it does not lose information from the input. It also implies that
`combine(s, v)`, as a function of `v`, has good avalanche properties;
that is, small (e.g. single bit) perturbations in the input `v` lead to
large perturbations in the return value (half of the output bits changing,
on average).
. For two different seeds `s1` and `s2`, `combine(s1, v)` and
`combine(s2, v)`, treated as functions of `v`, should produce two
different random permutations.
. `combine(0, 0)` should not be 0. Since a common initial value of `seed`
is zero, `combine(0, 0) == 0` would imply that applying `hash_combine` on
any sequence of zeroes, regardless of length, will produce zero. This is
undesirable, as it would lead to e.g. `std::vector<int>()` and
`std::vector<int>(4)` to have the same hash value.
The current implementation uses the function `mix(s + 0x9e3779b9 + v)` as
`combine(s, v)`, where `mix(x)` is a high quality mixing function that is a
bijection over the `std::size_t` values, of the form
[source]
----
x ^= x >> k1;
x *= m1;
x ^= x >> k2;
x *= m2;
x ^= x >> k3;
----
where the constants `k1`, `k2`, `k3`, `m1`, `m2` are suitably chosen.
Note that `mix(0)` is 0. This is why we add the arbitrary constant
`0x9e3779b9` to meet the third requirement above.
--
=== hash_range
[source]
----
template<class It> void hash_range( std::size_t& seed, It first, It last );
----
Effects: ::
+
--
When `typename std::iterator_traits<It>::value_type` is not `char`, `signed char`,
`unsigned char`, `std::byte`, or `char8_t`,
[source]
----
for( ; first != last; ++first )
{
boost::hash_combine<typename std::iterator_traits<It>::value_type>( seed, *first );
}
----
Otherwise, bytes from `[first, last)` are coalesced and hashed in an
unspecified manner. This is done in order to improve performance when hashing
strings.
--
Remarks: ::
For chars, the current implementation uses
https://github.com/pdimov/mulxp_hash[`mulxp1_hash`] when `std::size_t` is
64 bit, and `mulxp1_hash32` when it's 32 bit.
[source]
----
template<class It> std::size_t hash_range( It first, It last );
----
Effects: ::
+
[source]
----
size_t seed = 0;
boost::hash_range( seed, first, last );
return seed;
----
=== hash_unordered_range
[source]
----
template<class It> void hash_unordered_range( std::size_t& seed, It first, It last );
----
Effects: :: Updates `seed` with the values of
`boost::hash<typename std::iterator_traits<It>::value_type>()(*i)`
for each `i` in `[first, last)`, such that the order of elements does
not affect the final result.
[source]
----
template<class It> std::size_t hash_unordered_range( It first, It last );
----
Effects: ::
+
[source]
----
size_t seed = 0;
boost::hash_unordered_range( seed, first, last );
return seed;
----
=== hash_value
[source]
----
// Enabled only when T is an integral type
template<class T>
std::size_t hash_value( T v );
----
Returns: ::
When the value of `v` fits into `std::size_t`, when `T` is an unsigned type,
or into `ssize_t`, when `T` is a signed type, `static_cast<std::size_t>(v)`.
+
Otherwise, an unspecified value obtained by mixing the value bits of `v`.
[source]
----
// Enabled only when T is an enumeration type
template<class T>
std::size_t hash_value( T v );
----
Returns: ::
`static_cast<std::size_t>(v)`.
Remarks: ::
`hash_value(std::to_underlying(v))` would be better, but {cpp}03
compatibility mandates the current implementation.
[source]
----
// Enabled only when T is a floating point type
template<class T>
std::size_t hash_value( T v );
----
Returns: ::
An unspecified value obtained by mixing the value bits of `v`.
Remarks: ::
When `sizeof(v) \<= sizeof(std::size_t)`, the bits of `v` are returned
as-is (except in the case of -0.0, which is treated as +0.0).
[source]
----
template<class T>
std::size_t hash_value( T* const& v );
----
Returns: ::
An unspecified value derived from `reinterpret_cast<std::uintptr_t>(v)`.
[source]
----
template<class T, std::size_t N>
std::size_t hash_value( T const (&v)[N] );
----
Returns: ::
`boost::hash_range( v, v + N )`.
[source]
----
template<class T>
std::size_t hash_value( std::complex<T> const& v );
----
Returns: ::
An unspecified value derived from `boost::hash<T>()(v.real())` and
`boost::hash<T>()(v.imag())` such that, if `v.imag() == 0`, the value
is equal to `boost::hash<T>()(v.real())`.
Remarks: ::
A more straightforward implementation would just have used `hash_combine`
on `v.real()` and `v.imag()`, but the historical guarantee that real-valued
complex numbers should match the hash value of their real part precludes it.
+
This guarantee may be dropped in a future release, as it's of questionable
utility.
[source]
----
template<class A, class B>
std::size_t hash_value( std::pair<A, B> const& v );
----
Effects: ::
+
[source]
----
std::size_t seed = 0;
boost::hash_combine( seed, v.first );
boost::hash_combine( seed, v.second );
return seed;
----
[source]
----
// Enabled only when container_hash::is_tuple_like<T>::value is true
template<class T>
std::size_t hash_value( T const& v );
----
Effects: ::
+
[source]
----
std::size_t seed = 0;
using std::get;
boost::hash_combine( seed, get<0>(v) );
boost::hash_combine( seed, get<1>(v) );
// ...
boost::hash_combine( seed, get<N-1>(v) );
return seed;
----
+
where `N` is `std::tuple_size<T>::value`.
Remarks: ::
This overload is only enabled when
`container_hash::is_range<T>::value` is `false`.
[source]
----
// Enabled only when container_hash::is_range<T>::value is true
template<class T>
std::size_t hash_value( T const& v );
----
Returns: ::
`boost::hash_range( v.begin(), v.end() )`.
Remarks: ::
This overload is only enabled when
`container_hash::is_contiguous_range<T>::value` and
`container_hash::is_unordered_range<T>::value` are both `false`.
+
It handles all standard containers that aren't contiguous or unordered, such
as `std::deque`, `std::list`, `std::set`, `std::map`.
[source]
----
// Enabled only when container_hash::is_contiguous_range<T>::value is true
template<class T>
std::size_t hash_value( T const& v );
----
Returns: ::
`boost::hash_range( v.data(), v.data() + v.size() )`.
Remarks: ::
This overload handles all standard contiguous containers, such as
`std::string`, `std::vector`, `std::array`, `std::string_view`.
[source]
----
// Enabled only when container_hash::is_unordered_range<T>::value is true
template<class T>
std::size_t hash_value( T const& v );
----
Returns: ::
`boost::hash_unordered_range( v.begin(), v.end() )`.
Remarks: ::
This overload handles the standard unordered containers, such as
`std::unordered_set` and `std::unordered_map`.
[source]
----
// Enabled only when container_hash::is_described_class<T>::value is true
template<class T>
std::size_t hash_value( T const& v );
----
Effects: ::
+
[source]
----
std::size_t seed = 0;
boost::hash_combine( seed, b1 );
boost::hash_combine( seed, b2 );
// ...
boost::hash_combine( seed, bM );
boost::hash_combine( seed, m1 );
boost::hash_combine( seed, m2 );
// ...
boost::hash_combine( seed, mN );
return seed;
----
+
where `bi` are the bases of `v` and `mi` are its members.
[source]
----
template<class T>
std::size_t hash_value( std::shared_ptr<T> const& v );
template<class T, class D>
std::size_t hash_value( std::unique_ptr<T, D> const& v );
----
Returns: ::
`boost::hash<T*>( v.get() )`.
[source]
----
std::size_t hash_value( std::type_index const& v );
----
Returns: ::
`v.hash_code()`.
[source]
----
std::size_t hash_value( std::error_code const& v );
std::size_t hash_value( std::error_condition const& v );
----
Effects: ::
+
[source]
----
std::size_t seed = 0;
boost::hash_combine( seed, v.value() );
boost::hash_combine( seed, &v.category() );
return seed;
----
[source]
----
template<class T>
std::size_t hash_value( std::optional<T> const& v );
----
Returns: ::
For a disengaged `v`, an unspecified constant value; otherwise,
`boost::hash<T>()( *v )`.
[source]
----
std::size_t hash_value( std::monostate v );
----
Returns: ::
An unspecified constant value.
[source]
----
template<class... T>
std::size_t hash_value( std::variant<T...> const& v );
----
Effects: ::
+
[source]
----
std::size_t seed = 0;
boost::hash_combine( seed, v.index() );
boost::hash_combine( seed, x );
return seed;
----
+
where `x` is the currently contained value in `v`.
Throws: ::
`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>
Defines the trait `boost::container_hash::is_range`.
[source]
----
namespace boost
{
namespace container_hash
{
template<class T> struct is_range;
} // namespace container_hash
} // namespace boost
----
=== is_range<T>
[source]
----
template<class T> struct is_range
{
static constexpr bool value = /* see below */;
};
----
`is_range<T>::value` is `true` when, for a const value `x` of type
`T`, `x.begin()` and `x.end()` return iterators of the same type
`It` (such that `std::iterator_traits<It>` is a valid specialization.)
Users are allowed to specialize `is_range` for their types if the
default behavior does not deduce the correct value.
== <boost/container_hash/{zwsp}is_contiguous_range.hpp>
Defines the trait `boost::container_hash::is_contiguous_range`.
[source]
----
namespace boost
{
namespace container_hash
{
template<class T> struct is_contiguous_range;
} // namespace container_hash
} // namespace boost
----
=== is_contiguous_range<T>
[source]
----
template<class T> struct is_contiguous_range
{
static constexpr bool value = /* see below */;
};
----
`is_contiguous_range<T>::value` is `true` when `is_range<T>::value` is
`true` and when, for a const value `x` of type `T`, `x.data()` returns
a pointer to a type that matches the `value_type` of the iterator returned
by `x.begin()` and `x.end()`, and `x.size()` returns a value of an integral
type.
Users are allowed to specialize `is_contiguous_range` for their types
if the default behavior does not deduce the correct value.
== <boost/container_hash/{zwsp}is_unordered_range.hpp>
Defines the trait `boost::container_hash::is_unordered_range`.
[source]
----
namespace boost
{
namespace container_hash
{
template<class T> struct is_unordered_range;
} // namespace container_hash
} // namespace boost
----
=== is_unordered_range<T>
[source]
----
template<class T> struct is_unordered_range
{
static constexpr bool value = /* see below */;
};
----
`is_unordered_range<T>::value` is `true` when `is_range<T>::value` is
`true` and when `T::hasher` is a valid type.
Users are allowed to specialize `is_unordered_range` for their types
if the default behavior does not deduce the correct value.
== <boost/container_hash/{zwsp}is_described_class.hpp>
Defines the trait `boost::container_hash::is_described_class`.
[source]
----
namespace boost
{
namespace container_hash
{
template<class T> struct is_described_class;
} // namespace container_hash
} // namespace boost
----
=== is_described_class<T>
[source]
----
template<class T> struct is_described_class
{
static constexpr bool value = /* see below */;
};
----
`is_described_class<T>::value` is `true` when
`boost::describe::has_describe_bases<T>::value` is `true`,
`boost::describe::has_describe_members<T>::value` is `true`, and
`T` is not a union.
Users are allowed to specialize `is_described_class` for their types
if the default behavior does not deduce the correct value.
== <boost/container_hash/{zwsp}is_tuple_like.hpp>
Defines the trait `boost::container_hash::is_tuple_like`.
[source]
----
namespace boost
{
namespace container_hash
{
template<class T> struct is_tuple_like;
} // namespace container_hash
} // namespace boost
----
=== is_tuple_like<T>
[source]
----
template<class T> struct is_tuple_like
{
static constexpr bool value = /* see below */;
};
----
`is_tuple_like<T>::value` is `true` when `std::tuple_size<T>::value`
is valid.
Users are allowed to specialize `is_tuple_like` for their types
if the default behavior does not deduce the correct value.