755 lines
17 KiB
Plaintext
755 lines
17 KiB
Plaintext
////
|
|
Copyright 2005-2008 Daniel James
|
|
Copyright 2022 Christian Mazakas
|
|
Copyright 2022 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 );
|
|
|
|
} // 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}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.
|