mirror of
https://github.com/BlackMATov/meta.hpp.git
synced 2025-12-14 11:40:35 +07:00
@@ -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"
|
||||
|
||||
26
headers/meta.hpp/meta_base/hash_combiner.hpp
Normal file
26
headers/meta.hpp/meta_base/hash_combiner.hpp
Normal 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));
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
27
headers/meta.hpp/meta_detail/index_family.hpp
Normal file
27
headers/meta.hpp/meta_detail/index_family.hpp
Normal 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>;
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
namespace meta_hpp
|
||||
{
|
||||
inline argument_index::argument_index(any_type type, std::size_t position)
|
||||
: type_{std::move(type)}
|
||||
: type_{type}
|
||||
, position_{position} {}
|
||||
|
||||
template < typename Argument >
|
||||
@@ -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_;
|
||||
}
|
||||
|
||||
@@ -15,13 +15,17 @@
|
||||
namespace meta_hpp
|
||||
{
|
||||
inline constructor_index::constructor_index(constructor_type type)
|
||||
: type_{std::move(type)} {}
|
||||
: type_{type} {}
|
||||
|
||||
template < detail::class_kind Class, typename... Args >
|
||||
constructor_index constructor_index::make() {
|
||||
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_;
|
||||
}
|
||||
|
||||
@@ -15,13 +15,17 @@
|
||||
namespace meta_hpp
|
||||
{
|
||||
inline destructor_index::destructor_index(destructor_type type)
|
||||
: type_{std::move(type)} {}
|
||||
: type_{type} {}
|
||||
|
||||
template < detail::class_kind Class >
|
||||
destructor_index destructor_index::make() {
|
||||
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_;
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
namespace meta_hpp
|
||||
{
|
||||
inline evalue_index::evalue_index(enum_type type, std::string name)
|
||||
: type_{std::move(type)}
|
||||
: type_{type}
|
||||
, name_{std::move(name)} {}
|
||||
|
||||
template < detail::enum_kind Enum >
|
||||
@@ -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_;
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
namespace meta_hpp
|
||||
{
|
||||
inline function_index::function_index(function_type type, std::string name)
|
||||
: type_{std::move(type)}
|
||||
: type_{type}
|
||||
, name_{std::move(name)} {}
|
||||
|
||||
template < detail::function_kind Function >
|
||||
@@ -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_;
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
namespace meta_hpp
|
||||
{
|
||||
inline member_index::member_index(member_type type, std::string name)
|
||||
: type_{std::move(type)}
|
||||
: type_{type}
|
||||
, name_{std::move(name)} {}
|
||||
|
||||
template < detail::member_kind Member >
|
||||
@@ -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_;
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
namespace meta_hpp
|
||||
{
|
||||
inline method_index::method_index(method_type type, std::string name)
|
||||
: type_{std::move(type)}
|
||||
: type_{type}
|
||||
, name_{std::move(name)} {}
|
||||
|
||||
template < detail::method_kind Method >
|
||||
@@ -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_;
|
||||
}
|
||||
|
||||
@@ -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_;
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
namespace meta_hpp
|
||||
{
|
||||
inline variable_index::variable_index(pointer_type type, std::string name)
|
||||
: type_{std::move(type)}
|
||||
: type_{type}
|
||||
, name_{std::move(name)} {}
|
||||
|
||||
template < detail::pointer_kind Pointer >
|
||||
@@ -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_;
|
||||
}
|
||||
|
||||
@@ -156,8 +156,8 @@ namespace meta_hpp
|
||||
[[nodiscard]] const std::vector<any_type>& get_argument_types() const noexcept;
|
||||
|
||||
[[nodiscard]] const class_set& get_bases() const noexcept;
|
||||
[[nodiscard]] const constructor_map& get_ctors() const noexcept;
|
||||
[[nodiscard]] const destructor_map& get_dtors() const noexcept;
|
||||
[[nodiscard]] const constructor_map& get_constructors() const noexcept;
|
||||
[[nodiscard]] const destructor_map& get_destructors() const noexcept;
|
||||
[[nodiscard]] const function_map& get_functions() const noexcept;
|
||||
[[nodiscard]] const member_map& get_members() const noexcept;
|
||||
[[nodiscard]] const method_map& get_methods() const noexcept;
|
||||
@@ -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 >
|
||||
|
||||
@@ -77,11 +77,11 @@ namespace meta_hpp
|
||||
return data_->bases;
|
||||
}
|
||||
|
||||
inline const constructor_map& class_type::get_ctors() const noexcept {
|
||||
inline const constructor_map& class_type::get_constructors() const noexcept {
|
||||
return data_->constructors;
|
||||
}
|
||||
|
||||
inline const destructor_map& class_type::get_dtors() const noexcept {
|
||||
inline const destructor_map& class_type::get_destructors() const noexcept {
|
||||
return data_->destructors;
|
||||
}
|
||||
|
||||
|
||||
@@ -183,11 +183,11 @@ TEST_CASE("meta/meta_types/class_type") {
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("get_ctors") {
|
||||
CHECK(base_clazz_1_type.get_ctors().size() == 1);
|
||||
CHECK(base_clazz_2_type.get_ctors().size() == 1);
|
||||
CHECK(derived_clazz_type.get_ctors().size() == 1);
|
||||
CHECK(final_derived_clazz_type.get_ctors().size() == 1);
|
||||
SUBCASE("get_constructors") {
|
||||
CHECK(base_clazz_1_type.get_constructors().size() == 1);
|
||||
CHECK(base_clazz_2_type.get_constructors().size() == 1);
|
||||
CHECK(derived_clazz_type.get_constructors().size() == 1);
|
||||
CHECK(final_derived_clazz_type.get_constructors().size() == 1);
|
||||
}
|
||||
|
||||
SUBCASE("get_bases") {
|
||||
|
||||
99
untests/meta_utilities/hash_tests.cpp
Normal file
99
untests/meta_utilities/hash_tests.cpp
Normal 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_destructors().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<std::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>());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user