mirror of
https://github.com/BlackMATov/meta.hpp.git
synced 2025-12-16 22:17:02 +07:00
base type for classes
This commit is contained in:
@@ -40,6 +40,7 @@ namespace meta_hpp
|
||||
|
||||
namespace meta_hpp
|
||||
{
|
||||
class base_info;
|
||||
class class_info;
|
||||
class ctor_info;
|
||||
class data_info;
|
||||
@@ -53,6 +54,7 @@ namespace meta_hpp
|
||||
|
||||
namespace meta_hpp
|
||||
{
|
||||
template < typename Base > class base_;
|
||||
template < typename Class > class class_;
|
||||
template < typename... Args > class ctor_;
|
||||
class data_;
|
||||
@@ -70,6 +72,7 @@ namespace meta_hpp
|
||||
|
||||
class arithmetic_type;
|
||||
class array_type;
|
||||
class base_type;
|
||||
class class_type;
|
||||
class ctor_type;
|
||||
class enum_type;
|
||||
@@ -92,6 +95,7 @@ namespace meta_hpp
|
||||
template < typename K, typename V >
|
||||
using info_map = std::map<K, V, std::less<>>;
|
||||
|
||||
using base_info_map = info_map<type_id, base_info>;
|
||||
using class_info_map = info_map<std::string, class_info>;
|
||||
using ctor_info_map = info_map<type_id, ctor_info>;
|
||||
using data_info_map = info_map<std::string, data_info>;
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#include "meta_fwd.hpp"
|
||||
|
||||
#include "meta_infos/base_info.hpp"
|
||||
#include "meta_infos/class_info.hpp"
|
||||
#include "meta_infos/ctor_info.hpp"
|
||||
#include "meta_infos/data_info.hpp"
|
||||
|
||||
93
headers/meta.hpp/meta_infos/base_info.hpp
Normal file
93
headers/meta.hpp/meta_infos/base_info.hpp
Normal file
@@ -0,0 +1,93 @@
|
||||
/*******************************************************************************
|
||||
* 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 "_infos_fwd.hpp"
|
||||
|
||||
#include "data_info.hpp"
|
||||
|
||||
namespace meta_hpp
|
||||
{
|
||||
class base_info final {
|
||||
public:
|
||||
base_info() = default;
|
||||
|
||||
void merge(const base_info& other);
|
||||
explicit operator bool() const noexcept;
|
||||
|
||||
const base_type& type() const noexcept;
|
||||
public:
|
||||
template < typename F >
|
||||
void visit(F&& f) const;
|
||||
|
||||
template < typename F >
|
||||
void each_data(F&& f) const;
|
||||
|
||||
data_info get_data_by_name(std::string_view name) const noexcept;
|
||||
private:
|
||||
template < typename Base > friend class base_;
|
||||
|
||||
template < typename Base, typename Derived >
|
||||
explicit base_info(typename_arg_t<Base>, typename_arg_t<Derived>);
|
||||
private:
|
||||
struct state;
|
||||
std::shared_ptr<state> state_;
|
||||
};
|
||||
}
|
||||
|
||||
namespace meta_hpp
|
||||
{
|
||||
struct base_info::state final {
|
||||
base_type type;
|
||||
data_info_map datas;
|
||||
};
|
||||
}
|
||||
|
||||
namespace meta_hpp
|
||||
{
|
||||
inline void base_info::merge(const base_info& other) {
|
||||
(void)other;
|
||||
///TODO: implme
|
||||
}
|
||||
|
||||
inline base_info::operator bool() const noexcept {
|
||||
return !!state_;
|
||||
}
|
||||
|
||||
inline const base_type& base_info::type() const noexcept {
|
||||
return state_->type;
|
||||
}
|
||||
}
|
||||
|
||||
namespace meta_hpp
|
||||
{
|
||||
template < typename F >
|
||||
void base_info::visit(F&& f) const {
|
||||
each_data(f);
|
||||
}
|
||||
|
||||
template < typename F >
|
||||
void base_info::each_data(F&& f) const {
|
||||
for ( auto&& name_info : state_->datas ) {
|
||||
std::invoke(f, name_info.second);
|
||||
}
|
||||
}
|
||||
|
||||
inline data_info base_info::get_data_by_name(std::string_view name) const noexcept {
|
||||
return detail::find_or_default(state_->datas, name);
|
||||
}
|
||||
}
|
||||
|
||||
namespace meta_hpp
|
||||
{
|
||||
template < typename Base, typename Derived >
|
||||
base_info::base_info(typename_arg_t<Base>, typename_arg_t<Derived>)
|
||||
: state_{std::make_shared<state>(state{
|
||||
base_type{typename_arg<Base>, typename_arg<Derived>},
|
||||
{}
|
||||
})} {}
|
||||
}
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#include "_infos_fwd.hpp"
|
||||
|
||||
#include "base_info.hpp"
|
||||
#include "ctor_info.hpp"
|
||||
#include "data_info.hpp"
|
||||
#include "enum_info.hpp"
|
||||
@@ -26,10 +27,23 @@ namespace meta_hpp
|
||||
|
||||
const std::string& name() const noexcept;
|
||||
const class_type& type() const noexcept;
|
||||
|
||||
template < typename Base >
|
||||
bool is_derived_from() const;
|
||||
bool is_derived_from(any_type base) const noexcept;
|
||||
|
||||
template < typename... Args >
|
||||
ctor_info get_ctor_by_args() const noexcept;
|
||||
template < std::size_t Args >
|
||||
ctor_info get_ctor_by_args(const std::array<any_type, Args>& args) const noexcept;
|
||||
ctor_info get_ctor_by_args(const std::vector<any_type>& args) const noexcept;
|
||||
public:
|
||||
template < typename F >
|
||||
void visit(F&& f) const;
|
||||
|
||||
template < typename F >
|
||||
void each_base(F&& f) const;
|
||||
|
||||
template < typename F >
|
||||
void each_class(F&& f) const;
|
||||
|
||||
@@ -73,6 +87,7 @@ namespace meta_hpp
|
||||
struct class_info::state final {
|
||||
std::string name;
|
||||
class_type type;
|
||||
base_info_map bases;
|
||||
class_info_map classes;
|
||||
ctor_info_map ctors;
|
||||
data_info_map datas;
|
||||
@@ -101,12 +116,62 @@ namespace meta_hpp
|
||||
inline const class_type& class_info::type() const noexcept {
|
||||
return state_->type;
|
||||
}
|
||||
|
||||
template < typename Base >
|
||||
bool class_info::is_derived_from() const {
|
||||
return class_info::is_derived_from(type_db::get<Base>());
|
||||
}
|
||||
|
||||
inline bool class_info::is_derived_from(any_type base) const noexcept {
|
||||
for ( auto&& id_info : state_->bases ) {
|
||||
if ( base.id() == id_info.second.type().base_class_type().id() ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template < typename... Args >
|
||||
ctor_info class_info::get_ctor_by_args() const noexcept {
|
||||
std::array<any_type, sizeof...(Args)> args{type_db::get<Args>()...};
|
||||
return get_ctor_by_args(args);
|
||||
}
|
||||
|
||||
template < std::size_t Args >
|
||||
ctor_info class_info::get_ctor_by_args(const std::array<any_type, Args>& args) const noexcept {
|
||||
for ( auto&& id_info : state_->ctors ) {
|
||||
const std::vector<any_type>& ctor_args =
|
||||
id_info.second.type().argument_types();
|
||||
|
||||
if ( args.size() == ctor_args.size()
|
||||
&& std::equal(args.begin(), args.end(), ctor_args.begin()) )
|
||||
{
|
||||
return id_info.second;
|
||||
}
|
||||
}
|
||||
return ctor_info{};
|
||||
}
|
||||
|
||||
inline ctor_info class_info::get_ctor_by_args(const std::vector<any_type>& args) const noexcept {
|
||||
for ( auto&& id_info : state_->ctors ) {
|
||||
const std::vector<any_type>& ctor_args =
|
||||
id_info.second.type().argument_types();
|
||||
|
||||
if ( args.size() == ctor_args.size()
|
||||
&& std::equal(args.begin(), args.end(), ctor_args.begin()) )
|
||||
{
|
||||
return id_info.second;
|
||||
}
|
||||
}
|
||||
return ctor_info{};
|
||||
}
|
||||
}
|
||||
|
||||
namespace meta_hpp
|
||||
{
|
||||
template < typename F >
|
||||
void class_info::visit(F&& f) const {
|
||||
each_base(f);
|
||||
each_class(f);
|
||||
each_ctor(f);
|
||||
each_data(f);
|
||||
@@ -116,6 +181,13 @@ namespace meta_hpp
|
||||
each_method(f);
|
||||
}
|
||||
|
||||
template < typename F >
|
||||
void class_info::each_base(F&& f) const {
|
||||
for ( auto&& id_info : state_->bases ) {
|
||||
std::invoke(f, id_info.second);
|
||||
}
|
||||
}
|
||||
|
||||
template < typename F >
|
||||
void class_info::each_class(F&& f) const {
|
||||
for ( auto&& name_info : state_->classes ) {
|
||||
@@ -197,6 +269,6 @@ namespace meta_hpp
|
||||
: state_{std::make_shared<state>(state{
|
||||
std::move(name),
|
||||
type_db::get<Class>().template as<class_type>(),
|
||||
{}, {}, {}, {}, {}, {}, {}
|
||||
{}, {}, {}, {}, {}, {}, {}, {}
|
||||
})} {}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "meta_fwd.hpp"
|
||||
#include "meta_infos.hpp"
|
||||
|
||||
#include "meta_registry/base_.hpp"
|
||||
#include "meta_registry/class_.hpp"
|
||||
#include "meta_registry/ctor_.hpp"
|
||||
#include "meta_registry/data_.hpp"
|
||||
@@ -48,6 +49,7 @@ namespace meta_hpp
|
||||
void add_(const std::string& prefix, ...) = delete;
|
||||
private:
|
||||
struct add_info_f;
|
||||
void add_info_(const std::string& prefix, const base_info& info);
|
||||
void add_info_(const std::string& prefix, const class_info& info);
|
||||
void add_info_(const std::string& prefix, const ctor_info& info);
|
||||
void add_info_(const std::string& prefix, const data_info& info);
|
||||
@@ -149,6 +151,11 @@ namespace meta_hpp
|
||||
}
|
||||
};
|
||||
|
||||
inline void registry::add_info_(const std::string& prefix, const base_info& info) {
|
||||
(void)prefix;
|
||||
(void)info;
|
||||
}
|
||||
|
||||
inline void registry::add_info_(const std::string& prefix, const class_info& info) {
|
||||
std::string name = prefix.empty() ? info.name() : prefix + "::" + info.name();
|
||||
info.visit(kari_hpp::curry(add_info_f{}, std::ref(*this), name));
|
||||
|
||||
58
headers/meta.hpp/meta_registry/base_.hpp
Normal file
58
headers/meta.hpp/meta_registry/base_.hpp
Normal file
@@ -0,0 +1,58 @@
|
||||
/*******************************************************************************
|
||||
* 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 "_registry_fwd.hpp"
|
||||
|
||||
#include "data_.hpp"
|
||||
|
||||
namespace meta_hpp
|
||||
{
|
||||
template < typename Base >
|
||||
class base_ final {
|
||||
public:
|
||||
explicit base_() = default;
|
||||
|
||||
template < typename Derived >
|
||||
base_info make_info() const;
|
||||
public:
|
||||
template < typename... Internals >
|
||||
base_& operator()(Internals&&...internals);
|
||||
private:
|
||||
void add_(const data_& internal);
|
||||
void add_(...) = delete;
|
||||
private:
|
||||
data_info_map datas_;
|
||||
};
|
||||
}
|
||||
|
||||
namespace meta_hpp
|
||||
{
|
||||
template < typename Base >
|
||||
template < typename Derived >
|
||||
base_info base_<Base>::make_info() const {
|
||||
base_info info{typename_arg<Base>, typename_arg<Derived>};
|
||||
info.state_->datas.insert(datas_.begin(), datas_.end());
|
||||
return info;
|
||||
}
|
||||
|
||||
template < typename Base >
|
||||
template < typename... Internals >
|
||||
base_<Base>& base_<Base>::operator()(Internals&&...internals) {
|
||||
(add_(std::forward<Internals>(internals)), ...);
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
|
||||
namespace meta_hpp
|
||||
{
|
||||
template < typename Base >
|
||||
void base_<Base>::add_(const data_& internal) {
|
||||
auto info = internal.make_info();
|
||||
detail::merge_with(datas_, info.name(), info, &data_info::merge);
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#include "_registry_fwd.hpp"
|
||||
|
||||
#include "base_.hpp"
|
||||
#include "ctor_.hpp"
|
||||
#include "data_.hpp"
|
||||
#include "enum_.hpp"
|
||||
@@ -27,6 +28,8 @@ namespace meta_hpp
|
||||
template < typename... Internals >
|
||||
class_& operator()(Internals&&...internals);
|
||||
private:
|
||||
template < typename Base >
|
||||
void add_(const base_<Base>& internal);
|
||||
template < typename Class2 >
|
||||
void add_(const class_<Class2>& internal);
|
||||
template < typename... Args >
|
||||
@@ -43,6 +46,7 @@ namespace meta_hpp
|
||||
void add_(...) = delete;
|
||||
private:
|
||||
std::string name_;
|
||||
base_info_map bases_;
|
||||
class_info_map classes_;
|
||||
ctor_info_map ctors_;
|
||||
data_info_map datas_;
|
||||
@@ -62,6 +66,7 @@ namespace meta_hpp
|
||||
template < typename Class >
|
||||
class_info class_<Class>::make_info() const {
|
||||
class_info info{typename_arg<Class>, name_};
|
||||
info.state_->bases.insert(bases_.begin(), bases_.end());
|
||||
info.state_->classes.insert(classes_.begin(), classes_.end());
|
||||
info.state_->ctors.insert(ctors_.begin(), ctors_.end());
|
||||
info.state_->datas.insert(datas_.begin(), datas_.end());
|
||||
@@ -82,6 +87,13 @@ namespace meta_hpp
|
||||
|
||||
namespace meta_hpp
|
||||
{
|
||||
template < typename Class >
|
||||
template < typename Base >
|
||||
void class_<Class>::add_(const base_<Base>& internal) {
|
||||
auto info = internal.template make_info<Class>();
|
||||
detail::merge_with(bases_, info.type().id(), info, &base_info::merge);
|
||||
}
|
||||
|
||||
template < typename Class >
|
||||
template < typename Class2 >
|
||||
void class_<Class>::add_(const class_<Class2>& internal) {
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
#include "meta_types/arithmetic_type.hpp"
|
||||
#include "meta_types/array_type.hpp"
|
||||
#include "meta_types/base_type.hpp"
|
||||
#include "meta_types/class_type.hpp"
|
||||
#include "meta_types/ctor_type.hpp"
|
||||
#include "meta_types/enum_type.hpp"
|
||||
|
||||
@@ -148,6 +148,7 @@ namespace meta_hpp
|
||||
std::variant<
|
||||
const arithmetic_type*,
|
||||
const array_type*,
|
||||
const base_type*,
|
||||
const class_type*,
|
||||
const ctor_type*,
|
||||
const enum_type*,
|
||||
|
||||
77
headers/meta.hpp/meta_types/base_type.hpp
Normal file
77
headers/meta.hpp/meta_types/base_type.hpp
Normal file
@@ -0,0 +1,77 @@
|
||||
/*******************************************************************************
|
||||
* 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 "_types_fwd.hpp"
|
||||
|
||||
namespace meta_hpp
|
||||
{
|
||||
class base_type final : public type_base {
|
||||
public:
|
||||
base_type() = default;
|
||||
|
||||
base_type(base_type&&) = default;
|
||||
base_type& operator=(base_type&&) = default;
|
||||
|
||||
base_type(const base_type&) = default;
|
||||
base_type& operator=(const base_type&) = default;
|
||||
|
||||
template < typename Base, typename Derived >
|
||||
explicit base_type(typename_arg_t<Base>, typename_arg_t<Derived>);
|
||||
|
||||
any_type base_class_type() const noexcept;
|
||||
any_type derived_class_type() const noexcept;
|
||||
private:
|
||||
struct state;
|
||||
std::shared_ptr<state> state_;
|
||||
};
|
||||
}
|
||||
|
||||
namespace meta_hpp::detail
|
||||
{
|
||||
template < typename Base, typename Derived >
|
||||
struct base_traits {
|
||||
static_assert(std::is_base_of_v<Base, Derived>);
|
||||
|
||||
using base_class_type = Base;
|
||||
using derived_class_type = Derived;
|
||||
|
||||
static any_type make_base_class_type() {
|
||||
return type_db::get<base_class_type>();
|
||||
}
|
||||
|
||||
static any_type make_derived_class_type() {
|
||||
return type_db::get<derived_class_type>();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
namespace meta_hpp
|
||||
{
|
||||
struct base_type::state final {
|
||||
const any_type base_class_type;
|
||||
const any_type derived_class_type;
|
||||
};
|
||||
|
||||
template < typename Base, typename Derived >
|
||||
base_type::base_type(typename_arg_t<Base>, typename_arg_t<Derived>)
|
||||
: type_base{typename_arg<struct base_type_tag, Base, Derived>}
|
||||
, state_{std::make_shared<state>(state{
|
||||
detail::base_traits<Base, Derived>::make_base_class_type(),
|
||||
detail::base_traits<Base, Derived>::make_derived_class_type(),
|
||||
})} {
|
||||
static_assert(std::is_base_of_v<Base, Derived>);
|
||||
}
|
||||
|
||||
inline any_type base_type::base_class_type() const noexcept {
|
||||
return state_->base_class_type;
|
||||
}
|
||||
|
||||
inline any_type base_type::derived_class_type() const noexcept {
|
||||
return state_->derived_class_type;
|
||||
}
|
||||
}
|
||||
@@ -59,16 +59,16 @@ namespace meta_hpp
|
||||
template < typename T
|
||||
, std::enable_if_t<!std::is_reference_v<T>, int> >
|
||||
inline arg::arg(T&& v)
|
||||
: data_{const_cast<add_ptr_t<remove_cvref_t<T>>>(std::addressof(v))}
|
||||
, raw_type_{type_db::get<remove_cvref_t<T>>()}
|
||||
: data_{const_cast<std::add_pointer_t<stdex::remove_cvref_t<T>>>(std::addressof(v))}
|
||||
, raw_type_{type_db::get<stdex::remove_cvref_t<T>>()}
|
||||
, ref_type_{std::is_const_v<T> ? ref_types::crref : ref_types::rref} {}
|
||||
|
||||
template < typename T
|
||||
, std::enable_if_t<std::is_lvalue_reference_v<T>, int> >
|
||||
inline arg::arg(T&& v)
|
||||
: data_{const_cast<add_ptr_t<remove_cvref_t<T>>>(std::addressof(v))}
|
||||
, raw_type_{type_db::get<remove_cvref_t<T>>()}
|
||||
, ref_type_{std::is_const_v<remove_ref_t<T>> ? ref_types::cref : ref_types::ref} {}
|
||||
: data_{const_cast<std::add_pointer_t<stdex::remove_cvref_t<T>>>(std::addressof(v))}
|
||||
, raw_type_{type_db::get<stdex::remove_cvref_t<T>>()}
|
||||
, ref_type_{std::is_const_v<std::remove_reference_t<T>> ? ref_types::cref : ref_types::ref} {}
|
||||
|
||||
template < typename To >
|
||||
inline To arg::cast() const {
|
||||
@@ -81,7 +81,7 @@ namespace meta_hpp
|
||||
}
|
||||
|
||||
if constexpr ( std::is_reference_v<To> ) {
|
||||
using raw_type = remove_cvref_t<To>;
|
||||
using raw_type = stdex::remove_cvref_t<To>;
|
||||
|
||||
if constexpr ( std::is_lvalue_reference_v<To> ) {
|
||||
return *static_cast<raw_type*>(data_);
|
||||
@@ -93,7 +93,7 @@ namespace meta_hpp
|
||||
}
|
||||
|
||||
if constexpr ( !std::is_pointer_v<To> && !std::is_reference_v<To> ) {
|
||||
using raw_type = remove_cvref_t<To>;
|
||||
using raw_type = stdex::remove_cvref_t<To>;
|
||||
|
||||
if ( ref_type() == ref_types::ref ) {
|
||||
if constexpr ( std::is_constructible_v<To, raw_type&> ) {
|
||||
@@ -126,14 +126,14 @@ namespace meta_hpp
|
||||
template < typename To >
|
||||
inline bool arg::can_cast() const noexcept {
|
||||
if constexpr ( std::is_pointer_v<To> ) {
|
||||
using to_raw_type = remove_cv_t<To>;
|
||||
using to_raw_ptr_type = remove_cv_t<std::remove_pointer_t<to_raw_type>>;
|
||||
using to_raw_type = std::remove_cv_t<To>;
|
||||
using to_raw_ptr_type = std::remove_cv_t<std::remove_pointer_t<to_raw_type>>;
|
||||
return raw_type().id() == type_db::get<to_raw_type>().id()
|
||||
|| raw_type().id() == type_db::get<add_ptr_t<to_raw_ptr_type>>().id();
|
||||
|| raw_type().id() == type_db::get<std::add_pointer_t<to_raw_ptr_type>>().id();
|
||||
}
|
||||
|
||||
if constexpr ( std::is_lvalue_reference_v<To> ) {
|
||||
constexpr bool to_const = std::is_const_v<remove_ref_t<To>>;
|
||||
constexpr bool to_const = std::is_const_v<std::remove_reference_t<To>>;
|
||||
|
||||
if ( !to_const && is_rvalue() ) {
|
||||
return false;
|
||||
@@ -143,21 +143,21 @@ namespace meta_hpp
|
||||
return false;
|
||||
}
|
||||
|
||||
using to_raw_type = remove_cvref_t<To>;
|
||||
using to_raw_type = stdex::remove_cvref_t<To>;
|
||||
if ( raw_type().id() == type_db::get<to_raw_type>().id() ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if constexpr ( to_const && std::is_pointer_v<to_raw_type> ) {
|
||||
using to_raw_ptr_type = remove_cv_t<std::remove_pointer_t<to_raw_type>>;
|
||||
return raw_type().id() == type_db::get<add_ptr_t<to_raw_ptr_type>>().id();
|
||||
using to_raw_ptr_type = std::remove_cv_t<std::remove_pointer_t<to_raw_type>>;
|
||||
return raw_type().id() == type_db::get<std::add_pointer_t<to_raw_ptr_type>>().id();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if constexpr ( std::is_rvalue_reference_v<To> ) {
|
||||
constexpr bool to_const = std::is_const_v<remove_ref_t<To>>;
|
||||
constexpr bool to_const = std::is_const_v<std::remove_reference_t<To>>;
|
||||
|
||||
if ( !is_rvalue() ) {
|
||||
return false;
|
||||
@@ -167,21 +167,21 @@ namespace meta_hpp
|
||||
return false;
|
||||
}
|
||||
|
||||
using to_raw_type = remove_cvref_t<To>;
|
||||
using to_raw_type = stdex::remove_cvref_t<To>;
|
||||
if ( raw_type().id() == type_db::get<to_raw_type>().id() ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if constexpr ( to_const && std::is_pointer_v<to_raw_type> ) {
|
||||
using to_raw_ptr_type = remove_cv_t<std::remove_pointer_t<to_raw_type>>;
|
||||
return raw_type().id() == type_db::get<add_ptr_t<to_raw_ptr_type>>().id();
|
||||
using to_raw_ptr_type = std::remove_cv_t<std::remove_pointer_t<to_raw_type>>;
|
||||
return raw_type().id() == type_db::get<std::add_pointer_t<to_raw_ptr_type>>().id();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if constexpr ( !std::is_pointer_v<To> && !std::is_reference_v<To> ) {
|
||||
using to_raw_type = remove_cv_t<To>;
|
||||
using to_raw_type = std::remove_cv_t<To>;
|
||||
if ( raw_type().id() != type_db::get<to_raw_type>().id() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
45
untests/features/infos/base_info_tests.cpp
Normal file
45
untests/features/infos/base_info_tests.cpp
Normal file
@@ -0,0 +1,45 @@
|
||||
/*******************************************************************************
|
||||
* 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 "_infos_fwd.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
using namespace meta_hpp;
|
||||
using namespace std::string_literals;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
class base {
|
||||
public:
|
||||
virtual ~base() {}
|
||||
};
|
||||
|
||||
class derived final : public base {
|
||||
public:
|
||||
derived() = default;
|
||||
};
|
||||
|
||||
struct empty final {};
|
||||
}
|
||||
|
||||
TEST_CASE("features/infos/base") {
|
||||
registry db;
|
||||
|
||||
db(
|
||||
class_<base>{"base"},
|
||||
class_<derived>{"derived"}(
|
||||
base_<base>{}
|
||||
)
|
||||
);
|
||||
|
||||
REQUIRE(db.get_class_by_path("derived"));
|
||||
const class_info derived_info = db.get_class_by_path("derived");
|
||||
|
||||
CHECK(derived_info.is_derived_from<base>());
|
||||
CHECK_FALSE(derived_info.is_derived_from<empty>());
|
||||
}
|
||||
@@ -8,7 +8,87 @@
|
||||
|
||||
namespace
|
||||
{
|
||||
using namespace meta_hpp;
|
||||
using namespace std::string_literals;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
class shape {
|
||||
public:
|
||||
virtual ~shape() {}
|
||||
virtual int area() const = 0;
|
||||
};
|
||||
|
||||
class rectangle : public shape {
|
||||
public:
|
||||
rectangle(const rectangle& other) {
|
||||
width_ = other.width_;
|
||||
height_ = other.height_;
|
||||
}
|
||||
|
||||
rectangle& operator=(const rectangle& other) {
|
||||
if ( this != &other ) {
|
||||
return *this;
|
||||
}
|
||||
width_ = other.width_;
|
||||
height_ = other.height_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
rectangle(int width, int height)
|
||||
: width_{width}
|
||||
, height_{height} {}
|
||||
|
||||
int area() const override {
|
||||
return width_ * height_;
|
||||
}
|
||||
|
||||
int width() const noexcept {
|
||||
return width_;
|
||||
}
|
||||
|
||||
int height() const noexcept {
|
||||
return height_;
|
||||
}
|
||||
private:
|
||||
int width_{};
|
||||
int height_{};
|
||||
};
|
||||
}
|
||||
|
||||
TEST_CASE("features/infos/class") {
|
||||
registry db;
|
||||
|
||||
db(
|
||||
class_<shape>{"shape"}(
|
||||
method_{"area", &shape::area}
|
||||
),
|
||||
class_<rectangle>{"rectangle"}(
|
||||
base_<shape>{},
|
||||
ctor_<int, int>{},
|
||||
method_{"width", &rectangle::width},
|
||||
method_{"height", &rectangle::height}
|
||||
)
|
||||
);
|
||||
|
||||
SUBCASE("base") {
|
||||
REQUIRE(db.get_class_by_path("shape"));
|
||||
const class_info shape_info = db.get_class_by_path("shape");
|
||||
CHECK(shape_info.name() == "shape");
|
||||
CHECK(shape_info.type().id() == type_db::get<shape>().id());
|
||||
|
||||
CHECK_FALSE(shape_info.is_derived_from<shape>());
|
||||
CHECK_FALSE(shape_info.is_derived_from<rectangle>());
|
||||
}
|
||||
|
||||
SUBCASE("derived") {
|
||||
REQUIRE(db.get_class_by_path("rectangle"));
|
||||
const class_info rectangle_info = db.get_class_by_path("rectangle");
|
||||
CHECK(rectangle_info.name() == "rectangle");
|
||||
CHECK(rectangle_info.type().id() == type_db::get<rectangle>().id());
|
||||
|
||||
CHECK(rectangle_info.is_derived_from<shape>());
|
||||
CHECK_FALSE(rectangle_info.is_derived_from<rectangle>());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,113 @@
|
||||
|
||||
namespace
|
||||
{
|
||||
using namespace meta_hpp;
|
||||
using namespace std::string_literals;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
struct ivec2 {
|
||||
int x{};
|
||||
int y{};
|
||||
|
||||
[[maybe_unused]] ivec2() = default;
|
||||
[[maybe_unused]] ivec2(const ivec2& other) = default;
|
||||
[[maybe_unused]] explicit ivec2(int v): x{v}, y{v} {}
|
||||
[[maybe_unused]] ivec2(int x, int y): x{x}, y{y} {}
|
||||
};
|
||||
}
|
||||
|
||||
TEST_CASE("features/infos/ctor") {
|
||||
registry db;
|
||||
|
||||
db(
|
||||
namespace_{"vmath"}(
|
||||
class_<ivec2>{"ivec2"}(
|
||||
ctor_<>{}(data_{"info", "void ctor"s}),
|
||||
ctor_<const ivec2&>{}(data_{"info", "copy ctor"s}),
|
||||
ctor_<int>{}(data_{"info", "int ctor"s}),
|
||||
ctor_<int, int>{}(data_{"info", "int,int ctor"s})
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
const class_info ivec2_info = db.get_class_by_path("vmath::ivec2");
|
||||
REQUIRE(ivec2_info);
|
||||
|
||||
SUBCASE("void") {
|
||||
const ctor_info ci = ivec2_info.get_ctor_by_args();
|
||||
REQUIRE(ci);
|
||||
|
||||
REQUIRE(ci.get_data_by_name("info"));
|
||||
CHECK(ci.get_data_by_name("info").value().equals("void ctor"s));
|
||||
|
||||
{
|
||||
const ctor_info ci2 = ivec2_info.get_ctor_by_args(std::array<any_type, 0>{});
|
||||
const ctor_info ci3 = ivec2_info.get_ctor_by_args(std::vector<any_type>{});
|
||||
REQUIRE(ci2);
|
||||
REQUIRE(ci3);
|
||||
CHECK(ci.type().id() == ci2.type().id());
|
||||
CHECK(ci.type().id() == ci2.type().id());
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("int") {
|
||||
const ctor_info ci = ivec2_info.get_ctor_by_args<int>();
|
||||
REQUIRE(ci);
|
||||
|
||||
REQUIRE(ci.get_data_by_name("info"));
|
||||
CHECK(ci.get_data_by_name("info").value().equals("int ctor"s));
|
||||
|
||||
{
|
||||
const ctor_info ci2 = ivec2_info.get_ctor_by_args(std::array<any_type, 1>{
|
||||
type_db::get<int>()});
|
||||
const ctor_info ci3 = ivec2_info.get_ctor_by_args(std::vector<any_type>{
|
||||
type_db::get<int>()});
|
||||
REQUIRE(ci2);
|
||||
REQUIRE(ci3);
|
||||
CHECK(ci.type().id() == ci2.type().id());
|
||||
CHECK(ci.type().id() == ci2.type().id());
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("const ivec2&") {
|
||||
const ctor_info ci = ivec2_info.get_ctor_by_args<const ivec2&>();
|
||||
REQUIRE(ci);
|
||||
|
||||
REQUIRE(ci.get_data_by_name("info"));
|
||||
CHECK(ci.get_data_by_name("info").value().equals("copy ctor"s));
|
||||
|
||||
{
|
||||
const ctor_info ci2 = ivec2_info.get_ctor_by_args(std::array<any_type, 1>{
|
||||
type_db::get<const ivec2&>()});
|
||||
const ctor_info ci3 = ivec2_info.get_ctor_by_args(std::vector<any_type>{
|
||||
type_db::get<const ivec2&>()});
|
||||
REQUIRE(ci2);
|
||||
REQUIRE(ci3);
|
||||
CHECK(ci.type().id() == ci2.type().id());
|
||||
CHECK(ci.type().id() == ci2.type().id());
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("int,int") {
|
||||
const ctor_info ci = ivec2_info.get_ctor_by_args<int,int>();
|
||||
REQUIRE(ci);
|
||||
|
||||
REQUIRE(ci.get_data_by_name("info"));
|
||||
CHECK(ci.get_data_by_name("info").value().equals("int,int ctor"s));
|
||||
|
||||
{
|
||||
const ctor_info ci2 = ivec2_info.get_ctor_by_args(std::array<any_type, 2>{
|
||||
type_db::get<int>(),
|
||||
type_db::get<int>()});
|
||||
const ctor_info ci3 = ivec2_info.get_ctor_by_args(std::vector<any_type>{
|
||||
type_db::get<int>(),
|
||||
type_db::get<int>()});
|
||||
REQUIRE(ci2);
|
||||
REQUIRE(ci3);
|
||||
CHECK(ci.type().id() == ci2.type().id());
|
||||
CHECK(ci.type().id() == ci2.type().id());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
30
untests/features/types/base_type_tests.cpp
Normal file
30
untests/features/types/base_type_tests.cpp
Normal file
@@ -0,0 +1,30 @@
|
||||
/*******************************************************************************
|
||||
* 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 "_types_fwd.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
using namespace meta_hpp;
|
||||
using namespace std::string_literals;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
struct base {
|
||||
virtual ~base() = 0;
|
||||
};
|
||||
|
||||
struct derived final : base {
|
||||
};
|
||||
}
|
||||
|
||||
TEST_CASE("features/types/base") {
|
||||
base_type bt{typename_arg<base>, typename_arg<derived>};
|
||||
|
||||
CHECK(bt.base_class_type().id() == type_db::get<base>().id());
|
||||
CHECK(bt.derived_class_type().id() == type_db::get<derived>().id());
|
||||
}
|
||||
Reference in New Issue
Block a user