diff options
author | Steven Le Rouzic <steven.lerouzic@gmail.com> | 2025-01-06 00:33:50 +0100 |
---|---|---|
committer | Steven Le Rouzic <steven.lerouzic@gmail.com> | 2025-01-06 00:33:50 +0100 |
commit | 48f7e22d9cc93989173afe2550fcc2f082c61773 (patch) | |
tree | 1adaa1c16b905b48eeff1997c595909d43a46cd0 /asl | |
parent | 159f38d4e12bbcc48799431f4b69321a445be8ca (diff) |
Start work on hashing
Diffstat (limited to 'asl')
-rw-r--r-- | asl/hash.hpp | 45 | ||||
-rw-r--r-- | asl/meta.hpp | 7 | ||||
-rw-r--r-- | asl/tests/meta_tests.cpp | 4 |
3 files changed, 54 insertions, 2 deletions
diff --git a/asl/hash.hpp b/asl/hash.hpp index 6190e8f..5eb64f6 100644 --- a/asl/hash.hpp +++ b/asl/hash.hpp @@ -1,12 +1,12 @@ #pragma once
#include "asl/integers.hpp"
+#include "asl/meta.hpp"
+#include "asl/utility.hpp"
namespace asl::city_hash
{
-// All CityHash stuff below this point
-
// Hash function for a byte array.
uint64_t CityHash64(const char *s, size_t len);
@@ -51,3 +51,44 @@ constexpr uint64_t Hash128to64(const uint128_t& x) }
} // namespace asl::city_hash
+
+namespace asl
+{
+
+template<typename T, typename H>
+concept hashable_generic = requires(const T& value, H h)
+{
+ { AslHashValue(h, value) } -> same_as<H>;
+};
+
+struct HashState
+{
+ uint128_t state{};
+
+ constexpr HashState() = default;
+ explicit constexpr HashState(uint128_t s) : state{s} {}
+
+ static constexpr HashState combine(HashState h)
+ {
+ return h;
+ }
+
+ template<hashable_generic<HashState> Arg, hashable_generic<HashState>... Remaining>
+ static constexpr HashState combine(HashState h, const Arg& arg, const Remaining&... remaining)
+ {
+ return combine(AslHashValue(h, arg), remaining...);
+ }
+};
+
+template<typename T>
+concept hashable = hashable_generic<T, HashState>;
+
+template<typename H, uniquely_represented T>
+constexpr H AslHashValue(H h, const T& value)
+{
+ auto hashed = city_hash::CityHash128WithSeed(reinterpret_cast<const char*>(&value), size_of<T>, h.state);
+ return HashState{hashed};
+}
+
+} // namespace asl
+
diff --git a/asl/meta.hpp b/asl/meta.hpp index 84616f4..c353b0f 100644 --- a/asl/meta.hpp +++ b/asl/meta.hpp @@ -189,6 +189,13 @@ template<> struct _is_integer_helper<uint64_t> : true_type {}; template<typename T> concept is_integer = _is_integer_helper<un_cv_t<T>>::value;
+template<typename T> struct is_uniquely_represented : false_type {};
+template<is_integer T> struct is_uniquely_represented<T> : true_type {};
+template<> struct is_uniquely_represented<uint128_t> : true_type {};
+template<> struct is_uniquely_represented<byte> : true_type {};
+
+template<typename T> concept uniquely_represented = is_uniquely_represented<T>::value;
+
template<typename T, typename U>
concept equality_comparable_with = requires (const un_cvref_t<T>& a, const un_cvref_t<U>& b)
{
diff --git a/asl/tests/meta_tests.cpp b/asl/tests/meta_tests.cpp index 24e9754..4fedd71 100644 --- a/asl/tests/meta_tests.cpp +++ b/asl/tests/meta_tests.cpp @@ -232,3 +232,7 @@ static_assert(asl::is_floating_point<volatile double>); static_assert(!asl::is_floating_point<const float&>);
static_assert(!asl::is_floating_point<int>);
static_assert(!asl::is_floating_point<C>);
+
+static_assert(asl::uniquely_represented<int>);
+static_assert(asl::uniquely_represented<uint128_t>);
+static_assert(!asl::uniquely_represented<bool>);
|