////
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;

} // 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 );

template<class... T>
  std::size_t hash_value( std::tuple<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 in an unspecified manner
and then passed to `hash_combine`, more than one at a time. This is done in
order to improve performance when hashing strings.
--

[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]
----
template<class... T>
  std::size_t hash_value( std::tuple<T...> const& v );
----

Effects: ::
+
[source]
----
std::size_t seed = 0;

boost::hash_combine( seed, std::get<0>(v) );
boost::hash_combine( seed, std::get<1>(v) );
// ...
boost::hash_combine( seed, std::get<N-1>(v) );

return seed;
----
+
where `N` is `sizeof...(T)`.

[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.
