std::hash for indices and types

This commit is contained in:
BlackMATov
2022-02-14 16:44:01 +07:00
parent bdae59b6a5
commit bbcbebd76e
16 changed files with 230 additions and 0 deletions

View File

@@ -37,6 +37,7 @@
#include "meta_base/enum_bitflags.hpp"
#include "meta_base/enum.hpp"
#include "meta_base/fixed_function.hpp"
#include "meta_base/hash_combiner.hpp"
#include "meta_base/noncopyable.hpp"
#include "meta_base/overloaded.hpp"
#include "meta_base/select_overload.hpp"

View File

@@ -0,0 +1,26 @@
/*******************************************************************************
* 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-2022, by Matvey Cherevko (blackmatov@gmail.com)
******************************************************************************/
#pragma once
#include <cstddef>
#include <functional>
namespace meta_hpp::detail
{
struct hash_combiner {
template < typename T >
[[nodiscard]] std::size_t operator()(const T& x) noexcept {
return std::hash<T>{}(x);
}
template < typename T >
[[nodiscard]] std::size_t operator()(std::size_t seed, const T& x) noexcept {
// NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers, readability-magic-numbers)
return (seed ^= std::hash<T>{}(x) + 0x9e3779b9 + (seed << 6) + (seed >> 2));
}
};
}

View File

@@ -60,3 +60,13 @@ namespace meta_hpp::detail
}
};
}
namespace std
{
template <>
struct hash<meta_hpp::detail::type_id> {
size_t operator()(const meta_hpp::detail::type_id& id) const noexcept {
return id.get_hash();
}
};
}

View File

@@ -0,0 +1,27 @@
/*******************************************************************************
* 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-2022, by Matvey Cherevko (blackmatov@gmail.com)
******************************************************************************/
#pragma once
#include "../meta_base.hpp"
namespace meta_hpp::detail
{
template < typename T >
inline constexpr bool is_index_family_v =
std::is_same_v<T, argument_index> ||
std::is_same_v<T, constructor_index> ||
std::is_same_v<T, destructor_index> ||
std::is_same_v<T, evalue_index> ||
std::is_same_v<T, function_index> ||
std::is_same_v<T, member_index> ||
std::is_same_v<T, method_index> ||
std::is_same_v<T, scope_index> ||
std::is_same_v<T, variable_index>;
template < typename T >
concept index_family = is_index_family_v<T>;
}

View File

@@ -9,11 +9,14 @@
#include "meta_base.hpp"
#include "meta_types.hpp"
#include "meta_detail/index_family.hpp"
namespace meta_hpp
{
class argument_index final {
public:
argument_index() = delete;
[[nodiscard]] std::size_t get_hash() const noexcept;
[[nodiscard]] const any_type& get_type() const noexcept;
[[nodiscard]] std::size_t get_position() const noexcept;
private:
@@ -32,6 +35,7 @@ namespace meta_hpp
class constructor_index final {
public:
constructor_index() = delete;
[[nodiscard]] std::size_t get_hash() const noexcept;
[[nodiscard]] const constructor_type& get_type() const noexcept;
private:
friend detail::constructor_state;
@@ -48,6 +52,7 @@ namespace meta_hpp
class destructor_index final {
public:
destructor_index() = delete;
[[nodiscard]] std::size_t get_hash() const noexcept;
[[nodiscard]] const destructor_type& get_type() const noexcept;
private:
friend detail::destructor_state;
@@ -64,6 +69,7 @@ namespace meta_hpp
class evalue_index final {
public:
evalue_index() = delete;
[[nodiscard]] std::size_t get_hash() const noexcept;
[[nodiscard]] const enum_type& get_type() const noexcept;
[[nodiscard]] const std::string& get_name() const noexcept;
private:
@@ -82,6 +88,7 @@ namespace meta_hpp
class function_index final {
public:
function_index() = delete;
[[nodiscard]] std::size_t get_hash() const noexcept;
[[nodiscard]] const function_type& get_type() const noexcept;
[[nodiscard]] const std::string& get_name() const noexcept;
private:
@@ -100,6 +107,7 @@ namespace meta_hpp
class member_index final {
public:
member_index() = delete;
[[nodiscard]] std::size_t get_hash() const noexcept;
[[nodiscard]] const member_type& get_type() const noexcept;
[[nodiscard]] const std::string& get_name() const noexcept;
private:
@@ -118,6 +126,7 @@ namespace meta_hpp
class method_index final {
public:
method_index() = delete;
[[nodiscard]] std::size_t get_hash() const noexcept;
[[nodiscard]] const method_type& get_type() const noexcept;
[[nodiscard]] const std::string& get_name() const noexcept;
private:
@@ -136,6 +145,7 @@ namespace meta_hpp
class scope_index final {
public:
scope_index() = delete;
[[nodiscard]] std::size_t get_hash() const noexcept;
[[nodiscard]] const std::string& get_name() const noexcept;
private:
friend detail::scope_state;
@@ -151,6 +161,7 @@ namespace meta_hpp
class variable_index final {
public:
variable_index() = delete;
[[nodiscard]] std::size_t get_hash() const noexcept;
[[nodiscard]] const pointer_type& get_type() const noexcept;
[[nodiscard]] const std::string& get_name() const noexcept;
private:
@@ -166,3 +177,13 @@ namespace meta_hpp
std::string name_;
};
}
namespace std
{
template < meta_hpp::detail::index_family T >
struct hash<T> {
size_t operator()(const T& t) const noexcept {
return t.get_hash();
}
};
}

View File

@@ -23,6 +23,10 @@ namespace meta_hpp
return argument_index{detail::resolve_type<Argument>(), position};
}
inline std::size_t argument_index::get_hash() const noexcept {
return detail::hash_combiner{}(detail::hash_combiner{}(type_), position_);
}
inline const any_type& argument_index::get_type() const noexcept {
return type_;
}

View File

@@ -22,6 +22,10 @@ namespace meta_hpp
return constructor_index{detail::resolve_constructor_type<Class, Args...>()};
}
inline std::size_t constructor_index::get_hash() const noexcept {
return detail::hash_combiner{}(type_);
}
inline const constructor_type& constructor_index::get_type() const noexcept {
return type_;
}

View File

@@ -22,6 +22,10 @@ namespace meta_hpp
return destructor_index{detail::resolve_destructor_type<Class>()};
}
inline std::size_t destructor_index::get_hash() const noexcept {
return detail::hash_combiner{}(type_);
}
inline const destructor_type& destructor_index::get_type() const noexcept {
return type_;
}

View File

@@ -23,6 +23,10 @@ namespace meta_hpp
return evalue_index{detail::resolve_type<Enum>(), std::move(name)};
}
inline std::size_t evalue_index::get_hash() const noexcept {
return detail::hash_combiner{}(detail::hash_combiner{}(type_), name_);
}
inline const enum_type& evalue_index::get_type() const noexcept {
return type_;
}

View File

@@ -23,6 +23,10 @@ namespace meta_hpp
return function_index{detail::resolve_type<Function>(), std::move(name)};
}
inline std::size_t function_index::get_hash() const noexcept {
return detail::hash_combiner{}(detail::hash_combiner{}(type_), name_);
}
inline const function_type& function_index::get_type() const noexcept {
return type_;
}

View File

@@ -23,6 +23,10 @@ namespace meta_hpp
return member_index{detail::resolve_type<Member>(), std::move(name)};
}
inline std::size_t member_index::get_hash() const noexcept {
return detail::hash_combiner{}(detail::hash_combiner{}(type_), name_);
}
inline const member_type& member_index::get_type() const noexcept {
return type_;
}

View File

@@ -23,6 +23,10 @@ namespace meta_hpp
return method_index{detail::resolve_type<Method>(), std::move(name)};
}
inline std::size_t method_index::get_hash() const noexcept {
return detail::hash_combiner{}(detail::hash_combiner{}(type_), name_);
}
inline const method_type& method_index::get_type() const noexcept {
return type_;
}

View File

@@ -21,6 +21,10 @@ namespace meta_hpp
return scope_index{std::move(name)};
}
inline std::size_t scope_index::get_hash() const noexcept {
return detail::hash_combiner{}(name_);
}
inline const std::string& scope_index::get_name() const noexcept {
return name_;
}

View File

@@ -23,6 +23,10 @@ namespace meta_hpp
return variable_index{detail::resolve_type<Pointer>(), std::move(name)};
}
inline std::size_t variable_index::get_hash() const noexcept {
return detail::hash_combiner{}(detail::hash_combiner{}(type_), name_);
}
inline const pointer_type& variable_index::get_type() const noexcept {
return type_;
}

View File

@@ -424,6 +424,16 @@ namespace meta_hpp
};
}
namespace std
{
template < meta_hpp::detail::type_family T >
struct hash<T> {
size_t operator()(const T& t) const noexcept {
return meta_hpp::detail::hash_combiner{}(t.get_id());
}
};
}
namespace meta_hpp
{
template < detail::type_family T, detail::type_family U >

View File

@@ -0,0 +1,99 @@
/*******************************************************************************
* 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-2022, by Matvey Cherevko (blackmatov@gmail.com)
******************************************************************************/
#include "../meta_untests.hpp"
namespace
{
const double pi_v{3.1415926536};
enum class color : unsigned {
red = 0xFF0000,
green = 0x00FF00,
blue = 0x0000FF,
};
struct ivec2 {
int x{};
int y{};
explicit ivec2(int v) : x{v}, y{v} {}
ivec2(int x, int y) : x{x}, y{y} {}
ivec2& add(const ivec2& other) noexcept {
x += other.x;
y += other.y;
return *this;
}
static ivec2 iadd(const ivec2& l, const ivec2& r) noexcept {
return {l.x + r.x, l.y + r.y};
}
};
}
TEST_CASE("meta/meta_utilities/hash") {
namespace meta = meta_hpp;
meta::enum_<color>()
.evalue_("red", color::red)
.evalue_("green", color::green)
.evalue_("blue", color::blue);
meta::class_<ivec2>()
.constructor_<int>()
.constructor_<int, int>()
.destructor_()
.member_("x", &ivec2::x)
.member_("y", &ivec2::y)
.method_("add", &ivec2::add)
.function_("iadd", &ivec2::iadd);
const meta::class_type ivec2_type = meta::resolve_type<ivec2>();
const meta::constructor ivec2_ctor = ivec2_type.get_constructor_with<int>();
const meta::destructor ivec2_dtor = ivec2_type.get_dtors().begin()->second;
const meta::function ivec2_function = ivec2_type.get_function("iadd");
const meta::argument ivec2_function_arg = ivec2_function.get_argument(0);
const meta::member ivec2_member = ivec2_type.get_member("x");
const meta::method ivec2_method = ivec2_type.get_method("add");
const meta::enum_type color_type = meta::resolve_type<color>();
const meta::evalue red_color = color_type.get_evalue("red");
const meta::scope local_scope = meta::local_scope_("local-scope")
.variable_("pi_v", &pi_v);
const meta::variable pi_variable = local_scope.get_variable("pi_v");
SUBCASE("index_family") {
std::hash<meta::argument_index>{}(ivec2_function_arg.get_index());
std::hash<meta::constructor_index>{}(ivec2_ctor.get_index());
std::hash<meta::destructor_index>{}(ivec2_dtor.get_index());
std::hash<meta::evalue_index>{}(red_color.get_index());
std::hash<meta::function_index>{}(ivec2_function.get_index());
std::hash<meta::member_index>{}(ivec2_member.get_index());
std::hash<meta::method_index>{}(ivec2_method.get_index());
std::hash<meta::scope_index>{}(local_scope.get_index());
std::hash<meta::variable_index>{}(pi_variable.get_index());
}
SUBCASE("type_family") {
std::hash<meta::any_type>{}(meta::resolve_type<ivec2>());
std::hash<meta::array_type>{}(meta::resolve_type<int[]>());
std::hash<meta::class_type>{}(meta::resolve_type<ivec2>());
std::hash<meta::constructor_type>{}(ivec2_ctor.get_type());
std::hash<meta::destructor_type>{}(ivec2_dtor.get_type());
std::hash<meta::enum_type>{}(red_color.get_type());
std::hash<meta::function_type>{}(ivec2_function.get_type());
std::hash<meta::member_type>{}(ivec2_member.get_type());
std::hash<meta::method_type>{}(ivec2_method.get_type());
std::hash<meta::nullptr_type>{}(meta::resolve_type<nullptr_t>());
std::hash<meta::number_type>{}(meta::resolve_type<int>());
std::hash<meta::pointer_type>{}(meta::resolve_type<int*>());
std::hash<meta::reference_type>{}(meta::resolve_type<int&>());
std::hash<meta::void_type>{}(meta::resolve_type<void>());
}
}