From cccda1bac2bb705aeced3cf6016e10dcef257ada Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Wed, 7 Feb 2024 08:39:12 +0700 Subject: [PATCH] cleanup and simplify internal hash calculations --- develop/singles/headers/meta.hpp/meta_all.hpp | 281 ++++++++++-------- .../meta_shared_exe/meta_shared_tests.cpp | 52 ++-- headers/meta.hpp/meta_base.hpp | 2 +- headers/meta.hpp/meta_base/hash_combiner.hpp | 33 -- headers/meta.hpp/meta_base/hash_composer.hpp | 76 +++++ headers/meta.hpp/meta_detail/type_sharing.hpp | 164 +++++----- .../meta.hpp/meta_indices/argument_index.hpp | 2 +- .../meta_indices/constructor_index.hpp | 2 +- .../meta_indices/destructor_index.hpp | 2 +- .../meta.hpp/meta_indices/evalue_index.hpp | 2 +- .../meta.hpp/meta_indices/function_index.hpp | 2 +- .../meta.hpp/meta_indices/member_index.hpp | 2 +- .../meta.hpp/meta_indices/method_index.hpp | 2 +- headers/meta.hpp/meta_indices/scope_index.hpp | 2 +- .../meta.hpp/meta_indices/variable_index.hpp | 2 +- headers/meta.hpp/meta_types.hpp | 9 +- headers/meta.hpp/meta_uresult/uresult.hpp | 2 +- 17 files changed, 351 insertions(+), 286 deletions(-) delete mode 100644 headers/meta.hpp/meta_base/hash_combiner.hpp create mode 100644 headers/meta.hpp/meta_base/hash_composer.hpp diff --git a/develop/singles/headers/meta.hpp/meta_all.hpp b/develop/singles/headers/meta.hpp/meta_all.hpp index 84fe91b..14f8dbf 100644 --- a/develop/singles/headers/meta.hpp/meta_all.hpp +++ b/develop/singles/headers/meta.hpp/meta_all.hpp @@ -764,30 +764,6 @@ namespace meta_hpp::detail } } -namespace meta_hpp::detail -{ - struct hash_combiner { - template < typename T > - [[nodiscard]] std::size_t operator()(const T& x) const noexcept { - return std::hash{}(x); - } - - template < typename T > - requires(sizeof(std::size_t) == sizeof(std::uint32_t)) - [[nodiscard]] std::size_t operator()(std::size_t seed, const T& x) const noexcept { - // NOLINTNEXTLINE(*-magic-numbers) - return (seed ^= std::hash{}(x) + 0x9e3779b9U + (seed << 6) + (seed >> 2)); - } - - template < typename T > - requires(sizeof(std::size_t) == sizeof(std::uint64_t)) - [[nodiscard]] std::size_t operator()(std::size_t seed, const T& x) const noexcept { - // NOLINTNEXTLINE(*-magic-numbers) - return (seed ^= std::hash{}(x) + 0x9e3779b97f4a7c15LLU + (seed << 12) + (seed >> 4)); - } - }; -} - namespace meta_hpp::detail { class hashed_string final { @@ -847,6 +823,70 @@ namespace std }; } +namespace meta_hpp::detail +{ + template < std::size_t SizeBytes = sizeof(std::size_t) > + struct hash_composer_traits {}; + + template <> + struct hash_composer_traits { + [[nodiscard]] static constexpr std::size_t combine(std::size_t a, std::size_t b) noexcept { + // NOLINTNEXTLINE(*-magic-numbers) + return (a ^= b + 0x9e3779b9U + (a << 6) + (a >> 2)); + } + }; + + template <> + struct hash_composer_traits { + [[nodiscard]] static constexpr std::size_t combine(std::size_t a, std::size_t b) noexcept { + // NOLINTNEXTLINE(*-magic-numbers) + return (a ^= b + 0x9e3779b97f4a7c15LLU + (a << 12) + (a >> 4)); + } + }; + + struct hash_composer final : private hash_composer_traits<> { + std::size_t hash{fnv1a_hash_traits<>::prime}; + + constexpr operator std::size_t() const noexcept { + return hash; + } + + constexpr hash_composer operator<<(std::string_view value) noexcept { + hash = combine(hash, hashed_string{value}.get_hash()); + return *this; + } + + template < typename Pointer > + requires std::is_pointer_v + constexpr hash_composer operator<<(Pointer value) noexcept { + // NOLINTNEXTLINE(*-reinterpret-cast) + hash = combine(hash, reinterpret_cast(value)); + return *this; + } + + template < typename Integral > + requires(std::is_integral_v && sizeof(Integral) <= sizeof(std::size_t)) + constexpr hash_composer operator<<(Integral value) noexcept { + hash = combine(hash, static_cast(value)); + return *this; + } + + template < typename Enum > + requires(std::is_enum_v && sizeof(std::underlying_type_t) <= sizeof(std::size_t)) + constexpr hash_composer operator<<(Enum value) noexcept { + hash = combine(hash, static_cast(value)); + return *this; + } + + template < typename Enum > + requires(std::is_enum_v && sizeof(std::underlying_type_t) <= sizeof(std::size_t)) + constexpr hash_composer operator<<(bitflags value) noexcept { + hash = combine(hash, static_cast(value.as_raw())); + return *this; + } + }; +} + namespace meta_hpp::detail { template < typename Value, typename Allocator > @@ -2695,6 +2735,8 @@ namespace meta_hpp [[nodiscard]] bool is_valid() const noexcept; [[nodiscard]] explicit operator bool() const noexcept; + [[nodiscard]] std::size_t get_hash() const noexcept; + [[nodiscard]] id_type get_id() const noexcept; [[nodiscard]] type_kind get_kind() const noexcept; [[nodiscard]] const metadata_map& get_metadata() const noexcept; @@ -2987,7 +3029,7 @@ namespace std template < meta_hpp::type_family Type > struct hash { size_t operator()(const Type& type) const noexcept { - return type.is_valid() ? type.get_id().get_hash() : 0; + return type.get_hash(); } }; } @@ -3262,6 +3304,11 @@ namespace meta_hpp return is_valid(); } + template < type_family Type > + std::size_t type_base::get_hash() const noexcept { + return get_id().get_hash(); + } + template < type_family Type > typename type_base::id_type type_base::get_id() const noexcept { return id_type{data_}; @@ -5518,7 +5565,7 @@ namespace meta_hpp } inline std::size_t argument_index::get_hash() const noexcept { - return detail::hash_combiner{}(detail::hash_combiner{}(type_), position_); + return detail::hash_composer{} << type_.get_hash() << position_; } } @@ -5536,7 +5583,7 @@ namespace meta_hpp } inline std::size_t constructor_index::get_hash() const noexcept { - return detail::hash_combiner{}(type_); + return detail::hash_composer{} << type_.get_hash(); } } @@ -5554,7 +5601,7 @@ namespace meta_hpp } inline std::size_t destructor_index::get_hash() const noexcept { - return detail::hash_combiner{}(type_); + return detail::hash_composer{} << type_.get_hash(); } } @@ -5582,7 +5629,7 @@ namespace meta_hpp } inline std::size_t evalue_index::get_hash() const noexcept { - return detail::hash_combiner{}(detail::hash_combiner{}(type_), name_); + return detail::hash_composer{} << type_.get_hash() << name_; } } @@ -5610,7 +5657,7 @@ namespace meta_hpp } inline std::size_t function_index::get_hash() const noexcept { - return detail::hash_combiner{}(detail::hash_combiner{}(type_), name_); + return detail::hash_composer{} << type_.get_hash() << name_; } } @@ -5638,7 +5685,7 @@ namespace meta_hpp } inline std::size_t member_index::get_hash() const noexcept { - return detail::hash_combiner{}(detail::hash_combiner{}(type_), name_); + return detail::hash_composer{} << type_.get_hash() << name_; } } @@ -5666,7 +5713,7 @@ namespace meta_hpp } inline std::size_t method_index::get_hash() const noexcept { - return detail::hash_combiner{}(detail::hash_combiner{}(type_), name_); + return detail::hash_composer{} << type_.get_hash() << name_; } } @@ -5688,7 +5735,7 @@ namespace meta_hpp } inline std::size_t scope_index::get_hash() const noexcept { - return detail::hash_combiner{}(name_); + return detail::hash_composer{} << name_; } } @@ -5716,7 +5763,7 @@ namespace meta_hpp } inline std::size_t variable_index::get_hash() const noexcept { - return detail::hash_combiner{}(detail::hash_combiner{}(type_), name_); + return detail::hash_composer{} << type_.get_hash() << name_; } } @@ -6426,39 +6473,9 @@ namespace meta_hpp::detail namespace meta_hpp::detail { template < typename Type > - [[nodiscard]] constexpr std::size_t shared_hash() noexcept { + [[nodiscard]] constexpr std::size_t get_shared_hash() noexcept { return shared_type_hash, Type>{}(); } - - template < enum_kind Enum > - [[nodiscard]] constexpr std::size_t shared_hash(Enum value) noexcept { - return static_cast(value); - } - - template < enum_kind Enum > - [[nodiscard]] constexpr std::size_t shared_hash(bitflags value) noexcept { - return static_cast(value.as_raw()); - } - - template < typename Integral > - requires(std::is_integral_v && sizeof(Integral) <= sizeof(std::size_t)) - [[nodiscard]] constexpr std::size_t shared_hash(Integral value) noexcept { - return static_cast(value); - } - - template < typename Value > - requires(sizeof(std::size_t) == sizeof(std::uint32_t)) - [[nodiscard]] constexpr std::size_t shared_hash_append(std::size_t seed, Value value) noexcept { - // NOLINTNEXTLINE(*-magic-numbers) - return (seed ^= shared_hash(value) + 0x9e3779b9U + (seed << 6) + (seed >> 2)); - } - - template < typename Value > - requires(sizeof(std::size_t) == sizeof(std::uint64_t)) - [[nodiscard]] constexpr std::size_t shared_hash_append(std::size_t seed, Value value) noexcept { - // NOLINTNEXTLINE(*-magic-numbers) - return (seed ^= shared_hash(value) + 0x9e3779b97f4a7c15LLU + (seed << 12) + (seed >> 4)); - } } namespace meta_hpp::detail @@ -6475,7 +6492,7 @@ namespace meta_hpp::detail template < type_kind, typename... > struct shared_type_data_hash { [[nodiscard]] std::size_t operator()(const void* type_data) const noexcept { - return hash_combiner{}(type_data); + return hash_composer{} << type_data; } }; @@ -6529,192 +6546,206 @@ namespace meta_hpp::detail template < shared_type_kind Array > struct shared_type_hash { [[nodiscard]] constexpr std::size_t operator()() const noexcept { - std::size_t hash = shared_hash(type_kind::array_); + hash_composer hash{}; + hash << type_kind::array_; using traits = array_traits; - hash = shared_hash_append(hash, traits::make_flags()); + hash << traits::make_flags(); - hash = shared_hash_append(hash, shared_hash()); + hash << get_shared_hash(); - hash = shared_hash_append(hash, traits::extent); + hash << traits::extent; - return hash; + return hash.hash; } }; template < shared_type_kind Class > struct shared_type_hash { [[nodiscard]] constexpr std::size_t operator()() const noexcept { - std::size_t hash = shared_hash(type_kind::class_); + hash_composer hash{}; + hash << type_kind::class_; using traits = class_traits; - hash = shared_hash_append(hash, traits::make_flags()); + hash << traits::make_flags(); - hash = shared_hash_append(hash, shared_type_name{}()); + hash << shared_type_name{}(); - return hash; + return hash.hash; } }; template < shared_type_kind Class, shared_type_kind... Args > struct shared_type_hash { [[nodiscard]] constexpr std::size_t operator()() const noexcept { - std::size_t hash = shared_hash(type_kind::constructor_); + hash_composer hash{}; + hash << type_kind::constructor_; using traits = constructor_traits; - hash = shared_hash_append(hash, traits::make_flags()); + hash << traits::make_flags(); - hash = shared_hash_append(hash, shared_hash()); + hash << get_shared_hash(); traits::argument_types::for_each([&hash]() { // - hash = shared_hash_append(hash, shared_hash()); + hash << get_shared_hash(); }); - return hash; + return hash.hash; } }; template < shared_type_kind Class > struct shared_type_hash { [[nodiscard]] constexpr std::size_t operator()() const noexcept { - std::size_t hash = shared_hash(type_kind::destructor_); + hash_composer hash{}; + hash << type_kind::destructor_; using traits = destructor_traits; - hash = shared_hash_append(hash, traits::make_flags()); + hash << traits::make_flags(); - hash = shared_hash_append(hash, shared_hash()); + hash << get_shared_hash(); - return hash; + return hash.hash; } }; template < shared_type_kind Enum > struct shared_type_hash { [[nodiscard]] constexpr std::size_t operator()() const noexcept { - std::size_t hash = shared_hash(type_kind::enum_); + hash_composer hash{}; + hash << type_kind::enum_; using traits = enum_traits; - hash = shared_hash_append(hash, traits::make_flags()); + hash << traits::make_flags(); - hash = shared_hash_append(hash, shared_type_name{}()); + hash << shared_type_name{}(); - return hash; + return hash.hash; } }; template < shared_type_kind Function > struct shared_type_hash { [[nodiscard]] constexpr std::size_t operator()() const noexcept { - std::size_t hash = shared_hash(type_kind::function_); + hash_composer composer{}; + + composer << type_kind::function_; using traits = function_traits; - hash = shared_hash_append(hash, traits::make_flags()); + composer << traits::make_flags(); - hash = shared_hash_append(hash, shared_hash()); + composer << get_shared_hash(); - traits::argument_types::for_each([&hash]() { // - hash = shared_hash_append(hash, shared_hash()); + traits::argument_types::for_each([&composer]() { // + composer << get_shared_hash(); }); - return hash; + return composer.hash; } }; template < shared_type_kind Member > struct shared_type_hash { [[nodiscard]] constexpr std::size_t operator()() const noexcept { - std::size_t hash = shared_hash(type_kind::member_); + hash_composer hash{}; + hash << type_kind::member_; using traits = member_traits; - hash = shared_hash_append(hash, traits::make_flags()); + hash << traits::make_flags(); - hash = shared_hash_append(hash, shared_hash()); - hash = shared_hash_append(hash, shared_hash()); + hash << get_shared_hash(); + hash << get_shared_hash(); - return hash; + return hash.hash; } }; template < shared_type_kind Method > struct shared_type_hash { [[nodiscard]] constexpr std::size_t operator()() const noexcept { - std::size_t hash = shared_hash(type_kind::method_); + hash_composer hash{}; + hash << type_kind::method_; using traits = method_traits; - hash = shared_hash_append(hash, traits::make_flags()); + hash << traits::make_flags(); - hash = shared_hash_append(hash, shared_hash()); - hash = shared_hash_append(hash, shared_hash()); + hash << get_shared_hash(); + hash << get_shared_hash(); traits::argument_types::for_each([&hash]() { // - hash = shared_hash_append(hash, shared_hash()); + hash << get_shared_hash(); }); - return hash; + return hash.hash; } }; template < shared_type_kind Nullptr > struct shared_type_hash { [[nodiscard]] constexpr std::size_t operator()() const noexcept { - std::size_t hash = shared_hash(type_kind::nullptr_); + hash_composer hash{}; + hash << type_kind::nullptr_; - hash = shared_hash_append(hash, shared_type_name{}()); + hash << shared_type_name{}(); - return hash; + return hash.hash; } }; template < shared_type_kind Number > struct shared_type_hash { [[nodiscard]] constexpr std::size_t operator()() const noexcept { - std::size_t hash = shared_hash(type_kind::number_); + hash_composer hash{}; + hash << type_kind::number_; using traits = number_traits; - hash = shared_hash_append(hash, traits::make_flags()); + hash << traits::make_flags(); - hash = shared_hash_append(hash, shared_type_name{}()); + hash << shared_type_name{}(); - return hash; + return hash.hash; } }; template < shared_type_kind Pointer > struct shared_type_hash { [[nodiscard]] constexpr std::size_t operator()() const noexcept { - std::size_t hash = shared_hash(type_kind::pointer_); + hash_composer hash{}; + hash << type_kind::pointer_; using traits = pointer_traits; - hash = shared_hash_append(hash, traits::make_flags()); + hash << traits::make_flags(); - hash = shared_hash_append(hash, shared_hash()); + hash << get_shared_hash(); - return hash; + return hash.hash; } }; template < shared_type_kind Reference > struct shared_type_hash { [[nodiscard]] constexpr std::size_t operator()() const noexcept { - std::size_t hash = shared_hash(type_kind::reference_); + hash_composer hash{}; + hash << type_kind::reference_; using traits = reference_traits; - hash = shared_hash_append(hash, traits::make_flags()); + hash << traits::make_flags(); - hash = shared_hash_append(hash, shared_hash()); + hash << get_shared_hash(); - return hash; + return hash.hash; } }; template < shared_type_kind Void > struct shared_type_hash { [[nodiscard]] constexpr std::size_t operator()() const noexcept { - std::size_t hash = shared_hash(type_kind::void_); + hash_composer hash{}; + hash << type_kind::void_; - hash = shared_hash_append(hash, shared_type_name{}()); + hash << shared_type_name{}(); - return hash; + return hash.hash; } }; } @@ -6725,7 +6756,7 @@ namespace meta_hpp::detail template <> \ struct shared_type_name { \ [[nodiscard]] constexpr std::size_t operator()() const noexcept { \ - return hashed_string{Name}.get_hash(); \ + return hash_composer{} << std::string_view{Name}; \ } \ }; \ } @@ -10809,7 +10840,7 @@ namespace meta_hpp } inline std::size_t uerror::get_hash() const noexcept { - return detail::hash_combiner{}(error_); + return detail::hash_composer{} << error_; } } diff --git a/develop/unshared/meta_shared_exe/meta_shared_tests.cpp b/develop/unshared/meta_shared_exe/meta_shared_tests.cpp index 0ed4009..9163692 100644 --- a/develop/unshared/meta_shared_exe/meta_shared_tests.cpp +++ b/develop/unshared/meta_shared_exe/meta_shared_tests.cpp @@ -281,34 +281,34 @@ TEST_CASE("meta/meta_shared/tests") { SUBCASE("9") { using meta::detail::type_access; - using meta::detail::hash_combiner; + using meta::detail::hash_composer; - CHECK_FALSE(meta::resolve_type().get_id().get_hash() == hash_combiner{}(type_access(meta::resolve_type()))); - CHECK_FALSE(meta::resolve_type().get_id().get_hash() == hash_combiner{}(type_access(meta::resolve_type()))); - CHECK_FALSE(meta::resolve_type().get_id().get_hash() == hash_combiner{}(type_access(meta::resolve_type()))); - CHECK_FALSE(meta::resolve_type().get_id().get_hash() == hash_combiner{}(type_access(meta::resolve_type()))); - CHECK_FALSE(meta::resolve_type().get_id().get_hash() == hash_combiner{}(type_access(meta::resolve_type()))); - CHECK_FALSE(meta::resolve_type().get_id().get_hash() == hash_combiner{}(type_access(meta::resolve_type()))); - CHECK_FALSE(meta::resolve_type().get_id().get_hash() == hash_combiner{}(type_access(meta::resolve_type()))); - CHECK_FALSE(meta::resolve_type().get_id().get_hash() == hash_combiner{}(type_access(meta::resolve_type()))); - CHECK_FALSE(meta::resolve_type().get_id().get_hash() == hash_combiner{}(type_access(meta::resolve_type()))); - CHECK_FALSE(meta::resolve_type().get_id().get_hash() == hash_combiner{}(type_access(meta::resolve_type()))); - CHECK_FALSE(meta::resolve_type().get_id().get_hash() == hash_combiner{}(type_access(meta::resolve_type()))); + CHECK_FALSE(meta::resolve_type().get_id().get_hash() == hash_composer{} << type_access(meta::resolve_type())); + CHECK_FALSE(meta::resolve_type().get_id().get_hash() == hash_composer{} << type_access(meta::resolve_type())); + CHECK_FALSE(meta::resolve_type().get_id().get_hash() == hash_composer{} << type_access(meta::resolve_type())); + CHECK_FALSE(meta::resolve_type().get_id().get_hash() == hash_composer{} << type_access(meta::resolve_type())); + CHECK_FALSE(meta::resolve_type().get_id().get_hash() == hash_composer{} << type_access(meta::resolve_type())); + CHECK_FALSE(meta::resolve_type().get_id().get_hash() == hash_composer{} << type_access(meta::resolve_type())); + CHECK_FALSE(meta::resolve_type().get_id().get_hash() == hash_composer{} << type_access(meta::resolve_type())); + CHECK_FALSE(meta::resolve_type().get_id().get_hash() == hash_composer{} << type_access(meta::resolve_type())); + CHECK_FALSE(meta::resolve_type().get_id().get_hash() == hash_composer{} << type_access(meta::resolve_type())); + CHECK_FALSE(meta::resolve_type().get_id().get_hash() == hash_composer{} << type_access(meta::resolve_type())); + CHECK_FALSE(meta::resolve_type().get_id().get_hash() == hash_composer{} << type_access(meta::resolve_type())); - CHECK(meta::resolve_type().get_id().get_hash() == hash_combiner{}(type_access(meta::resolve_type()))); - CHECK(meta::resolve_type().get_id().get_hash() == hash_combiner{}(type_access(meta::resolve_type()))); - CHECK(meta::resolve_type().get_id().get_hash() == hash_combiner{}(type_access(meta::resolve_type()))); - CHECK(meta::resolve_type().get_id().get_hash() == hash_combiner{}(type_access(meta::resolve_type()))); - CHECK(meta::resolve_type().get_id().get_hash() == hash_combiner{}(type_access(meta::resolve_type()))); - CHECK(meta::resolve_type().get_id().get_hash() == hash_combiner{}(type_access(meta::resolve_type()))); - CHECK(meta::resolve_type().get_id().get_hash() == hash_combiner{}(type_access(meta::resolve_type()))); - CHECK(meta::resolve_type().get_id().get_hash() == hash_combiner{}(type_access(meta::resolve_type()))); - CHECK(meta::resolve_type().get_id().get_hash() == hash_combiner{}(type_access(meta::resolve_type()))); - CHECK(meta::resolve_type().get_id().get_hash() == hash_combiner{}(type_access(meta::resolve_type()))); - CHECK(meta::resolve_type().get_id().get_hash() == hash_combiner{}(type_access(meta::resolve_type()))); - CHECK(meta::resolve_type().get_id().get_hash() == hash_combiner{}(type_access(meta::resolve_type()))); - CHECK(meta::resolve_type().get_id().get_hash() == hash_combiner{}(type_access(meta::resolve_type()))); - CHECK(meta::resolve_type().get_id().get_hash() == hash_combiner{}(type_access(meta::resolve_type()))); + CHECK(meta::resolve_type().get_id().get_hash() == hash_composer{} << type_access(meta::resolve_type())); + CHECK(meta::resolve_type().get_id().get_hash() == hash_composer{} << type_access(meta::resolve_type())); + CHECK(meta::resolve_type().get_id().get_hash() == hash_composer{} << type_access(meta::resolve_type())); + CHECK(meta::resolve_type().get_id().get_hash() == hash_composer{} << type_access(meta::resolve_type())); + CHECK(meta::resolve_type().get_id().get_hash() == hash_composer{} << type_access(meta::resolve_type())); + CHECK(meta::resolve_type().get_id().get_hash() == hash_composer{} << type_access(meta::resolve_type())); + CHECK(meta::resolve_type().get_id().get_hash() == hash_composer{} << type_access(meta::resolve_type())); + CHECK(meta::resolve_type().get_id().get_hash() == hash_composer{} << type_access(meta::resolve_type())); + CHECK(meta::resolve_type().get_id().get_hash() == hash_composer{} << type_access(meta::resolve_type())); + CHECK(meta::resolve_type().get_id().get_hash() == hash_composer{} << type_access(meta::resolve_type())); + CHECK(meta::resolve_type().get_id().get_hash() == hash_composer{} << type_access(meta::resolve_type())); + CHECK(meta::resolve_type().get_id().get_hash() == hash_composer{} << type_access(meta::resolve_type())); + CHECK(meta::resolve_type().get_id().get_hash() == hash_composer{} << type_access(meta::resolve_type())); + CHECK(meta::resolve_type().get_id().get_hash() == hash_composer{} << type_access(meta::resolve_type())); } SUBCASE("10") { diff --git a/headers/meta.hpp/meta_base.hpp b/headers/meta.hpp/meta_base.hpp index cd69b64..55d2273 100644 --- a/headers/meta.hpp/meta_base.hpp +++ b/headers/meta.hpp/meta_base.hpp @@ -13,7 +13,7 @@ #include "meta_base/exceptions.hpp" #include "meta_base/fixed_function.hpp" #include "meta_base/fnv1a_hash.hpp" -#include "meta_base/hash_combiner.hpp" +#include "meta_base/hash_composer.hpp" #include "meta_base/hashed_string.hpp" #include "meta_base/insert_or_assign.hpp" #include "meta_base/is_in_place_type.hpp" diff --git a/headers/meta.hpp/meta_base/hash_combiner.hpp b/headers/meta.hpp/meta_base/hash_combiner.hpp deleted file mode 100644 index ed0674d..0000000 --- a/headers/meta.hpp/meta_base/hash_combiner.hpp +++ /dev/null @@ -1,33 +0,0 @@ -/******************************************************************************* - * This file is part of the "https://github.com/blackmatov/meta.hpp" - * For conditions of distribution and use, see copyright notice in LICENSE.md - * Copyright (C) 2021-2024, by Matvey Cherevko (blackmatov@gmail.com) - ******************************************************************************/ - -#pragma once - -#include "base.hpp" - -namespace meta_hpp::detail -{ - struct hash_combiner { - template < typename T > - [[nodiscard]] std::size_t operator()(const T& x) const noexcept { - return std::hash{}(x); - } - - template < typename T > - requires(sizeof(std::size_t) == sizeof(std::uint32_t)) - [[nodiscard]] std::size_t operator()(std::size_t seed, const T& x) const noexcept { - // NOLINTNEXTLINE(*-magic-numbers) - return (seed ^= std::hash{}(x) + 0x9e3779b9U + (seed << 6) + (seed >> 2)); - } - - template < typename T > - requires(sizeof(std::size_t) == sizeof(std::uint64_t)) - [[nodiscard]] std::size_t operator()(std::size_t seed, const T& x) const noexcept { - // NOLINTNEXTLINE(*-magic-numbers) - return (seed ^= std::hash{}(x) + 0x9e3779b97f4a7c15LLU + (seed << 12) + (seed >> 4)); - } - }; -} diff --git a/headers/meta.hpp/meta_base/hash_composer.hpp b/headers/meta.hpp/meta_base/hash_composer.hpp new file mode 100644 index 0000000..31a3e60 --- /dev/null +++ b/headers/meta.hpp/meta_base/hash_composer.hpp @@ -0,0 +1,76 @@ +/******************************************************************************* + * This file is part of the "https://github.com/blackmatov/meta.hpp" + * For conditions of distribution and use, see copyright notice in LICENSE.md + * Copyright (C) 2021-2024, by Matvey Cherevko (blackmatov@gmail.com) + ******************************************************************************/ + +#pragma once + +#include "base.hpp" +#include "bitflags.hpp" +#include "fnv1a_hash.hpp" +#include "hashed_string.hpp" + +namespace meta_hpp::detail +{ + template < std::size_t SizeBytes = sizeof(std::size_t) > + struct hash_composer_traits {}; + + template <> + struct hash_composer_traits { + [[nodiscard]] static constexpr std::size_t combine(std::size_t a, std::size_t b) noexcept { + // NOLINTNEXTLINE(*-magic-numbers) + return (a ^= b + 0x9e3779b9U + (a << 6) + (a >> 2)); + } + }; + + template <> + struct hash_composer_traits { + [[nodiscard]] static constexpr std::size_t combine(std::size_t a, std::size_t b) noexcept { + // NOLINTNEXTLINE(*-magic-numbers) + return (a ^= b + 0x9e3779b97f4a7c15LLU + (a << 12) + (a >> 4)); + } + }; + + struct hash_composer final : private hash_composer_traits<> { + std::size_t hash{fnv1a_hash_traits<>::prime}; + + constexpr operator std::size_t() const noexcept { + return hash; + } + + constexpr hash_composer operator<<(std::string_view value) noexcept { + hash = combine(hash, hashed_string{value}.get_hash()); + return *this; + } + + template < typename Pointer > + requires std::is_pointer_v + constexpr hash_composer operator<<(Pointer value) noexcept { + // NOLINTNEXTLINE(*-reinterpret-cast) + hash = combine(hash, reinterpret_cast(value)); + return *this; + } + + template < typename Integral > + requires(std::is_integral_v && sizeof(Integral) <= sizeof(std::size_t)) + constexpr hash_composer operator<<(Integral value) noexcept { + hash = combine(hash, static_cast(value)); + return *this; + } + + template < typename Enum > + requires(std::is_enum_v && sizeof(std::underlying_type_t) <= sizeof(std::size_t)) + constexpr hash_composer operator<<(Enum value) noexcept { + hash = combine(hash, static_cast(value)); + return *this; + } + + template < typename Enum > + requires(std::is_enum_v && sizeof(std::underlying_type_t) <= sizeof(std::size_t)) + constexpr hash_composer operator<<(bitflags value) noexcept { + hash = combine(hash, static_cast(value.as_raw())); + return *this; + } + }; +} diff --git a/headers/meta.hpp/meta_detail/type_sharing.hpp b/headers/meta.hpp/meta_detail/type_sharing.hpp index cdaa04c..fe88476 100644 --- a/headers/meta.hpp/meta_detail/type_sharing.hpp +++ b/headers/meta.hpp/meta_detail/type_sharing.hpp @@ -23,39 +23,9 @@ namespace meta_hpp::detail namespace meta_hpp::detail { template < typename Type > - [[nodiscard]] constexpr std::size_t shared_hash() noexcept { + [[nodiscard]] constexpr std::size_t get_shared_hash() noexcept { return shared_type_hash, Type>{}(); } - - template < enum_kind Enum > - [[nodiscard]] constexpr std::size_t shared_hash(Enum value) noexcept { - return static_cast(value); - } - - template < enum_kind Enum > - [[nodiscard]] constexpr std::size_t shared_hash(bitflags value) noexcept { - return static_cast(value.as_raw()); - } - - template < typename Integral > - requires(std::is_integral_v && sizeof(Integral) <= sizeof(std::size_t)) - [[nodiscard]] constexpr std::size_t shared_hash(Integral value) noexcept { - return static_cast(value); - } - - template < typename Value > - requires(sizeof(std::size_t) == sizeof(std::uint32_t)) - [[nodiscard]] constexpr std::size_t shared_hash_append(std::size_t seed, Value value) noexcept { - // NOLINTNEXTLINE(*-magic-numbers) - return (seed ^= shared_hash(value) + 0x9e3779b9U + (seed << 6) + (seed >> 2)); - } - - template < typename Value > - requires(sizeof(std::size_t) == sizeof(std::uint64_t)) - [[nodiscard]] constexpr std::size_t shared_hash_append(std::size_t seed, Value value) noexcept { - // NOLINTNEXTLINE(*-magic-numbers) - return (seed ^= shared_hash(value) + 0x9e3779b97f4a7c15LLU + (seed << 12) + (seed >> 4)); - } } namespace meta_hpp::detail @@ -72,7 +42,7 @@ namespace meta_hpp::detail template < type_kind, typename... > struct shared_type_data_hash { [[nodiscard]] std::size_t operator()(const void* type_data) const noexcept { - return hash_combiner{}(type_data); + return hash_composer{} << type_data; } }; @@ -126,192 +96,206 @@ namespace meta_hpp::detail template < shared_type_kind Array > struct shared_type_hash { [[nodiscard]] constexpr std::size_t operator()() const noexcept { - std::size_t hash = shared_hash(type_kind::array_); + hash_composer hash{}; + hash << type_kind::array_; using traits = array_traits; - hash = shared_hash_append(hash, traits::make_flags()); + hash << traits::make_flags(); - hash = shared_hash_append(hash, shared_hash()); + hash << get_shared_hash(); - hash = shared_hash_append(hash, traits::extent); + hash << traits::extent; - return hash; + return hash.hash; } }; template < shared_type_kind Class > struct shared_type_hash { [[nodiscard]] constexpr std::size_t operator()() const noexcept { - std::size_t hash = shared_hash(type_kind::class_); + hash_composer hash{}; + hash << type_kind::class_; using traits = class_traits; - hash = shared_hash_append(hash, traits::make_flags()); + hash << traits::make_flags(); - hash = shared_hash_append(hash, shared_type_name{}()); + hash << shared_type_name{}(); - return hash; + return hash.hash; } }; template < shared_type_kind Class, shared_type_kind... Args > struct shared_type_hash { [[nodiscard]] constexpr std::size_t operator()() const noexcept { - std::size_t hash = shared_hash(type_kind::constructor_); + hash_composer hash{}; + hash << type_kind::constructor_; using traits = constructor_traits; - hash = shared_hash_append(hash, traits::make_flags()); + hash << traits::make_flags(); - hash = shared_hash_append(hash, shared_hash()); + hash << get_shared_hash(); traits::argument_types::for_each([&hash]() { // - hash = shared_hash_append(hash, shared_hash()); + hash << get_shared_hash(); }); - return hash; + return hash.hash; } }; template < shared_type_kind Class > struct shared_type_hash { [[nodiscard]] constexpr std::size_t operator()() const noexcept { - std::size_t hash = shared_hash(type_kind::destructor_); + hash_composer hash{}; + hash << type_kind::destructor_; using traits = destructor_traits; - hash = shared_hash_append(hash, traits::make_flags()); + hash << traits::make_flags(); - hash = shared_hash_append(hash, shared_hash()); + hash << get_shared_hash(); - return hash; + return hash.hash; } }; template < shared_type_kind Enum > struct shared_type_hash { [[nodiscard]] constexpr std::size_t operator()() const noexcept { - std::size_t hash = shared_hash(type_kind::enum_); + hash_composer hash{}; + hash << type_kind::enum_; using traits = enum_traits; - hash = shared_hash_append(hash, traits::make_flags()); + hash << traits::make_flags(); - hash = shared_hash_append(hash, shared_type_name{}()); + hash << shared_type_name{}(); - return hash; + return hash.hash; } }; template < shared_type_kind Function > struct shared_type_hash { [[nodiscard]] constexpr std::size_t operator()() const noexcept { - std::size_t hash = shared_hash(type_kind::function_); + hash_composer composer{}; + + composer << type_kind::function_; using traits = function_traits; - hash = shared_hash_append(hash, traits::make_flags()); + composer << traits::make_flags(); - hash = shared_hash_append(hash, shared_hash()); + composer << get_shared_hash(); - traits::argument_types::for_each([&hash]() { // - hash = shared_hash_append(hash, shared_hash()); + traits::argument_types::for_each([&composer]() { // + composer << get_shared_hash(); }); - return hash; + return composer.hash; } }; template < shared_type_kind Member > struct shared_type_hash { [[nodiscard]] constexpr std::size_t operator()() const noexcept { - std::size_t hash = shared_hash(type_kind::member_); + hash_composer hash{}; + hash << type_kind::member_; using traits = member_traits; - hash = shared_hash_append(hash, traits::make_flags()); + hash << traits::make_flags(); - hash = shared_hash_append(hash, shared_hash()); - hash = shared_hash_append(hash, shared_hash()); + hash << get_shared_hash(); + hash << get_shared_hash(); - return hash; + return hash.hash; } }; template < shared_type_kind Method > struct shared_type_hash { [[nodiscard]] constexpr std::size_t operator()() const noexcept { - std::size_t hash = shared_hash(type_kind::method_); + hash_composer hash{}; + hash << type_kind::method_; using traits = method_traits; - hash = shared_hash_append(hash, traits::make_flags()); + hash << traits::make_flags(); - hash = shared_hash_append(hash, shared_hash()); - hash = shared_hash_append(hash, shared_hash()); + hash << get_shared_hash(); + hash << get_shared_hash(); traits::argument_types::for_each([&hash]() { // - hash = shared_hash_append(hash, shared_hash()); + hash << get_shared_hash(); }); - return hash; + return hash.hash; } }; template < shared_type_kind Nullptr > struct shared_type_hash { [[nodiscard]] constexpr std::size_t operator()() const noexcept { - std::size_t hash = shared_hash(type_kind::nullptr_); + hash_composer hash{}; + hash << type_kind::nullptr_; - hash = shared_hash_append(hash, shared_type_name{}()); + hash << shared_type_name{}(); - return hash; + return hash.hash; } }; template < shared_type_kind Number > struct shared_type_hash { [[nodiscard]] constexpr std::size_t operator()() const noexcept { - std::size_t hash = shared_hash(type_kind::number_); + hash_composer hash{}; + hash << type_kind::number_; using traits = number_traits; - hash = shared_hash_append(hash, traits::make_flags()); + hash << traits::make_flags(); - hash = shared_hash_append(hash, shared_type_name{}()); + hash << shared_type_name{}(); - return hash; + return hash.hash; } }; template < shared_type_kind Pointer > struct shared_type_hash { [[nodiscard]] constexpr std::size_t operator()() const noexcept { - std::size_t hash = shared_hash(type_kind::pointer_); + hash_composer hash{}; + hash << type_kind::pointer_; using traits = pointer_traits; - hash = shared_hash_append(hash, traits::make_flags()); + hash << traits::make_flags(); - hash = shared_hash_append(hash, shared_hash()); + hash << get_shared_hash(); - return hash; + return hash.hash; } }; template < shared_type_kind Reference > struct shared_type_hash { [[nodiscard]] constexpr std::size_t operator()() const noexcept { - std::size_t hash = shared_hash(type_kind::reference_); + hash_composer hash{}; + hash << type_kind::reference_; using traits = reference_traits; - hash = shared_hash_append(hash, traits::make_flags()); + hash << traits::make_flags(); - hash = shared_hash_append(hash, shared_hash()); + hash << get_shared_hash(); - return hash; + return hash.hash; } }; template < shared_type_kind Void > struct shared_type_hash { [[nodiscard]] constexpr std::size_t operator()() const noexcept { - std::size_t hash = shared_hash(type_kind::void_); + hash_composer hash{}; + hash << type_kind::void_; - hash = shared_hash_append(hash, shared_type_name{}()); + hash << shared_type_name{}(); - return hash; + return hash.hash; } }; } @@ -322,7 +306,7 @@ namespace meta_hpp::detail template <> \ struct shared_type_name { \ [[nodiscard]] constexpr std::size_t operator()() const noexcept { \ - return hashed_string{Name}.get_hash(); \ + return hash_composer{} << std::string_view{Name}; \ } \ }; \ } diff --git a/headers/meta.hpp/meta_indices/argument_index.hpp b/headers/meta.hpp/meta_indices/argument_index.hpp index 83bbd32..a08c824 100644 --- a/headers/meta.hpp/meta_indices/argument_index.hpp +++ b/headers/meta.hpp/meta_indices/argument_index.hpp @@ -30,6 +30,6 @@ namespace meta_hpp } inline std::size_t argument_index::get_hash() const noexcept { - return detail::hash_combiner{}(detail::hash_combiner{}(type_), position_); + return detail::hash_composer{} << type_.get_hash() << position_; } } diff --git a/headers/meta.hpp/meta_indices/constructor_index.hpp b/headers/meta.hpp/meta_indices/constructor_index.hpp index d6b9e62..d2d8443 100644 --- a/headers/meta.hpp/meta_indices/constructor_index.hpp +++ b/headers/meta.hpp/meta_indices/constructor_index.hpp @@ -24,6 +24,6 @@ namespace meta_hpp } inline std::size_t constructor_index::get_hash() const noexcept { - return detail::hash_combiner{}(type_); + return detail::hash_composer{} << type_.get_hash(); } } diff --git a/headers/meta.hpp/meta_indices/destructor_index.hpp b/headers/meta.hpp/meta_indices/destructor_index.hpp index a08ada3..f0e02e8 100644 --- a/headers/meta.hpp/meta_indices/destructor_index.hpp +++ b/headers/meta.hpp/meta_indices/destructor_index.hpp @@ -24,6 +24,6 @@ namespace meta_hpp } inline std::size_t destructor_index::get_hash() const noexcept { - return detail::hash_combiner{}(type_); + return detail::hash_composer{} << type_.get_hash(); } } diff --git a/headers/meta.hpp/meta_indices/evalue_index.hpp b/headers/meta.hpp/meta_indices/evalue_index.hpp index dc0bfee..b5ecb60 100644 --- a/headers/meta.hpp/meta_indices/evalue_index.hpp +++ b/headers/meta.hpp/meta_indices/evalue_index.hpp @@ -34,6 +34,6 @@ namespace meta_hpp } inline std::size_t evalue_index::get_hash() const noexcept { - return detail::hash_combiner{}(detail::hash_combiner{}(type_), name_); + return detail::hash_composer{} << type_.get_hash() << name_; } } diff --git a/headers/meta.hpp/meta_indices/function_index.hpp b/headers/meta.hpp/meta_indices/function_index.hpp index 555aa3b..61e4d19 100644 --- a/headers/meta.hpp/meta_indices/function_index.hpp +++ b/headers/meta.hpp/meta_indices/function_index.hpp @@ -34,6 +34,6 @@ namespace meta_hpp } inline std::size_t function_index::get_hash() const noexcept { - return detail::hash_combiner{}(detail::hash_combiner{}(type_), name_); + return detail::hash_composer{} << type_.get_hash() << name_; } } diff --git a/headers/meta.hpp/meta_indices/member_index.hpp b/headers/meta.hpp/meta_indices/member_index.hpp index d63cadb..3254a44 100644 --- a/headers/meta.hpp/meta_indices/member_index.hpp +++ b/headers/meta.hpp/meta_indices/member_index.hpp @@ -34,6 +34,6 @@ namespace meta_hpp } inline std::size_t member_index::get_hash() const noexcept { - return detail::hash_combiner{}(detail::hash_combiner{}(type_), name_); + return detail::hash_composer{} << type_.get_hash() << name_; } } diff --git a/headers/meta.hpp/meta_indices/method_index.hpp b/headers/meta.hpp/meta_indices/method_index.hpp index 3405ee4..3d9dc85 100644 --- a/headers/meta.hpp/meta_indices/method_index.hpp +++ b/headers/meta.hpp/meta_indices/method_index.hpp @@ -34,6 +34,6 @@ namespace meta_hpp } inline std::size_t method_index::get_hash() const noexcept { - return detail::hash_combiner{}(detail::hash_combiner{}(type_), name_); + return detail::hash_composer{} << type_.get_hash() << name_; } } diff --git a/headers/meta.hpp/meta_indices/scope_index.hpp b/headers/meta.hpp/meta_indices/scope_index.hpp index 6497a98..be8ecbe 100644 --- a/headers/meta.hpp/meta_indices/scope_index.hpp +++ b/headers/meta.hpp/meta_indices/scope_index.hpp @@ -28,6 +28,6 @@ namespace meta_hpp } inline std::size_t scope_index::get_hash() const noexcept { - return detail::hash_combiner{}(name_); + return detail::hash_composer{} << name_; } } diff --git a/headers/meta.hpp/meta_indices/variable_index.hpp b/headers/meta.hpp/meta_indices/variable_index.hpp index c34523b..a4c84a3 100644 --- a/headers/meta.hpp/meta_indices/variable_index.hpp +++ b/headers/meta.hpp/meta_indices/variable_index.hpp @@ -34,6 +34,6 @@ namespace meta_hpp } inline std::size_t variable_index::get_hash() const noexcept { - return detail::hash_combiner{}(detail::hash_combiner{}(type_), name_); + return detail::hash_composer{} << type_.get_hash() << name_; } } diff --git a/headers/meta.hpp/meta_types.hpp b/headers/meta.hpp/meta_types.hpp index b3b0463..92ff98a 100644 --- a/headers/meta.hpp/meta_types.hpp +++ b/headers/meta.hpp/meta_types.hpp @@ -79,6 +79,8 @@ namespace meta_hpp [[nodiscard]] bool is_valid() const noexcept; [[nodiscard]] explicit operator bool() const noexcept; + [[nodiscard]] std::size_t get_hash() const noexcept; + [[nodiscard]] id_type get_id() const noexcept; [[nodiscard]] type_kind get_kind() const noexcept; [[nodiscard]] const metadata_map& get_metadata() const noexcept; @@ -371,7 +373,7 @@ namespace std template < meta_hpp::type_family Type > struct hash { size_t operator()(const Type& type) const noexcept { - return type.is_valid() ? type.get_id().get_hash() : 0; + return type.get_hash(); } }; } @@ -646,6 +648,11 @@ namespace meta_hpp return is_valid(); } + template < type_family Type > + std::size_t type_base::get_hash() const noexcept { + return get_id().get_hash(); + } + template < type_family Type > typename type_base::id_type type_base::get_id() const noexcept { return id_type{data_}; diff --git a/headers/meta.hpp/meta_uresult/uresult.hpp b/headers/meta.hpp/meta_uresult/uresult.hpp index 64cbe93..e6d8afd 100644 --- a/headers/meta.hpp/meta_uresult/uresult.hpp +++ b/headers/meta.hpp/meta_uresult/uresult.hpp @@ -47,7 +47,7 @@ namespace meta_hpp } inline std::size_t uerror::get_hash() const noexcept { - return detail::hash_combiner{}(error_); + return detail::hash_composer{} << error_; } }