Files
meta.hpp/headers/meta.hpp/meta_registry.hpp
BlackMATov 2ea9a01f32 basic ctors
2021-07-13 09:24:07 +07:00

247 lines
8.0 KiB
C++

/*******************************************************************************
* 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_ctor.hpp"
#include "meta_data.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 < typename T >
std::optional<class_info> resolve() const {
const family_id fid = get_family_id<T>();
return detail::find_opt(types_, fid);
}
template < typename T >
std::optional<class_info> resolve(T&&) const {
const family_id fid = get_family_id<std::decay_t<T>>();
return detail::find_opt(types_, fid);
}
std::optional<class_info> get_class_by_name(std::string_view name) const {
return detail::find_opt(classes_, name);
}
std::optional<field_info> get_field_by_name(std::string_view name) const {
return detail::find_opt(fields_, name);
}
std::optional<function_info> get_function_by_name(std::string_view name) const {
return detail::find_opt(functions_, name);
}
std::optional<method_info> get_method_by_name(std::string_view name) const {
return detail::find_opt(methods_, name);
}
std::optional<namespace_info> get_namespace_by_name(std::string_view name) const {
return detail::find_opt(namespaces_, name);
}
std::optional<variable_info> get_variable_by_name(std::string_view name) const {
return detail::find_opt(variables_, name);
}
template < typename F >
void each_type(F&& f) const {
for ( auto&& id_type : types_ ) {
std::invoke(f, id_type.second);
}
}
template < typename F >
void each_class(F&& f) const {
for ( auto&& id_info : classes_ ) {
std::invoke(f, id_info.second);
}
}
template < typename F >
void each_field(F&& f) const {
for ( auto&& id_info : fields_ ) {
std::invoke(f, id_info.second);
}
}
template < typename F >
void each_function(F&& f) const {
for ( auto&& id_info : functions_ ) {
std::invoke(f, id_info.second);
}
}
template < typename F >
void each_method(F&& f) const {
for ( auto&& id_info : methods_ ) {
std::invoke(f, id_info.second);
}
}
template < typename F >
void each_namespace(F&& f) const {
for ( auto&& id_info : namespaces_ ) {
std::invoke(f, id_info.second);
}
}
template < typename F >
void each_variable(F&& f) const {
for ( auto&& id_info : variables_ ) {
std::invoke(f, id_info.second);
}
}
template < typename F >
void visit(F&& f) const {
each_class(f);
each_field(f);
each_function(f);
each_method(f);
each_namespace(f);
each_variable(f);
}
template < typename... Internals >
registry& operator()(Internals&&...internals) {
(add_(std::string{}, std::forward<Internals>(internals)), ...);
return *this;
}
private:
template < typename InternalClass >
void add_(const std::string& prefix, class_<InternalClass> internal) {
add_(prefix, std::move(internal).make_info());
}
template < typename FunctionType >
void add_(const std::string& prefix, function_<FunctionType> internal) {
add_(prefix, std::move(internal).make_info());
}
void add_(const std::string& prefix, namespace_ internal) {
add_(prefix, std::move(internal).make_info());
}
template < typename VariableType >
void add_(const std::string& prefix, variable_<VariableType> internal) {
add_(prefix, std::move(internal).make_info());
}
private:
void add_(const std::string& prefix, const class_info& info) {
const std::string name = prefix.empty()
? info.id()
: prefix + "::" + info.id();
detail::merge_with(types_, info.family(), info, &class_info::merge);
detail::merge_with(classes_, name, info, &class_info::merge);
info.visit(overloaded {
[](const ctor_info&) {},
[](const data_info&) {},
[this, &name](const auto& internal){
add_(name, internal);
}
});
}
void add_(const std::string& prefix, const field_info& info) {
const std::string name = prefix.empty()
? info.id()
: prefix + "::" + info.id();
detail::merge_with(fields_, name, info, &field_info::merge);
info.visit(overloaded {
[](const data_info&) {},
[this, &name](const auto& internal){
add_(name, internal);
}
});
}
void add_(const std::string& prefix, const function_info& info) {
const std::string name = prefix.empty()
? info.id()
: prefix + "::" + info.id();
detail::merge_with(functions_, name, info, &function_info::merge);
info.visit(overloaded {
[](const data_info&) {},
[this, &name](const auto& internal){
add_(name, internal);
}
});
}
void add_(const std::string& prefix, const method_info& info) {
const std::string name = prefix.empty()
? info.id()
: prefix + "::" + info.id();
detail::merge_with(methods_, name, info, &method_info::merge);
info.visit(overloaded {
[](const data_info&) {},
[this, &name](const auto& internal){
add_(name, internal);
}
});
}
void add_(const std::string& prefix, const namespace_info& info) {
const std::string name = prefix.empty()
? info.id()
: prefix + "::" + info.id();
detail::merge_with(namespaces_, name, info, &namespace_info::merge);
info.visit(overloaded {
[](const data_info&) {},
[this, &name](const auto& internal){
add_(name, internal);
}
});
}
void add_(const std::string& prefix, const variable_info& info) {
const std::string name = prefix.empty()
? info.id()
: prefix + "::" + info.id();
detail::merge_with(variables_, name, info, &variable_info::merge);
info.visit(overloaded {
[](const data_info&) {},
[this, &name](const auto& internal){
add_(name, internal);
}
});
}
private:
std::map<family_id, class_info, std::less<>> types_;
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, namespace_info, std::less<>> namespaces_;
std::map<std::string, variable_info, std::less<>> variables_;
};
}