registry type holder

This commit is contained in:
BlackMATov
2021-07-01 05:51:11 +07:00
parent 8d5d57992b
commit 0a5c7d87d8
4 changed files with 281 additions and 0 deletions

View File

@@ -10,6 +10,7 @@
#include "meta_value.hpp"
#include "meta_registry.hpp"
#include "meta_type.hpp"
#include "meta_class.hpp"

View File

@@ -26,6 +26,7 @@ namespace meta_hpp
{
class value;
class registry;
class type;
class class_info;

View File

@@ -0,0 +1,108 @@
/*******************************************************************************
* 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, by Matvey Cherevko (blackmatov@gmail.com)
******************************************************************************/
#pragma once
#include "meta_fwd.hpp"
#include "meta_type.hpp"
#include "meta_class.hpp"
#include "meta_field.hpp"
#include "meta_function.hpp"
#include "meta_method.hpp"
#include "meta_namespace.hpp"
#include "meta_variable.hpp"
namespace meta_hpp
{
class registry {
public:
template < auto T >
std::optional<type> resolve() const {
const family_id fid = get_family_id<decltype(T)>();
return detail::find_opt(family_to_types_, fid);
}
template < typename T >
std::optional<type> resolve() const {
const family_id fid = get_family_id<T>();
return detail::find_opt(family_to_types_, fid);
}
template < typename T >
std::optional<type> resolve(const T&) const {
const family_id fid = get_family_id<T>();
return detail::find_opt(family_to_types_, fid);
}
template < typename... Internals >
registry& operator()(Internals&&...internals) {
(add_(std::forward<Internals>(internals)), ...);
return *this;
}
private:
void add_(const class_info& info) {
family_to_types_.emplace(info.fid(), info);
info.each_class([this](const class_info& internal){
add_(internal);
});
info.each_field([this](const field_info& internal){
add_(internal);
});
info.each_function([this](const function_info& internal){
add_(internal);
});
info.each_method([this](const method_info& internal){
add_(internal);
});
info.each_variable([this](const variable_info& internal){
add_(internal);
});
}
void add_(const field_info& info) {
family_to_types_.emplace(info.fid(), info);
}
void add_(const function_info& info) {
family_to_types_.emplace(info.fid(), info);
}
void add_(const method_info& info) {
family_to_types_.emplace(info.fid(), info);
}
void add_(const namespace_info& info) {
info.each_class([this](const class_info& internal){
add_(internal);
});
info.each_function([this](const function_info& internal){
add_(internal);
});
info.each_namespace([this](const namespace_info& internal){
add_(internal);
});
info.each_variable([this](const variable_info& internal){
add_(internal);
});
}
void add_(const variable_info& info) {
family_to_types_.emplace(info.fid(), info);
}
private:
std::map<family_id, type, std::less<>> family_to_types_;
};
}

View File

@@ -0,0 +1,171 @@
/*******************************************************************************
* 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, by Matvey Cherevko (blackmatov@gmail.com)
******************************************************************************/
#include <meta.hpp/meta_registry.hpp>
#include "doctest/doctest.hpp"
namespace
{
struct ivec2 {
int x{};
int y{};
static ivec2 zero;
int dot(ivec2 other) const {
return x * other.x + y * other.y;
}
};
struct ivec3 {
int x{};
int y{};
int z{};
static ivec3 zero;
int dot(ivec3 other) const {
return x * other.x + y * other.y + z * other.z;
}
};
ivec2 ivec2::zero{};
ivec3 ivec3::zero{};
ivec2 iadd2(ivec2 l, ivec2 r) {
return {l.x + r.x, l.y + r.y};
}
ivec3 iadd3(ivec3 l, ivec3 r) {
return {l.x + r.x, l.y + r.y, l.z + r.z};
}
}
TEST_CASE("meta/registry") {
namespace meta = meta_hpp;
using namespace std::string_literals;
auto registry = meta::registry{}(
meta::namespace_("vmath")(
meta::class_<ivec2>("ivec2")(
meta::field_<&ivec2::x>("x"),
meta::field_<&ivec2::y>("y"),
meta::method_<&ivec2::dot>("dot"),
meta::variable_<&ivec2::zero>("zero")
),
meta::class_<ivec3>("ivec3")(
meta::field_<&ivec3::x>("x"),
meta::field_<&ivec3::y>("y"),
meta::field_<&ivec3::z>("z"),
meta::method_<&ivec3::dot>("dot"),
meta::variable_<&ivec3::zero>("zero")
),
meta::function_<&iadd2>("iadd2"),
meta::function_<&iadd3>("iadd3")
)
);
SUBCASE("class_template") {
CHECK(registry.resolve<ivec2>());
const meta::type ivec2_type = registry.resolve<ivec2>().value();
CHECK(ivec2_type.is_class());
const meta::class_info& ivec2_info = ivec2_type.get_class_info();
CHECK(ivec2_info.id() == "ivec2");
}
SUBCASE("class_instance") {
ivec3 v3;
CHECK(registry.resolve(v3));
const meta::type ivec3_type = registry.resolve(v3).value();
CHECK(ivec3_type.is_class());
const meta::class_info& ivec3_info = ivec3_type.get_class_info();
CHECK(ivec3_info.id() == "ivec3");
}
SUBCASE("field_template") {
CHECK(registry.resolve<&ivec2::x>());
const meta::type ivec2_x_type = registry.resolve<&ivec2::x>().value();
CHECK(ivec2_x_type.is_field());
const meta::field_info& ivec2_x_info = ivec2_x_type.get_field_info();
CHECK(ivec2_x_info.id() == "x");
}
SUBCASE("field_instance") {
CHECK(registry.resolve(&ivec3::x));
const meta::type ivec3_x_type = registry.resolve<&ivec3::x>().value();
CHECK(ivec3_x_type.is_field());
const meta::field_info& ivec3_x_info = ivec3_x_type.get_field_info();
CHECK(ivec3_x_info.id() == "x");
}
SUBCASE("function_template") {
CHECK(registry.resolve<&iadd2>());
const meta::type iadd2_type = registry.resolve<&iadd2>().value();
CHECK(iadd2_type.is_function());
const meta::function_info& iadd2_info = iadd2_type.get_function_info();
CHECK(iadd2_info.id() == "iadd2");
}
SUBCASE("function_instance") {
CHECK(registry.resolve(&iadd3));
const meta::type iadd3_type = registry.resolve<&iadd3>().value();
CHECK(iadd3_type.is_function());
const meta::function_info& iadd3_info = iadd3_type.get_function_info();
CHECK(iadd3_info.id() == "iadd3");
}
SUBCASE("method_template") {
CHECK(registry.resolve<&ivec2::dot>());
const meta::type ivec2_dot_type = registry.resolve<&ivec2::dot>().value();
CHECK(ivec2_dot_type.is_method());
const meta::method_info& ivec2_dot_info = ivec2_dot_type.get_method_info();
CHECK(ivec2_dot_info.id() == "dot");
}
SUBCASE("method_instance") {
CHECK(registry.resolve(&ivec3::dot));
const meta::type ivec3_dot_type = registry.resolve<&ivec3::dot>().value();
CHECK(ivec3_dot_type.is_method());
const meta::method_info& ivec3_dot_info = ivec3_dot_type.get_method_info();
CHECK(ivec3_dot_info.id() == "dot");
}
SUBCASE("variable_template") {
CHECK(registry.resolve<&ivec2::zero>());
const meta::type ivec2_zero_type = registry.resolve<&ivec2::zero>().value();
CHECK(ivec2_zero_type.is_variable());
const meta::variable_info& ivec2_x_info = ivec2_zero_type.get_variable_info();
CHECK(ivec2_x_info.id() == "zero");
}
SUBCASE("variable_instance") {
CHECK(registry.resolve(&ivec3::zero));
const meta::type ivec3_zero_type = registry.resolve<&ivec3::zero>().value();
CHECK(ivec3_zero_type.is_variable());
const meta::variable_info& ivec3_x_info = ivec3_zero_type.get_variable_info();
CHECK(ivec3_x_info.id() == "zero");
}
}