From c011b2177cb414f30254942d35b12d1f9f7f0140 Mon Sep 17 00:00:00 2001 From: Danny Robson Date: Mon, 24 Jul 2023 12:56:19 +1000 Subject: [PATCH] hash/tuple: add a std compatible tuple hashing object --- CMakeLists.txt | 3 +++ hash/tuple.cpp | 1 + hash/tuple.hpp | 37 +++++++++++++++++++++++++++++++++++ test/hash/tuple.cpp | 47 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 88 insertions(+) create mode 100644 hash/tuple.cpp create mode 100644 hash/tuple.hpp create mode 100644 test/hash/tuple.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 3619bcb4..9e3cd227 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -427,6 +427,8 @@ list ( hash/siphash.hpp hash/table.cpp hash/table.hpp + hash/tuple.cpp + hash/tuple.hpp hash/wang.hpp hash/xxhash.cpp hash/xxhash.hpp @@ -755,6 +757,7 @@ if (TESTS) hash/murmur hash/siphash hash/table + hash/tuple hash/xxhash hton io diff --git a/hash/tuple.cpp b/hash/tuple.cpp new file mode 100644 index 00000000..0fc42dae --- /dev/null +++ b/hash/tuple.cpp @@ -0,0 +1 @@ +#include "./tuple.hpp" \ No newline at end of file diff --git a/hash/tuple.hpp b/hash/tuple.hpp new file mode 100644 index 00000000..1afe7700 --- /dev/null +++ b/hash/tuple.hpp @@ -0,0 +1,37 @@ +#pragma once + +#include "../hash.hpp" +#include "./mix.hpp" + +#include + + +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 + auto + operator() (std::tuple const &val) + { + return compute (val, std::make_index_sequence {}); + } + + private: + template + auto + compute (std::tuple const &val, std::index_sequence) + { + return MixT {} ( + ElementT {} (std::get (val))... + ); + } + }; +} \ No newline at end of file diff --git a/test/hash/tuple.cpp b/test/hash/tuple.cpp new file mode 100644 index 00000000..1af35e60 --- /dev/null +++ b/test/hash/tuple.cpp @@ -0,0 +1,47 @@ +#include "hash/tuple.hpp" + +#include "tap.hpp" + +#include + + +// A "hash" that returns the argument's size. +struct size_hash { + template + std::size_t + operator () (ValueT const &val) const + { return std::size (val); } +}; + + +// A 'mix' function that just sums the arguments. +struct sum_mix { + template + std::size_t + operator () (ValueT ...val) const + { + return (val + ...); + } +}; + + +int +main () +{ + using namespace std::string_view_literals; + + cruft::hash::tuple h; + + cruft::TAP::logger tap; + tap.expect_eq ( + h ( + std::make_tuple ( + "foo"sv, std::vector (5) + ) + ), + 8u, + "size/sum tuple hash" + ); + + return tap.status (); +} \ No newline at end of file