mirror of
https://github.com/BlackMATov/meta.hpp.git
synced 2025-12-14 19:41:29 +07:00
merge types in registry
This commit is contained in:
@@ -21,88 +21,152 @@ namespace meta_hpp
|
||||
{
|
||||
class registry {
|
||||
public:
|
||||
template < typename T >
|
||||
std::optional<type> resolve() const {
|
||||
return detail::find_opt(family_to_types_, get_family_id<T>());
|
||||
}
|
||||
|
||||
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);
|
||||
return resolve<decltype(T)>();
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
std::optional<type> resolve() const {
|
||||
const family_id fid = get_family_id<T>();
|
||||
return detail::find_opt(family_to_types_, fid);
|
||||
std::optional<type> resolve(T&&) const {
|
||||
return resolve<std::decay_t<T>>();
|
||||
}
|
||||
|
||||
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);
|
||||
std::optional<class_info> get_class_by_name(std::string_view name) const {
|
||||
return detail::find_opt(name_to_classes_, name);
|
||||
}
|
||||
|
||||
std::optional<field_info> get_field_by_name(std::string_view name) const {
|
||||
return detail::find_opt(name_to_fields_, name);
|
||||
}
|
||||
|
||||
std::optional<function_info> get_function_by_name(std::string_view name) const {
|
||||
return detail::find_opt(name_to_functions_, name);
|
||||
}
|
||||
|
||||
std::optional<method_info> get_method_by_name(std::string_view name) const {
|
||||
return detail::find_opt(name_to_methods_, name);
|
||||
}
|
||||
|
||||
std::optional<namespace_info> get_namespace_by_name(std::string_view name) const {
|
||||
return detail::find_opt(name_to_namespaces_, name);
|
||||
}
|
||||
|
||||
std::optional<variable_info> get_variable_by_name(std::string_view name) const {
|
||||
return detail::find_opt(name_to_variables_, name);
|
||||
}
|
||||
|
||||
template < typename... Internals >
|
||||
registry& operator()(Internals&&...internals) {
|
||||
(add_(std::forward<Internals>(internals)), ...);
|
||||
(add_(std::string{}, std::forward<Internals>(internals)), ...);
|
||||
return *this;
|
||||
}
|
||||
private:
|
||||
void add_(const class_info& info) {
|
||||
family_to_types_.emplace(info.fid(), info);
|
||||
void add_(const std::string& prefix, const class_info& info) {
|
||||
const std::string name = prefix.empty()
|
||||
? info.id()
|
||||
: prefix + "::" + info.id();
|
||||
|
||||
info.each_class([this](const class_info& internal){
|
||||
add_(internal);
|
||||
});
|
||||
detail::merge_with(name_to_classes_, name, info, &class_info::merge);
|
||||
detail::merge_with(family_to_types_, info.fid(), info, &type::merge);
|
||||
|
||||
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);
|
||||
info.visit(overloaded {
|
||||
[](const data_info&) {},
|
||||
[this, &name](const auto& internal){
|
||||
add_(name, internal);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void add_(const field_info& info) {
|
||||
family_to_types_.emplace(info.fid(), info);
|
||||
}
|
||||
void add_(const std::string& prefix, const field_info& info) {
|
||||
const std::string name = prefix.empty()
|
||||
? info.id()
|
||||
: prefix + "::" + info.id();
|
||||
|
||||
void add_(const function_info& info) {
|
||||
family_to_types_.emplace(info.fid(), info);
|
||||
}
|
||||
detail::merge_with(name_to_fields_, name, info, &field_info::merge);
|
||||
detail::merge_with(family_to_types_, info.fid(), info, &type::merge);
|
||||
|
||||
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);
|
||||
info.visit(overloaded {
|
||||
[](const data_info&) {},
|
||||
[this, &name](const auto& internal){
|
||||
add_(name, internal);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void add_(const variable_info& info) {
|
||||
family_to_types_.emplace(info.fid(), info);
|
||||
void add_(const std::string& prefix, const function_info& info) {
|
||||
const std::string name = prefix.empty()
|
||||
? info.id()
|
||||
: prefix + "::" + info.id();
|
||||
|
||||
detail::merge_with(name_to_functions_, name, info, &function_info::merge);
|
||||
detail::merge_with(family_to_types_, info.fid(), info, &type::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(name_to_methods_, name, info, &method_info::merge);
|
||||
detail::merge_with(family_to_types_, info.fid(), info, &type::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(name_to_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(name_to_variables_, name, info, &variable_info::merge);
|
||||
detail::merge_with(family_to_types_, info.fid(), info, &type::merge);
|
||||
|
||||
info.visit(overloaded {
|
||||
[](const data_info&) {},
|
||||
[this, &name](const auto& internal){
|
||||
add_(name, internal);
|
||||
}
|
||||
});
|
||||
}
|
||||
private:
|
||||
std::map<family_id, type, std::less<>> family_to_types_;
|
||||
std::map<std::string, class_info, std::less<>> name_to_classes_;
|
||||
std::map<std::string, field_info, std::less<>> name_to_fields_;
|
||||
std::map<std::string, function_info, std::less<>> name_to_functions_;
|
||||
std::map<std::string, method_info, std::less<>> name_to_methods_;
|
||||
std::map<std::string, namespace_info, std::less<>> name_to_namespaces_;
|
||||
std::map<std::string, variable_info, std::less<>> name_to_variables_;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -31,19 +31,83 @@ namespace meta_hpp
|
||||
type(Info&& info)
|
||||
: info_{std::forward<Info>(info)} {}
|
||||
|
||||
bool is_class() const noexcept { return std::holds_alternative<class_info>(info_); }
|
||||
bool is_field() const noexcept { return std::holds_alternative<field_info>(info_); }
|
||||
bool is_function() const noexcept { return std::holds_alternative<function_info>(info_); }
|
||||
bool is_method() const noexcept { return std::holds_alternative<method_info>(info_); }
|
||||
bool is_namespace() const noexcept { return std::holds_alternative<namespace_info>(info_); }
|
||||
bool is_variable() const noexcept { return std::holds_alternative<variable_info>(info_); }
|
||||
bool is_class() const noexcept {
|
||||
return std::holds_alternative<class_info>(info_);
|
||||
}
|
||||
|
||||
const class_info& get_class_info() const { return std::get<class_info>(info_); }
|
||||
const field_info& get_field_info() const { return std::get<field_info>(info_); }
|
||||
const function_info& get_function_info() const { return std::get<function_info>(info_); }
|
||||
const method_info& get_method_info() const { return std::get<method_info>(info_); }
|
||||
const namespace_info& get_namespace_info() const { return std::get<namespace_info>(info_); }
|
||||
const variable_info& get_variable_info() const { return std::get<variable_info>(info_); }
|
||||
bool is_field() const noexcept {
|
||||
return std::holds_alternative<field_info>(info_);
|
||||
}
|
||||
|
||||
bool is_function() const noexcept {
|
||||
return std::holds_alternative<function_info>(info_);
|
||||
}
|
||||
|
||||
bool is_method() const noexcept {
|
||||
return std::holds_alternative<method_info>(info_);
|
||||
}
|
||||
|
||||
bool is_namespace() const noexcept {
|
||||
return std::holds_alternative<namespace_info>(info_);
|
||||
}
|
||||
|
||||
bool is_variable() const noexcept {
|
||||
return std::holds_alternative<variable_info>(info_);
|
||||
}
|
||||
|
||||
std::optional<class_info> get_class() const {
|
||||
if ( const class_info* info = std::get_if<class_info>(&info_); info ) {
|
||||
return *info;
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<field_info> get_field() const {
|
||||
if ( const field_info* info = std::get_if<field_info>(&info_); info ) {
|
||||
return *info;
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<function_info> get_function() const {
|
||||
if ( const function_info* info = std::get_if<function_info>(&info_); info ) {
|
||||
return *info;
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<method_info> get_method() const {
|
||||
if ( const method_info* info = std::get_if<method_info>(&info_); info ) {
|
||||
return *info;
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<namespace_info> get_namespace() const {
|
||||
if ( const namespace_info* info = std::get_if<namespace_info>(&info_); info ) {
|
||||
return *info;
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<variable_info> get_variable() const {
|
||||
if ( const variable_info* info = std::get_if<variable_info>(&info_); info ) {
|
||||
return *info;
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
void merge(const type& other) {
|
||||
if ( info_.index() != other.info_.index() ) {
|
||||
throw std::logic_error("type::merge failed");
|
||||
}
|
||||
std::visit(overloaded {
|
||||
[&other](auto& info){
|
||||
using info_type = std::remove_reference_t<decltype(info)>;
|
||||
info.merge(std::get<info_type>(other.info_));
|
||||
}
|
||||
}, info_);
|
||||
}
|
||||
private:
|
||||
std::variant<
|
||||
class_info,
|
||||
|
||||
Reference in New Issue
Block a user