merge types in registry

This commit is contained in:
BlackMATov
2021-07-04 22:59:58 +07:00
parent 699f6beb76
commit 7df45ed270
5 changed files with 288 additions and 85 deletions

View File

@@ -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_;
};
}

View File

@@ -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,