hash/tuple: add a std compatible tuple hashing object

This commit is contained in:
Danny Robson 2023-07-24 12:56:19 +10:00
parent cb06fb9b29
commit c011b2177c
4 changed files with 88 additions and 0 deletions

View File

@ -427,6 +427,8 @@ list (
hash/siphash.hpp hash/siphash.hpp
hash/table.cpp hash/table.cpp
hash/table.hpp hash/table.hpp
hash/tuple.cpp
hash/tuple.hpp
hash/wang.hpp hash/wang.hpp
hash/xxhash.cpp hash/xxhash.cpp
hash/xxhash.hpp hash/xxhash.hpp
@ -755,6 +757,7 @@ if (TESTS)
hash/murmur hash/murmur
hash/siphash hash/siphash
hash/table hash/table
hash/tuple
hash/xxhash hash/xxhash
hton hton
io io

1
hash/tuple.cpp Normal file
View File

@ -0,0 +1 @@
#include "./tuple.hpp"

37
hash/tuple.hpp Normal file
View File

@ -0,0 +1,37 @@
#pragma once
#include "../hash.hpp"
#include "./mix.hpp"
#include <tuple>
namespace cruft::hash {
/// Computes a hash for a tuple type by elementwise hashing, then variadic mixing.
///
/// \tparam ElementT The per-element hash type
/// \tparam MixT The mixing hash type. Must support variadic operator()
template <
typename ElementT,
typename MixT = cruft::hash::mixer
>
class tuple {
public:
template <typename ...ValueT>
auto
operator() (std::tuple<ValueT...> const &val)
{
return compute (val, std::make_index_sequence<sizeof... (ValueT)> {});
}
private:
template <typename ...ValueT, std::size_t ...IndexV>
auto
compute (std::tuple<ValueT...> const &val, std::index_sequence<IndexV...>)
{
return MixT {} (
ElementT {} (std::get<IndexV> (val))...
);
}
};
}

47
test/hash/tuple.cpp Normal file
View File

@ -0,0 +1,47 @@
#include "hash/tuple.hpp"
#include "tap.hpp"
#include <string_view>
// A "hash" that returns the argument's size.
struct size_hash {
template <typename ValueT>
std::size_t
operator () (ValueT const &val) const
{ return std::size (val); }
};
// A 'mix' function that just sums the arguments.
struct sum_mix {
template <typename ...ValueT>
std::size_t
operator () (ValueT ...val) const
{
return (val + ...);
}
};
int
main ()
{
using namespace std::string_view_literals;
cruft::hash::tuple<size_hash, sum_mix> h;
cruft::TAP::logger tap;
tap.expect_eq (
h (
std::make_tuple (
"foo"sv, std::vector<int> (5)
)
),
8u,
"size/sum tuple hash"
);
return tap.status ();
}