//// 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_ == 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 struct is_range; template struct is_contiguous_range; template struct is_unordered_range; template struct is_described_class; template struct is_tuple_like; } // namespace container_hash template struct hash; template void hash_combine( std::size_t& seed, T const& v ); template void hash_range( std::size_t& seed, It first, It last ); template std::size_t hash_range( It first, It last ); template void hash_unordered_range( std::size_t& seed, It first, It last ); template std::size_t hash_unordered_range( It first, It last ); } // namespace boost ---- == Defines `boost::hash`, and helper functions. [source] ---- namespace boost { template struct hash; template void hash_combine( std::size_t& seed, T const& v ); template void hash_range( std::size_t& seed, It first, It last ); template std::size_t hash_range( It first, It last ); template void hash_unordered_range( std::size_t& seed, It first, It last ); template std::size_t hash_unordered_range( It first, It last ); // Enabled only when T is an integral type template std::size_t hash_value( T v ); // Enabled only when T is an enumeration type template std::size_t hash_value( T v ); // Enabled only when T is a floating point type template std::size_t hash_value( T v ); template std::size_t hash_value( T* const& v ); template std::size_t hash_value( T const (&v)[N] ); template std::size_t hash_value( std::complex const& v ); template std::size_t hash_value( std::pair const& v ); // Enabled only when container_hash::is_tuple_like::value is true template std::size_t hash_value( T const& v ); // Enabled only when container_hash::is_range::value is true template std::size_t hash_value( T const& v ); // Enabled only when container_hash::is_contiguous_range::value is true template std::size_t hash_value( T const& v ); // Enabled only when container_hash::is_unordered_range::value is true template std::size_t hash_value( T const& v ); // Enabled only when container_hash::is_described_class::value is true template std::size_t hash_value( T const& v ); template std::size_t hash_value( std::shared_ptr const& v ); template std::size_t hash_value( std::unique_ptr 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 std::size_t hash_value( std::optional const& v ); std::size_t hash_value( std::monostate v ); template std::size_t hash_value( std::variant const& v ); } // namespace boost ---- === hash [source] ---- template 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 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()(v)`. Throws: :: Only throws if `boost::hash()(v)` throws. On exception, `seed` is not updated. Remarks: :: + -- Equivalent to `seed = combine(seed, boost::hash()(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(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()` and `std::vector(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 void hash_range( std::size_t& seed, It first, It last ); ---- Effects: :: + -- When `typename std::iterator_traits::value_type` is not `char`, `signed char`, `unsigned char`, `std::byte`, or `char8_t`, [source] ---- for( ; first != last; ++first ) { boost::hash_combine::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 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 void hash_unordered_range( std::size_t& seed, It first, It last ); ---- Effects: :: Updates `seed` with the values of `boost::hash::value_type>()(*i)` for each `i` in `[first, last)`, such that the order of elements does not affect the final result. [source] ---- template 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 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(v)`. + Otherwise, an unspecified value obtained by mixing the value bits of `v`. [source] ---- // Enabled only when T is an enumeration type template std::size_t hash_value( T v ); ---- Returns: :: `static_cast(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 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 std::size_t hash_value( T* const& v ); ---- Returns: :: An unspecified value derived from `reinterpret_cast(v)`. [source] ---- template std::size_t hash_value( T const (&v)[N] ); ---- Returns: :: `boost::hash_range( v, v + N )`. [source] ---- template std::size_t hash_value( std::complex const& v ); ---- Returns: :: An unspecified value derived from `boost::hash()(v.real())` and `boost::hash()(v.imag())` such that, if `v.imag() == 0`, the value is equal to `boost::hash()(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 std::size_t hash_value( std::pair 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::value is true template 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(v) ); return seed; ---- + where `N` is `std::tuple_size::value`. Remarks: :: This overload is only enabled when `container_hash::is_range::value` is `false`. [source] ---- // Enabled only when container_hash::is_range::value is true template 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::value` and `container_hash::is_unordered_range::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::value is true template 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::value is true template 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::value is true template 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 std::size_t hash_value( std::shared_ptr const& v ); template std::size_t hash_value( std::unique_ptr const& v ); ---- Returns: :: `boost::hash( 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 std::size_t hash_value( std::optional const& v ); ---- Returns: :: For a disengaged `v`, an unspecified constant value; otherwise, `boost::hash()( *v )`. [source] ---- std::size_t hash_value( std::monostate v ); ---- Returns: :: An unspecified constant value. [source] ---- template std::size_t hash_value( std::variant 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`. == Defines the trait `boost::container_hash::is_range`. [source] ---- namespace boost { namespace container_hash { template struct is_range; } // namespace container_hash } // namespace boost ---- === is_range [source] ---- template struct is_range { static constexpr bool value = /* see below */; }; ---- `is_range::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` is a valid specialization.) Users are allowed to specialize `is_range` for their types if the default behavior does not deduce the correct value. == Defines the trait `boost::container_hash::is_contiguous_range`. [source] ---- namespace boost { namespace container_hash { template struct is_contiguous_range; } // namespace container_hash } // namespace boost ---- === is_contiguous_range [source] ---- template struct is_contiguous_range { static constexpr bool value = /* see below */; }; ---- `is_contiguous_range::value` is `true` when `is_range::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. == Defines the trait `boost::container_hash::is_unordered_range`. [source] ---- namespace boost { namespace container_hash { template struct is_unordered_range; } // namespace container_hash } // namespace boost ---- === is_unordered_range [source] ---- template struct is_unordered_range { static constexpr bool value = /* see below */; }; ---- `is_unordered_range::value` is `true` when `is_range::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. == Defines the trait `boost::container_hash::is_described_class`. [source] ---- namespace boost { namespace container_hash { template struct is_described_class; } // namespace container_hash } // namespace boost ---- === is_described_class [source] ---- template struct is_described_class { static constexpr bool value = /* see below */; }; ---- `is_described_class::value` is `true` when `boost::describe::has_describe_bases::value` is `true`, `boost::describe::has_describe_members::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. == Defines the trait `boost::container_hash::is_tuple_like`. [source] ---- namespace boost { namespace container_hash { template struct is_tuple_like; } // namespace container_hash } // namespace boost ---- === is_tuple_like [source] ---- template struct is_tuple_like { static constexpr bool value = /* see below */; }; ---- `is_tuple_like::value` is `true` when `std::tuple_size::value` is valid. Users are allowed to specialize `is_tuple_like` for their types if the default behavior does not deduce the correct value.