separate info and registry classes

This commit is contained in:
BlackMATov
2021-06-30 02:37:45 +07:00
parent d1c9bc40d8
commit bcd0c3ec77
19 changed files with 645 additions and 678 deletions

View File

@@ -9,11 +9,21 @@
#include "meta_fwd.hpp"
#include "meta_value.hpp"
#include "meta_registry.hpp"
#include "meta_class.hpp"
#include "meta_class_info.hpp"
#include "meta_field.hpp"
#include "meta_field_info.hpp"
#include "meta_function.hpp"
#include "meta_function_info.hpp"
#include "meta_method.hpp"
#include "meta_method_info.hpp"
#include "meta_namespace.hpp"
#include "meta_namespace_info.hpp"
#include "meta_variable.hpp"
#include "meta_variable_info.hpp"

View File

@@ -8,70 +8,7 @@
#include "meta_fwd.hpp"
#include "meta_field.hpp"
#include "meta_function.hpp"
#include "meta_method.hpp"
#include "meta_variable.hpp"
namespace meta_hpp
{
class class_info {
public:
class_info() = delete;
class_info(class_info&&) = default;
class_info(const class_info&) = default;
class_info& operator=(class_info&&) = default;
class_info& operator=(const class_info&) = default;
class_info(std::string id)
: id_(std::move(id)) {}
const std::string& id() const noexcept {
return id_;
}
std::optional<class_info> get_class(std::string_view id) const {
return detail::find_opt(classes_, id);
}
std::optional<field_info> get_field(std::string_view id) const {
return detail::find_opt(fields_, id);
}
std::optional<function_info> get_function(std::string_view id) const {
return detail::find_opt(functions_, id);
}
std::optional<method_info> get_method(std::string_view id) const {
return detail::find_opt(methods_, id);
}
std::optional<variable_info> get_variable(std::string_view id) const {
return detail::find_opt(variables_, id);
}
private:
friend class namespace_info;
template < typename Class > friend class class_;
friend class namespace_;
private:
void merge_with_(const class_info& other) {
detail::merge_with(classes_, other.classes_, &class_info::merge_with_);
detail::merge_with(fields_, other.fields_, &field_info::merge_with_);
detail::merge_with(functions_, other.functions_, &function_info::merge_with_);
detail::merge_with(methods_, other.methods_, &method_info::merge_with_);
detail::merge_with(variables_, other.variables_, &variable_info::merge_with_);
}
private:
std::string id_;
std::map<std::string, class_info, std::less<>> classes_;
std::map<std::string, field_info, std::less<>> fields_;
std::map<std::string, function_info, std::less<>> functions_;
std::map<std::string, method_info, std::less<>> methods_;
std::map<std::string, variable_info, std::less<>> variables_;
};
}
#include "meta_class_info.hpp"
namespace meta_hpp
{

View File

@@ -0,0 +1,74 @@
/*******************************************************************************
* 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_field_info.hpp"
#include "meta_function_info.hpp"
#include "meta_method_info.hpp"
#include "meta_variable_info.hpp"
namespace meta_hpp
{
class class_info {
public:
class_info() = delete;
class_info(class_info&&) = default;
class_info(const class_info&) = default;
class_info& operator=(class_info&&) = default;
class_info& operator=(const class_info&) = default;
class_info(std::string id)
: id_(std::move(id)) {}
const std::string& id() const noexcept {
return id_;
}
std::optional<class_info> get_class(std::string_view id) const {
return detail::find_opt(classes_, id);
}
std::optional<field_info> get_field(std::string_view id) const {
return detail::find_opt(fields_, id);
}
std::optional<function_info> get_function(std::string_view id) const {
return detail::find_opt(functions_, id);
}
std::optional<method_info> get_method(std::string_view id) const {
return detail::find_opt(methods_, id);
}
std::optional<variable_info> get_variable(std::string_view id) const {
return detail::find_opt(variables_, id);
}
private:
friend class namespace_info;
template < typename Class > friend class class_;
friend class namespace_;
private:
void merge_with_(const class_info& other) {
detail::merge_with(classes_, other.classes_, &class_info::merge_with_);
detail::merge_with(fields_, other.fields_, &field_info::merge_with_);
detail::merge_with(functions_, other.functions_, &function_info::merge_with_);
detail::merge_with(methods_, other.methods_, &method_info::merge_with_);
detail::merge_with(variables_, other.variables_, &variable_info::merge_with_);
}
private:
std::string id_;
std::map<std::string, class_info, std::less<>> classes_;
std::map<std::string, field_info, std::less<>> fields_;
std::map<std::string, function_info, std::less<>> functions_;
std::map<std::string, method_info, std::less<>> methods_;
std::map<std::string, variable_info, std::less<>> variables_;
};
}

View File

@@ -8,94 +8,7 @@
#include "meta_fwd.hpp"
#include "meta_value.hpp"
namespace meta_hpp::field_detail
{
template < typename Field >
struct field_traits;
template < typename T, typename Base >
struct field_traits<T Base::*> {
static constexpr bool is_const = false;
using value_type = T;
using instance_type = Base;
};
template < typename T, typename Base >
struct field_traits<const T Base::*>
: field_traits<T Base::*> {
static constexpr bool is_const = true;
};
template < auto Field >
value getter(const void* instance) {
using ft = field_traits<decltype(Field)>;
using value_type = typename ft::value_type;
using instance_type = typename ft::instance_type;
auto instance_ptr = static_cast<const instance_type*>(instance);
value_type typed_value = std::invoke(Field, *instance_ptr);
return value{std::move(typed_value)};
}
template < auto Field >
void setter([[maybe_unused]] void* instance, value value) {
using ft = field_traits<decltype(Field)>;
using value_type = typename ft::value_type;
using instance_type = typename ft::instance_type;
if constexpr ( !ft::is_const ) {
auto instance_ptr = static_cast<instance_type*>(instance);
std::invoke(Field, *instance_ptr) = value.cast<value_type>();
} else {
throw std::logic_error("an attempt to change a constant field");
}
}
}
namespace meta_hpp
{
class field_info {
public:
field_info() = delete;
field_info(field_info&&) = default;
field_info(const field_info&) = default;
field_info& operator=(field_info&&) = default;
field_info& operator=(const field_info&) = default;
field_info(std::string id)
: id_(std::move(id)) {}
const std::string& id() const noexcept {
return id_;
}
public:
value get(const void* instance) const {
return getter_(instance);
}
template < typename Value >
void set(void* instance, Value&& value) const {
return setter_(instance, std::forward<Value>(value));
}
private:
friend class class_info;
template < typename Class > friend class class_;
template < auto Field > friend class field_;
private:
void merge_with_(const field_info& other) {
(void)other;
}
private:
std::string id_;
value(*getter_)(const void*);
void(*setter_)(void*, value);
};
}
#include "meta_field_info.hpp"
namespace meta_hpp
{

View File

@@ -0,0 +1,98 @@
/*******************************************************************************
* 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_value.hpp"
namespace meta_hpp::field_detail
{
template < typename Field >
struct field_traits;
template < typename T, typename Base >
struct field_traits<T Base::*> {
static constexpr bool is_const = false;
using value_type = T;
using instance_type = Base;
};
template < typename T, typename Base >
struct field_traits<const T Base::*>
: field_traits<T Base::*> {
static constexpr bool is_const = true;
};
template < auto Field >
value getter(const void* instance) {
using ft = field_traits<decltype(Field)>;
using value_type = typename ft::value_type;
using instance_type = typename ft::instance_type;
auto instance_ptr = static_cast<const instance_type*>(instance);
value_type typed_value = std::invoke(Field, *instance_ptr);
return value{std::move(typed_value)};
}
template < auto Field >
void setter([[maybe_unused]] void* instance, value value) {
using ft = field_traits<decltype(Field)>;
using value_type = typename ft::value_type;
using instance_type = typename ft::instance_type;
if constexpr ( !ft::is_const ) {
auto instance_ptr = static_cast<instance_type*>(instance);
std::invoke(Field, *instance_ptr) = value.cast<value_type>();
} else {
throw std::logic_error("an attempt to change a constant field");
}
}
}
namespace meta_hpp
{
class field_info {
public:
field_info() = delete;
field_info(field_info&&) = default;
field_info(const field_info&) = default;
field_info& operator=(field_info&&) = default;
field_info& operator=(const field_info&) = default;
field_info(std::string id)
: id_(std::move(id)) {}
const std::string& id() const noexcept {
return id_;
}
public:
value get(const void* instance) const {
return getter_(instance);
}
template < typename Value >
void set(void* instance, Value&& value) const {
return setter_(instance, std::forward<Value>(value));
}
private:
friend class class_info;
template < typename Class > friend class class_;
template < auto Field > friend class field_;
private:
void merge_with_(const field_info& other) {
(void)other;
}
private:
std::string id_;
value(*getter_)(const void*);
void(*setter_)(void*, value);
};
}

View File

@@ -8,101 +8,7 @@
#include "meta_fwd.hpp"
#include "meta_value.hpp"
namespace meta_hpp::function_detail
{
template < typename Function >
struct function_traits;
template < typename R, typename... Args >
struct function_traits<R(*)(Args...)> {
static constexpr std::size_t arity = sizeof...(Args);
using return_type = R;
using argument_types = std::tuple<Args...>;
};
template < typename R, typename... Args >
struct function_traits<R(*)(Args...) noexcept>
: function_traits<R(*)(Args...)> {};
template < auto Function, std::size_t... Is >
value invoke(value* args, std::index_sequence<Is...>) {
using ft = function_traits<decltype(Function)>;
using return_type = typename ft::return_type;
using argument_types = typename ft::argument_types;
[[maybe_unused]] auto typed_arguments = std::make_tuple(
(args + Is)->try_cast<std::tuple_element_t<Is, argument_types>>()...);
if ( !(std::get<Is>(typed_arguments) && ...) ) {
throw std::logic_error("an attempt to call a function with incorrect argument types");
}
if constexpr ( std::is_void_v<return_type> ) {
std::invoke(Function,
*std::get<Is>(typed_arguments)...);
return value{};
} else {
return_type return_value = std::invoke(Function,
*std::get<Is>(typed_arguments)...);
return value{std::move(return_value)};
}
}
template < auto Function >
value invoke(value* args, std::size_t arg_count) {
using ft = function_traits<decltype(Function)>;
if ( arg_count != ft::arity ) {
throw std::logic_error("an attempt to call a function with an incorrect arity");
}
return invoke<Function>(args, std::make_index_sequence<ft::arity>());
}
}
namespace meta_hpp
{
class function_info {
public:
function_info() = delete;
function_info(function_info&&) = default;
function_info(const function_info&) = default;
function_info& operator=(function_info&&) = default;
function_info& operator=(const function_info&) = default;
function_info(std::string id)
: id_(std::move(id)) {}
const std::string& id() const noexcept {
return id_;
}
public:
template < typename... Args >
value invoke(Args&&... args) const {
std::array<value, sizeof...(Args)> vargs{{std::forward<Args>(args)...}};
return invoke_(vargs.data(), vargs.size());
}
private:
friend class class_info;
friend class namespace_info;
template < typename Class > friend class class_;
friend class namespace_;
template < auto Function > friend class function_;
private:
void merge_with_(const function_info& other) {
(void)other;
}
private:
std::string id_;
value(*invoke_)(value*, std::size_t);
};
}
#include "meta_function_info.hpp"
namespace meta_hpp
{

View File

@@ -0,0 +1,105 @@
/*******************************************************************************
* 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_value.hpp"
namespace meta_hpp::function_detail
{
template < typename Function >
struct function_traits;
template < typename R, typename... Args >
struct function_traits<R(*)(Args...)> {
static constexpr std::size_t arity = sizeof...(Args);
using return_type = R;
using argument_types = std::tuple<Args...>;
};
template < typename R, typename... Args >
struct function_traits<R(*)(Args...) noexcept>
: function_traits<R(*)(Args...)> {};
template < auto Function, std::size_t... Is >
value invoke(value* args, std::index_sequence<Is...>) {
using ft = function_traits<decltype(Function)>;
using return_type = typename ft::return_type;
using argument_types = typename ft::argument_types;
[[maybe_unused]] auto typed_arguments = std::make_tuple(
(args + Is)->try_cast<std::tuple_element_t<Is, argument_types>>()...);
if ( !(std::get<Is>(typed_arguments) && ...) ) {
throw std::logic_error("an attempt to call a function with incorrect argument types");
}
if constexpr ( std::is_void_v<return_type> ) {
std::invoke(Function,
*std::get<Is>(typed_arguments)...);
return value{};
} else {
return_type return_value = std::invoke(Function,
*std::get<Is>(typed_arguments)...);
return value{std::move(return_value)};
}
}
template < auto Function >
value invoke(value* args, std::size_t arg_count) {
using ft = function_traits<decltype(Function)>;
if ( arg_count != ft::arity ) {
throw std::logic_error("an attempt to call a function with an incorrect arity");
}
return invoke<Function>(args, std::make_index_sequence<ft::arity>());
}
}
namespace meta_hpp
{
class function_info {
public:
function_info() = delete;
function_info(function_info&&) = default;
function_info(const function_info&) = default;
function_info& operator=(function_info&&) = default;
function_info& operator=(const function_info&) = default;
function_info(std::string id)
: id_(std::move(id)) {}
const std::string& id() const noexcept {
return id_;
}
public:
template < typename... Args >
value invoke(Args&&... args) const {
std::array<value, sizeof...(Args)> vargs{{std::forward<Args>(args)...}};
return invoke_(vargs.data(), vargs.size());
}
private:
friend class class_info;
friend class namespace_info;
template < typename Class > friend class class_;
friend class namespace_;
template < auto Function > friend class function_;
private:
void merge_with_(const function_info& other) {
(void)other;
}
private:
std::string id_;
value(*invoke_)(value*, std::size_t);
};
}

View File

@@ -21,7 +21,6 @@
namespace meta_hpp
{
class value;
class registry;
class class_info;
class field_info;

View File

@@ -8,161 +8,7 @@
#include "meta_fwd.hpp"
#include "meta_value.hpp"
namespace meta_hpp::method_detail
{
template < typename Method >
struct method_traits;
template < typename R, typename Base, typename... Args >
struct method_traits<R(Base::*)(Args...)> {
static constexpr bool is_const = false;
static constexpr std::size_t arity = sizeof...(Args);
using return_type = R;
using instance_type = Base;
using argument_types = std::tuple<Args...>;
};
template < typename R, typename Base, typename... Args >
struct method_traits<R(Base::*)(Args...) const>
: method_traits<R(Base::*)(Args...)> {
static constexpr bool is_const = true;
};
template < typename R, typename Base, typename... Args >
struct method_traits<R(Base::*)(Args...) noexcept>
: method_traits<R(Base::*)(Args...)> {};
template < typename R, typename Base, typename... Args >
struct method_traits<R(Base::*)(Args...) const noexcept>
: method_traits<R(Base::*)(Args...) const> {};
template < auto Method, std::size_t... Is >
value invoke([[maybe_unused]] void* instance, value* args, std::index_sequence<Is...>) {
using mt = method_traits<decltype(Method)>;
using return_type = typename mt::return_type;
using instance_type = typename mt::instance_type;
using argument_types = typename mt::argument_types;
[[maybe_unused]] auto typed_arguments = std::make_tuple(
(args + Is)->try_cast<std::tuple_element_t<Is, argument_types>>()...);
if ( !(std::get<Is>(typed_arguments) && ...) ) {
throw std::logic_error("an attempt to call a method with incorrect argument types");
}
if constexpr ( std::is_void_v<return_type> ) {
std::invoke(Method,
std::ref(*static_cast<instance_type*>(instance)),
*std::get<Is>(typed_arguments)...);
return value{};
} else {
return_type return_value = std::invoke(Method,
std::ref(*static_cast<instance_type*>(instance)),
*std::get<Is>(typed_arguments)...);
return value{std::move(return_value)};
}
}
template < auto Method >
value invoke(void* instance, value* args, std::size_t arg_count) {
using mt = method_traits<decltype(Method)>;
if ( arg_count != mt::arity ) {
throw std::logic_error("an attempt to call a method with an incorrect arity");
}
return invoke<Method>(instance, args, std::make_index_sequence<mt::arity>());
}
template < auto Method, std::size_t... Is >
value cinvoke([[maybe_unused]] const void* instance, value* args, std::index_sequence<Is...>) {
using mt = method_traits<decltype(Method)>;
using return_type = typename mt::return_type;
using instance_type = typename mt::instance_type;
using argument_types = typename mt::argument_types;
[[maybe_unused]] auto typed_arguments = std::make_tuple(
(args + Is)->try_cast<std::tuple_element_t<Is, argument_types>>()...);
if ( !(std::get<Is>(typed_arguments) && ...) ) {
throw std::logic_error("an attempt to call a method with incorrect argument types");
}
if constexpr ( mt::is_const ) {
if constexpr ( std::is_void_v<return_type> ) {
std::invoke(Method,
std::ref(*static_cast<const instance_type*>(instance)),
*std::get<Is>(typed_arguments)...);
return value{};
} else {
return_type return_value = std::invoke(Method,
std::ref(*static_cast<const instance_type*>(instance)),
*std::get<Is>(typed_arguments)...);
return value{std::move(return_value)};
}
} else {
throw std::logic_error("an attempt to call a non-constant method by constant instance");
}
}
template < auto Method >
value cinvoke(const void* instance, value* args, std::size_t arg_count) {
using mt = method_traits<decltype(Method)>;
if ( arg_count != mt::arity ) {
throw std::logic_error("an attempt to call a method with a different arity");
}
return cinvoke<Method>(instance, args, std::make_index_sequence<mt::arity>());
}
}
namespace meta_hpp
{
class method_info {
public:
method_info() = delete;
method_info(method_info&&) = default;
method_info(const method_info&) = default;
method_info& operator=(method_info&&) = default;
method_info& operator=(const method_info&) = default;
method_info(std::string id)
: id_(std::move(id)) {}
const std::string& id() const noexcept {
return id_;
}
public:
template < typename... Args >
value invoke(void* instance, Args&&... args) const {
std::array<value, sizeof...(Args)> vargs{{std::forward<Args>(args)...}};
return invoke_(instance, vargs.data(), vargs.size());
}
template < typename... Args >
value invoke(const void* instance, Args&&... args) const {
std::array<value, sizeof...(Args)> vargs{{std::forward<Args>(args)...}};
return cinvoke_(instance, vargs.data(), vargs.size());
}
private:
friend class class_info;
template < typename Class > friend class class_;
template < auto Method > friend class method_;
private:
void merge_with_(const method_info& other) {
(void)other;
}
private:
std::string id_;
value(*invoke_)(void*, value*, std::size_t);
value(*cinvoke_)(const void*, value*, std::size_t);
};
}
#include "meta_method_info.hpp"
namespace meta_hpp
{

View File

@@ -0,0 +1,165 @@
/*******************************************************************************
* 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_value.hpp"
namespace meta_hpp::method_detail
{
template < typename Method >
struct method_traits;
template < typename R, typename Base, typename... Args >
struct method_traits<R(Base::*)(Args...)> {
static constexpr bool is_const = false;
static constexpr std::size_t arity = sizeof...(Args);
using return_type = R;
using instance_type = Base;
using argument_types = std::tuple<Args...>;
};
template < typename R, typename Base, typename... Args >
struct method_traits<R(Base::*)(Args...) const>
: method_traits<R(Base::*)(Args...)> {
static constexpr bool is_const = true;
};
template < typename R, typename Base, typename... Args >
struct method_traits<R(Base::*)(Args...) noexcept>
: method_traits<R(Base::*)(Args...)> {};
template < typename R, typename Base, typename... Args >
struct method_traits<R(Base::*)(Args...) const noexcept>
: method_traits<R(Base::*)(Args...) const> {};
template < auto Method, std::size_t... Is >
value invoke([[maybe_unused]] void* instance, value* args, std::index_sequence<Is...>) {
using mt = method_traits<decltype(Method)>;
using return_type = typename mt::return_type;
using instance_type = typename mt::instance_type;
using argument_types = typename mt::argument_types;
[[maybe_unused]] auto typed_arguments = std::make_tuple(
(args + Is)->try_cast<std::tuple_element_t<Is, argument_types>>()...);
if ( !(std::get<Is>(typed_arguments) && ...) ) {
throw std::logic_error("an attempt to call a method with incorrect argument types");
}
if constexpr ( std::is_void_v<return_type> ) {
std::invoke(Method,
std::ref(*static_cast<instance_type*>(instance)),
*std::get<Is>(typed_arguments)...);
return value{};
} else {
return_type return_value = std::invoke(Method,
std::ref(*static_cast<instance_type*>(instance)),
*std::get<Is>(typed_arguments)...);
return value{std::move(return_value)};
}
}
template < auto Method >
value invoke(void* instance, value* args, std::size_t arg_count) {
using mt = method_traits<decltype(Method)>;
if ( arg_count != mt::arity ) {
throw std::logic_error("an attempt to call a method with an incorrect arity");
}
return invoke<Method>(instance, args, std::make_index_sequence<mt::arity>());
}
template < auto Method, std::size_t... Is >
value cinvoke([[maybe_unused]] const void* instance, value* args, std::index_sequence<Is...>) {
using mt = method_traits<decltype(Method)>;
using return_type = typename mt::return_type;
using instance_type = typename mt::instance_type;
using argument_types = typename mt::argument_types;
[[maybe_unused]] auto typed_arguments = std::make_tuple(
(args + Is)->try_cast<std::tuple_element_t<Is, argument_types>>()...);
if ( !(std::get<Is>(typed_arguments) && ...) ) {
throw std::logic_error("an attempt to call a method with incorrect argument types");
}
if constexpr ( mt::is_const ) {
if constexpr ( std::is_void_v<return_type> ) {
std::invoke(Method,
std::ref(*static_cast<const instance_type*>(instance)),
*std::get<Is>(typed_arguments)...);
return value{};
} else {
return_type return_value = std::invoke(Method,
std::ref(*static_cast<const instance_type*>(instance)),
*std::get<Is>(typed_arguments)...);
return value{std::move(return_value)};
}
} else {
throw std::logic_error("an attempt to call a non-constant method by constant instance");
}
}
template < auto Method >
value cinvoke(const void* instance, value* args, std::size_t arg_count) {
using mt = method_traits<decltype(Method)>;
if ( arg_count != mt::arity ) {
throw std::logic_error("an attempt to call a method with a different arity");
}
return cinvoke<Method>(instance, args, std::make_index_sequence<mt::arity>());
}
}
namespace meta_hpp
{
class method_info {
public:
method_info() = delete;
method_info(method_info&&) = default;
method_info(const method_info&) = default;
method_info& operator=(method_info&&) = default;
method_info& operator=(const method_info&) = default;
method_info(std::string id)
: id_(std::move(id)) {}
const std::string& id() const noexcept {
return id_;
}
public:
template < typename... Args >
value invoke(void* instance, Args&&... args) const {
std::array<value, sizeof...(Args)> vargs{{std::forward<Args>(args)...}};
return invoke_(instance, vargs.data(), vargs.size());
}
template < typename... Args >
value invoke(const void* instance, Args&&... args) const {
std::array<value, sizeof...(Args)> vargs{{std::forward<Args>(args)...}};
return cinvoke_(instance, vargs.data(), vargs.size());
}
private:
friend class class_info;
template < typename Class > friend class class_;
template < auto Method > friend class method_;
private:
void merge_with_(const method_info& other) {
(void)other;
}
private:
std::string id_;
value(*invoke_)(void*, value*, std::size_t);
value(*cinvoke_)(const void*, value*, std::size_t);
};
}

View File

@@ -8,61 +8,7 @@
#include "meta_fwd.hpp"
#include "meta_class.hpp"
#include "meta_function.hpp"
#include "meta_variable.hpp"
namespace meta_hpp
{
class namespace_info {
public:
namespace_info() = delete;
namespace_info(namespace_info&&) = default;
namespace_info(const namespace_info&) = default;
namespace_info& operator=(namespace_info&&) = default;
namespace_info& operator=(const namespace_info&) = default;
namespace_info(std::string id)
: id_(std::move(id)) {}
const std::string& id() const noexcept {
return id_;
}
std::optional<class_info> get_class(std::string_view id) const {
return detail::find_opt(classes_, id);
}
std::optional<function_info> get_function(std::string_view id) const {
return detail::find_opt(functions_, id);
}
std::optional<namespace_info> get_namespace(std::string_view id) const {
return detail::find_opt(namespaces_, id);
}
std::optional<variable_info> get_variable(std::string_view id) const {
return detail::find_opt(variables_, id);
}
private:
friend class namespace_;
private:
void merge_with_(const namespace_info& other) {
detail::merge_with(classes_, other.classes_, &class_info::merge_with_);
detail::merge_with(functions_, other.functions_, &function_info::merge_with_);
detail::merge_with(namespaces_, other.namespaces_, &namespace_info::merge_with_);
detail::merge_with(variables_, other.variables_, &variable_info::merge_with_);
}
private:
std::string id_;
std::map<std::string, class_info, std::less<>> classes_;
std::map<std::string, function_info, std::less<>> functions_;
std::map<std::string, namespace_info, std::less<>> namespaces_;
std::map<std::string, variable_info, std::less<>> variables_;
};
}
#include "meta_namespace_info.hpp"
namespace meta_hpp
{

View File

@@ -0,0 +1,65 @@
/*******************************************************************************
* 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_class_info.hpp"
#include "meta_function_info.hpp"
#include "meta_variable_info.hpp"
namespace meta_hpp
{
class namespace_info {
public:
namespace_info() = delete;
namespace_info(namespace_info&&) = default;
namespace_info(const namespace_info&) = default;
namespace_info& operator=(namespace_info&&) = default;
namespace_info& operator=(const namespace_info&) = default;
namespace_info(std::string id)
: id_(std::move(id)) {}
const std::string& id() const noexcept {
return id_;
}
std::optional<class_info> get_class(std::string_view id) const {
return detail::find_opt(classes_, id);
}
std::optional<function_info> get_function(std::string_view id) const {
return detail::find_opt(functions_, id);
}
std::optional<namespace_info> get_namespace(std::string_view id) const {
return detail::find_opt(namespaces_, id);
}
std::optional<variable_info> get_variable(std::string_view id) const {
return detail::find_opt(variables_, id);
}
private:
friend class namespace_;
private:
void merge_with_(const namespace_info& other) {
detail::merge_with(classes_, other.classes_, &class_info::merge_with_);
detail::merge_with(functions_, other.functions_, &function_info::merge_with_);
detail::merge_with(namespaces_, other.namespaces_, &namespace_info::merge_with_);
detail::merge_with(variables_, other.variables_, &variable_info::merge_with_);
}
private:
std::string id_;
std::map<std::string, class_info, std::less<>> classes_;
std::map<std::string, function_info, std::less<>> functions_;
std::map<std::string, namespace_info, std::less<>> namespaces_;
std::map<std::string, variable_info, std::less<>> variables_;
};
}

View File

@@ -1,46 +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, by Matvey Cherevko (blackmatov@gmail.com)
******************************************************************************/
#pragma once
#include "meta_fwd.hpp"
#include "meta_class.hpp"
#include "meta_function.hpp"
#include "meta_namespace.hpp"
#include "meta_variable.hpp"
namespace meta_hpp
{
class registry {
public:
registry() = default;
template < typename... Internals >
registry& operator()(Internals&&...internals) {
default_namespace_(std::forward<Internals>(internals)...);
return *this;
}
std::optional<class_info> get_class(std::string_view id) const {
return default_namespace_.info().get_class(id);
}
std::optional<function_info> get_function(std::string_view id) const {
return default_namespace_.info().get_function(id);
}
std::optional<namespace_info> get_namespace(std::string_view id) const {
return default_namespace_.info().get_namespace(id);
}
std::optional<variable_info> get_variable(std::string_view id) const {
return default_namespace_.info().get_variable(id);
}
private:
namespace_ default_namespace_{""};
};
}

View File

@@ -8,91 +8,7 @@
#include "meta_fwd.hpp"
#include "meta_value.hpp"
namespace meta_hpp::variable_detail
{
template < typename Variable >
struct variable_traits;
template < typename T >
struct variable_traits<T*> {
static constexpr bool is_const = false;
using value_type = T;
};
template < typename T >
struct variable_traits<const T*> {
static constexpr bool is_const = true;
using value_type = T;
};
template < auto Variable >
value getter() {
using vt = variable_traits<decltype(Variable)>;
using value_type = typename vt::value_type;
value_type typed_value = *Variable;
return value{std::move(typed_value)};
}
template < auto Variable >
void setter(value value) {
using vt = variable_traits<decltype(Variable)>;
using value_type = typename vt::value_type;
if constexpr ( !vt::is_const ) {
*Variable = value.cast<value_type>();
} else {
throw std::logic_error("an attempt to change a constant variable");
}
}
}
namespace meta_hpp
{
class variable_info {
public:
variable_info() = delete;
variable_info(variable_info&&) = default;
variable_info(const variable_info&) = default;
variable_info& operator=(variable_info&&) = default;
variable_info& operator=(const variable_info&) = default;
variable_info(std::string id)
: id_(std::move(id)) {}
const std::string& id() const noexcept {
return id_;
}
public:
value get() const {
return getter_();
}
template < typename Value >
void set(Value&& value) const {
return setter_(std::forward<Value>(value));
}
private:
friend class class_info;
friend class namespace_info;
template < typename Class > friend class class_;
friend class namespace_;
template < auto Variable > friend class variable_;
private:
void merge_with_(const variable_info& other) {
(void)other;
}
private:
std::string id_;
value(*getter_)();
void(*setter_)(value);
};
}
#include "meta_variable_info.hpp"
namespace meta_hpp
{

View File

@@ -0,0 +1,95 @@
/*******************************************************************************
* 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_value.hpp"
namespace meta_hpp::variable_detail
{
template < typename Variable >
struct variable_traits;
template < typename T >
struct variable_traits<T*> {
static constexpr bool is_const = false;
using value_type = T;
};
template < typename T >
struct variable_traits<const T*> {
static constexpr bool is_const = true;
using value_type = T;
};
template < auto Variable >
value getter() {
using vt = variable_traits<decltype(Variable)>;
using value_type = typename vt::value_type;
value_type typed_value = *Variable;
return value{std::move(typed_value)};
}
template < auto Variable >
void setter(value value) {
using vt = variable_traits<decltype(Variable)>;
using value_type = typename vt::value_type;
if constexpr ( !vt::is_const ) {
*Variable = value.cast<value_type>();
} else {
throw std::logic_error("an attempt to change a constant variable");
}
}
}
namespace meta_hpp
{
class variable_info {
public:
variable_info() = delete;
variable_info(variable_info&&) = default;
variable_info(const variable_info&) = default;
variable_info& operator=(variable_info&&) = default;
variable_info& operator=(const variable_info&) = default;
variable_info(std::string id)
: id_(std::move(id)) {}
const std::string& id() const noexcept {
return id_;
}
public:
value get() const {
return getter_();
}
template < typename Value >
void set(Value&& value) const {
return setter_(std::forward<Value>(value));
}
private:
friend class class_info;
friend class namespace_info;
template < typename Class > friend class class_;
friend class namespace_;
template < auto Variable > friend class variable_;
private:
void merge_with_(const variable_info& other) {
(void)other;
}
private:
std::string id_;
value(*getter_)();
void(*setter_)(value);
};
}

View File

@@ -5,6 +5,11 @@
******************************************************************************/
#include <meta.hpp/meta_class.hpp>
#include <meta.hpp/meta_field.hpp>
#include <meta.hpp/meta_function.hpp>
#include <meta.hpp/meta_method.hpp>
#include <meta.hpp/meta_variable.hpp>
#include "doctest/doctest.hpp"
namespace

View File

@@ -87,27 +87,23 @@ TEST_CASE("meta/examples/ivec3") {
TEST_CASE("meta/examples/simple") {
namespace meta = meta_hpp;
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::method_<&ivec2::length2>("length2")
),
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::method_<&ivec3::length2>("length2")
),
meta::function_<meta::select<ivec2(ivec2,ivec2)>(&add)>("iadd2"),
meta::function_<meta::select<ivec3(ivec3,ivec3)>(&add)>("iadd3")
)
);
meta::namespace_info vmath_info = registry.get_namespace("vmath").value();
meta::namespace_info vmath_info = meta::namespace_("vmath")(
meta::class_<ivec2>("ivec2")(
meta::field_<&ivec2::x>("x"),
meta::field_<&ivec2::y>("y"),
meta::method_<&ivec2::dot>("dot"),
meta::method_<&ivec2::length2>("length2")
),
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::method_<&ivec3::length2>("length2")
),
meta::function_<meta::select<ivec2(ivec2,ivec2)>(&add)>("iadd2"),
meta::function_<meta::select<ivec3(ivec3,ivec3)>(&add)>("iadd3")
).info();
meta::class_info ivec2_info = vmath_info.get_class("ivec2").value();
meta::field_info ivec2_x_info = ivec2_info.get_field("x").value();

View File

@@ -4,7 +4,11 @@
* Copyright (C) 2021, by Matvey Cherevko (blackmatov@gmail.com)
******************************************************************************/
#include <meta.hpp/meta_class.hpp>
#include <meta.hpp/meta_function.hpp>
#include <meta.hpp/meta_namespace.hpp>
#include <meta.hpp/meta_variable.hpp>
#include "doctest/doctest.hpp"
namespace

View File

@@ -1,67 +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, by Matvey Cherevko (blackmatov@gmail.com)
******************************************************************************/
#include <meta.hpp/meta_registry.hpp>
#include "doctest/doctest.hpp"
namespace
{
class clazz {};
int func(int a) { return a; }
int variable{1};
const int cvariable{2};
}
TEST_CASE("meta/registry") {
namespace meta = meta_hpp;
meta::registry registry;
const meta::registry& cregistry = registry;
CHECK_FALSE(cregistry.get_class("clazz"));
CHECK_FALSE(cregistry.get_function("func"));
CHECK_FALSE(cregistry.get_namespace("ns"));
CHECK_FALSE(cregistry.get_variable("variable"));
CHECK_FALSE(cregistry.get_variable("cvariable"));
registry(
meta::class_<clazz>("clazz"),
meta::function_<&func>("func"),
meta::namespace_("ns"),
meta::variable_<&variable>("variable"),
meta::variable_<&cvariable>("cvariable"));
CHECK(cregistry.get_class("clazz"));
CHECK(cregistry.get_function("func"));
CHECK(cregistry.get_namespace("ns"));
CHECK(cregistry.get_variable("variable"));
CHECK(cregistry.get_variable("cvariable"));
{
meta::class_info clazz_info = cregistry.get_class("clazz").value();
CHECK(clazz_info.id() == "clazz");
}
{
meta::function_info clazz_info = cregistry.get_function("func").value();
CHECK(clazz_info.id() == "func");
}
{
meta::namespace_info namespace_info = cregistry.get_namespace("ns").value();
CHECK(namespace_info.id() == "ns");
}
{
meta::variable_info variable_info = cregistry.get_variable("variable").value();
CHECK(variable_info.id() == "variable");
}
{
meta::variable_info cvariable_info = cregistry.get_variable("cvariable").value();
CHECK(cvariable_info.id() == "cvariable");
}
}