From bcd0c3ec77005772c756138508b14159f67c3848 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Wed, 30 Jun 2021 02:37:45 +0700 Subject: [PATCH] separate info and registry classes --- headers/meta.hpp/meta.hpp | 12 +- headers/meta.hpp/meta_class.hpp | 65 +-------- headers/meta.hpp/meta_class_info.hpp | 74 ++++++++++ headers/meta.hpp/meta_field.hpp | 89 +----------- headers/meta.hpp/meta_field_info.hpp | 98 ++++++++++++++ headers/meta.hpp/meta_function.hpp | 96 +------------ headers/meta.hpp/meta_function_info.hpp | 105 +++++++++++++++ headers/meta.hpp/meta_fwd.hpp | 1 - headers/meta.hpp/meta_method.hpp | 156 +-------------------- headers/meta.hpp/meta_method_info.hpp | 165 +++++++++++++++++++++++ headers/meta.hpp/meta_namespace.hpp | 56 +------- headers/meta.hpp/meta_namespace_info.hpp | 65 +++++++++ headers/meta.hpp/meta_registry.hpp | 46 ------- headers/meta.hpp/meta_variable.hpp | 86 +----------- headers/meta.hpp/meta_variable_info.hpp | 95 +++++++++++++ untests/meta_class_tests.cpp | 5 + untests/meta_examples.cpp | 38 +++--- untests/meta_namespace_tests.cpp | 4 + untests/meta_registry_tests.cpp | 67 --------- 19 files changed, 645 insertions(+), 678 deletions(-) create mode 100644 headers/meta.hpp/meta_class_info.hpp create mode 100644 headers/meta.hpp/meta_field_info.hpp create mode 100644 headers/meta.hpp/meta_function_info.hpp create mode 100644 headers/meta.hpp/meta_method_info.hpp create mode 100644 headers/meta.hpp/meta_namespace_info.hpp delete mode 100644 headers/meta.hpp/meta_registry.hpp create mode 100644 headers/meta.hpp/meta_variable_info.hpp delete mode 100644 untests/meta_registry_tests.cpp diff --git a/headers/meta.hpp/meta.hpp b/headers/meta.hpp/meta.hpp index 5a55fac..04605e9 100644 --- a/headers/meta.hpp/meta.hpp +++ b/headers/meta.hpp/meta.hpp @@ -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" diff --git a/headers/meta.hpp/meta_class.hpp b/headers/meta.hpp/meta_class.hpp index 134431f..b7362ae 100644 --- a/headers/meta.hpp/meta_class.hpp +++ b/headers/meta.hpp/meta_class.hpp @@ -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 get_class(std::string_view id) const { - return detail::find_opt(classes_, id); - } - - std::optional get_field(std::string_view id) const { - return detail::find_opt(fields_, id); - } - - std::optional get_function(std::string_view id) const { - return detail::find_opt(functions_, id); - } - - std::optional get_method(std::string_view id) const { - return detail::find_opt(methods_, id); - } - - std::optional 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> classes_; - std::map> fields_; - std::map> functions_; - std::map> methods_; - std::map> variables_; - }; -} +#include "meta_class_info.hpp" namespace meta_hpp { diff --git a/headers/meta.hpp/meta_class_info.hpp b/headers/meta.hpp/meta_class_info.hpp new file mode 100644 index 0000000..8964d70 --- /dev/null +++ b/headers/meta.hpp/meta_class_info.hpp @@ -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 get_class(std::string_view id) const { + return detail::find_opt(classes_, id); + } + + std::optional get_field(std::string_view id) const { + return detail::find_opt(fields_, id); + } + + std::optional get_function(std::string_view id) const { + return detail::find_opt(functions_, id); + } + + std::optional get_method(std::string_view id) const { + return detail::find_opt(methods_, id); + } + + std::optional 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> classes_; + std::map> fields_; + std::map> functions_; + std::map> methods_; + std::map> variables_; + }; +} diff --git a/headers/meta.hpp/meta_field.hpp b/headers/meta.hpp/meta_field.hpp index 1cba987..228fc0f 100644 --- a/headers/meta.hpp/meta_field.hpp +++ b/headers/meta.hpp/meta_field.hpp @@ -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 { - static constexpr bool is_const = false; - using value_type = T; - using instance_type = Base; - }; - - template < typename T, typename Base > - struct field_traits - : field_traits { - static constexpr bool is_const = true; - }; - - template < auto Field > - value getter(const void* instance) { - using ft = field_traits; - using value_type = typename ft::value_type; - using instance_type = typename ft::instance_type; - - auto instance_ptr = static_cast(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; - 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); - std::invoke(Field, *instance_ptr) = value.cast(); - } 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)); - } - 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 { diff --git a/headers/meta.hpp/meta_field_info.hpp b/headers/meta.hpp/meta_field_info.hpp new file mode 100644 index 0000000..0bfc86e --- /dev/null +++ b/headers/meta.hpp/meta_field_info.hpp @@ -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 { + static constexpr bool is_const = false; + using value_type = T; + using instance_type = Base; + }; + + template < typename T, typename Base > + struct field_traits + : field_traits { + static constexpr bool is_const = true; + }; + + template < auto Field > + value getter(const void* instance) { + using ft = field_traits; + using value_type = typename ft::value_type; + using instance_type = typename ft::instance_type; + + auto instance_ptr = static_cast(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; + 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); + std::invoke(Field, *instance_ptr) = value.cast(); + } 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)); + } + 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); + }; +} diff --git a/headers/meta.hpp/meta_function.hpp b/headers/meta.hpp/meta_function.hpp index e11b333..c87be3f 100644 --- a/headers/meta.hpp/meta_function.hpp +++ b/headers/meta.hpp/meta_function.hpp @@ -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 { - static constexpr std::size_t arity = sizeof...(Args); - using return_type = R; - using argument_types = std::tuple; - }; - - template < typename R, typename... Args > - struct function_traits - : function_traits {}; - - template < auto Function, std::size_t... Is > - value invoke(value* args, std::index_sequence) { - using ft = function_traits; - 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>()...); - - if ( !(std::get(typed_arguments) && ...) ) { - throw std::logic_error("an attempt to call a function with incorrect argument types"); - } - - if constexpr ( std::is_void_v ) { - std::invoke(Function, - *std::get(typed_arguments)...); - return value{}; - } else { - return_type return_value = std::invoke(Function, - *std::get(typed_arguments)...); - return value{std::move(return_value)}; - } - } - - template < auto Function > - value invoke(value* args, std::size_t arg_count) { - using ft = function_traits; - - if ( arg_count != ft::arity ) { - throw std::logic_error("an attempt to call a function with an incorrect arity"); - } - - return invoke(args, std::make_index_sequence()); - } -} - -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 vargs{{std::forward(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 { diff --git a/headers/meta.hpp/meta_function_info.hpp b/headers/meta.hpp/meta_function_info.hpp new file mode 100644 index 0000000..5e95977 --- /dev/null +++ b/headers/meta.hpp/meta_function_info.hpp @@ -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 { + static constexpr std::size_t arity = sizeof...(Args); + using return_type = R; + using argument_types = std::tuple; + }; + + template < typename R, typename... Args > + struct function_traits + : function_traits {}; + + template < auto Function, std::size_t... Is > + value invoke(value* args, std::index_sequence) { + using ft = function_traits; + 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>()...); + + if ( !(std::get(typed_arguments) && ...) ) { + throw std::logic_error("an attempt to call a function with incorrect argument types"); + } + + if constexpr ( std::is_void_v ) { + std::invoke(Function, + *std::get(typed_arguments)...); + return value{}; + } else { + return_type return_value = std::invoke(Function, + *std::get(typed_arguments)...); + return value{std::move(return_value)}; + } + } + + template < auto Function > + value invoke(value* args, std::size_t arg_count) { + using ft = function_traits; + + if ( arg_count != ft::arity ) { + throw std::logic_error("an attempt to call a function with an incorrect arity"); + } + + return invoke(args, std::make_index_sequence()); + } +} + +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 vargs{{std::forward(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); + }; +} diff --git a/headers/meta.hpp/meta_fwd.hpp b/headers/meta.hpp/meta_fwd.hpp index cc304c8..7ba6e3d 100644 --- a/headers/meta.hpp/meta_fwd.hpp +++ b/headers/meta.hpp/meta_fwd.hpp @@ -21,7 +21,6 @@ namespace meta_hpp { class value; - class registry; class class_info; class field_info; diff --git a/headers/meta.hpp/meta_method.hpp b/headers/meta.hpp/meta_method.hpp index 8ce683a..1447385 100644 --- a/headers/meta.hpp/meta_method.hpp +++ b/headers/meta.hpp/meta_method.hpp @@ -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 { - 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; - }; - - template < typename R, typename Base, typename... Args > - struct method_traits - : method_traits { - static constexpr bool is_const = true; - }; - - template < typename R, typename Base, typename... Args > - struct method_traits - : method_traits {}; - - template < typename R, typename Base, typename... Args > - struct method_traits - : method_traits {}; - - template < auto Method, std::size_t... Is > - value invoke([[maybe_unused]] void* instance, value* args, std::index_sequence) { - using mt = method_traits; - 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>()...); - - if ( !(std::get(typed_arguments) && ...) ) { - throw std::logic_error("an attempt to call a method with incorrect argument types"); - } - - if constexpr ( std::is_void_v ) { - std::invoke(Method, - std::ref(*static_cast(instance)), - *std::get(typed_arguments)...); - return value{}; - } else { - return_type return_value = std::invoke(Method, - std::ref(*static_cast(instance)), - *std::get(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; - - if ( arg_count != mt::arity ) { - throw std::logic_error("an attempt to call a method with an incorrect arity"); - } - - return invoke(instance, args, std::make_index_sequence()); - } - - template < auto Method, std::size_t... Is > - value cinvoke([[maybe_unused]] const void* instance, value* args, std::index_sequence) { - using mt = method_traits; - 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>()...); - - if ( !(std::get(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 ) { - std::invoke(Method, - std::ref(*static_cast(instance)), - *std::get(typed_arguments)...); - return value{}; - } else { - return_type return_value = std::invoke(Method, - std::ref(*static_cast(instance)), - *std::get(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; - - if ( arg_count != mt::arity ) { - throw std::logic_error("an attempt to call a method with a different arity"); - } - - return cinvoke(instance, args, std::make_index_sequence()); - } -} - -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 vargs{{std::forward(args)...}}; - return invoke_(instance, vargs.data(), vargs.size()); - } - - template < typename... Args > - value invoke(const void* instance, Args&&... args) const { - std::array vargs{{std::forward(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 { diff --git a/headers/meta.hpp/meta_method_info.hpp b/headers/meta.hpp/meta_method_info.hpp new file mode 100644 index 0000000..3fca6c2 --- /dev/null +++ b/headers/meta.hpp/meta_method_info.hpp @@ -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 { + 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; + }; + + template < typename R, typename Base, typename... Args > + struct method_traits + : method_traits { + static constexpr bool is_const = true; + }; + + template < typename R, typename Base, typename... Args > + struct method_traits + : method_traits {}; + + template < typename R, typename Base, typename... Args > + struct method_traits + : method_traits {}; + + template < auto Method, std::size_t... Is > + value invoke([[maybe_unused]] void* instance, value* args, std::index_sequence) { + using mt = method_traits; + 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>()...); + + if ( !(std::get(typed_arguments) && ...) ) { + throw std::logic_error("an attempt to call a method with incorrect argument types"); + } + + if constexpr ( std::is_void_v ) { + std::invoke(Method, + std::ref(*static_cast(instance)), + *std::get(typed_arguments)...); + return value{}; + } else { + return_type return_value = std::invoke(Method, + std::ref(*static_cast(instance)), + *std::get(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; + + if ( arg_count != mt::arity ) { + throw std::logic_error("an attempt to call a method with an incorrect arity"); + } + + return invoke(instance, args, std::make_index_sequence()); + } + + template < auto Method, std::size_t... Is > + value cinvoke([[maybe_unused]] const void* instance, value* args, std::index_sequence) { + using mt = method_traits; + 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>()...); + + if ( !(std::get(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 ) { + std::invoke(Method, + std::ref(*static_cast(instance)), + *std::get(typed_arguments)...); + return value{}; + } else { + return_type return_value = std::invoke(Method, + std::ref(*static_cast(instance)), + *std::get(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; + + if ( arg_count != mt::arity ) { + throw std::logic_error("an attempt to call a method with a different arity"); + } + + return cinvoke(instance, args, std::make_index_sequence()); + } +} + +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 vargs{{std::forward(args)...}}; + return invoke_(instance, vargs.data(), vargs.size()); + } + + template < typename... Args > + value invoke(const void* instance, Args&&... args) const { + std::array vargs{{std::forward(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); + }; +} diff --git a/headers/meta.hpp/meta_namespace.hpp b/headers/meta.hpp/meta_namespace.hpp index 895e1e4..e3280a9 100644 --- a/headers/meta.hpp/meta_namespace.hpp +++ b/headers/meta.hpp/meta_namespace.hpp @@ -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 get_class(std::string_view id) const { - return detail::find_opt(classes_, id); - } - - std::optional get_function(std::string_view id) const { - return detail::find_opt(functions_, id); - } - - std::optional get_namespace(std::string_view id) const { - return detail::find_opt(namespaces_, id); - } - - std::optional 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> classes_; - std::map> functions_; - std::map> namespaces_; - std::map> variables_; - }; -} +#include "meta_namespace_info.hpp" namespace meta_hpp { diff --git a/headers/meta.hpp/meta_namespace_info.hpp b/headers/meta.hpp/meta_namespace_info.hpp new file mode 100644 index 0000000..4ad5bb2 --- /dev/null +++ b/headers/meta.hpp/meta_namespace_info.hpp @@ -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 get_class(std::string_view id) const { + return detail::find_opt(classes_, id); + } + + std::optional get_function(std::string_view id) const { + return detail::find_opt(functions_, id); + } + + std::optional get_namespace(std::string_view id) const { + return detail::find_opt(namespaces_, id); + } + + std::optional 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> classes_; + std::map> functions_; + std::map> namespaces_; + std::map> variables_; + }; +} diff --git a/headers/meta.hpp/meta_registry.hpp b/headers/meta.hpp/meta_registry.hpp deleted file mode 100644 index b2f43ce..0000000 --- a/headers/meta.hpp/meta_registry.hpp +++ /dev/null @@ -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)...); - return *this; - } - - std::optional get_class(std::string_view id) const { - return default_namespace_.info().get_class(id); - } - - std::optional get_function(std::string_view id) const { - return default_namespace_.info().get_function(id); - } - - std::optional get_namespace(std::string_view id) const { - return default_namespace_.info().get_namespace(id); - } - - std::optional get_variable(std::string_view id) const { - return default_namespace_.info().get_variable(id); - } - private: - namespace_ default_namespace_{""}; - }; -} diff --git a/headers/meta.hpp/meta_variable.hpp b/headers/meta.hpp/meta_variable.hpp index 0b840a6..78fe289 100644 --- a/headers/meta.hpp/meta_variable.hpp +++ b/headers/meta.hpp/meta_variable.hpp @@ -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 { - static constexpr bool is_const = false; - using value_type = T; - }; - - template < typename T > - struct variable_traits { - static constexpr bool is_const = true; - using value_type = T; - }; - - template < auto Variable > - value getter() { - using vt = variable_traits; - 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; - using value_type = typename vt::value_type; - - if constexpr ( !vt::is_const ) { - *Variable = value.cast(); - } 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)); - } - 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 { diff --git a/headers/meta.hpp/meta_variable_info.hpp b/headers/meta.hpp/meta_variable_info.hpp new file mode 100644 index 0000000..f9c6767 --- /dev/null +++ b/headers/meta.hpp/meta_variable_info.hpp @@ -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 { + static constexpr bool is_const = false; + using value_type = T; + }; + + template < typename T > + struct variable_traits { + static constexpr bool is_const = true; + using value_type = T; + }; + + template < auto Variable > + value getter() { + using vt = variable_traits; + 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; + using value_type = typename vt::value_type; + + if constexpr ( !vt::is_const ) { + *Variable = value.cast(); + } 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)); + } + 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); + }; +} diff --git a/untests/meta_class_tests.cpp b/untests/meta_class_tests.cpp index d399e53..4cdc650 100644 --- a/untests/meta_class_tests.cpp +++ b/untests/meta_class_tests.cpp @@ -5,6 +5,11 @@ ******************************************************************************/ #include +#include +#include +#include +#include + #include "doctest/doctest.hpp" namespace diff --git a/untests/meta_examples.cpp b/untests/meta_examples.cpp index 4df1896..e8332e7 100644 --- a/untests/meta_examples.cpp +++ b/untests/meta_examples.cpp @@ -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")( - meta::field_<&ivec2::x>("x"), - meta::field_<&ivec2::y>("y"), - meta::method_<&ivec2::dot>("dot"), - meta::method_<&ivec2::length2>("length2") - ), - meta::class_("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_(&add)>("iadd2"), - meta::function_(&add)>("iadd3") - ) - ); - - meta::namespace_info vmath_info = registry.get_namespace("vmath").value(); + meta::namespace_info vmath_info = meta::namespace_("vmath")( + meta::class_("ivec2")( + meta::field_<&ivec2::x>("x"), + meta::field_<&ivec2::y>("y"), + meta::method_<&ivec2::dot>("dot"), + meta::method_<&ivec2::length2>("length2") + ), + meta::class_("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_(&add)>("iadd2"), + meta::function_(&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(); diff --git a/untests/meta_namespace_tests.cpp b/untests/meta_namespace_tests.cpp index 146d71c..e5aca71 100644 --- a/untests/meta_namespace_tests.cpp +++ b/untests/meta_namespace_tests.cpp @@ -4,7 +4,11 @@ * Copyright (C) 2021, by Matvey Cherevko (blackmatov@gmail.com) ******************************************************************************/ +#include +#include #include +#include + #include "doctest/doctest.hpp" namespace diff --git a/untests/meta_registry_tests.cpp b/untests/meta_registry_tests.cpp deleted file mode 100644 index e62fc43..0000000 --- a/untests/meta_registry_tests.cpp +++ /dev/null @@ -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 -#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"), - 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"); - } -}