simple dtors

This commit is contained in:
BlackMATov
2022-01-22 05:58:04 +07:00
parent b414e71d8f
commit a0a24ea94e
17 changed files with 507 additions and 79 deletions

View File

@@ -17,6 +17,7 @@
#include "meta_states.hpp"
#include "meta_states/ctor.hpp"
#include "meta_states/dtor.hpp"
#include "meta_states/evalue.hpp"
#include "meta_states/function.hpp"
#include "meta_states/member.hpp"
@@ -28,6 +29,7 @@
#include "meta_traits/array_traits.hpp"
#include "meta_traits/class_traits.hpp"
#include "meta_traits/ctor_traits.hpp"
#include "meta_traits/dtor_traits.hpp"
#include "meta_traits/enum_traits.hpp"
#include "meta_traits/function_traits.hpp"
#include "meta_traits/member_traits.hpp"
@@ -41,6 +43,7 @@
#include "meta_types/array_type.hpp"
#include "meta_types/class_type.hpp"
#include "meta_types/ctor_type.hpp"
#include "meta_types/dtor_type.hpp"
#include "meta_types/enum_type.hpp"
#include "meta_types/function_type.hpp"
#include "meta_types/member_type.hpp"

View File

@@ -86,6 +86,7 @@ namespace meta_hpp
namespace meta_hpp
{
class ctor;
class dtor;
class evalue;
class function;
class member;
@@ -96,6 +97,7 @@ namespace meta_hpp
namespace detail
{
struct ctor_state;
struct dtor_state;
struct evalue_state;
struct function_state;
struct member_state;
@@ -104,6 +106,7 @@ namespace meta_hpp
struct variable_state;
using ctor_state_ptr = std::shared_ptr<ctor_state>;
using dtor_state_ptr = std::shared_ptr<dtor_state>;
using evalue_state_ptr = std::shared_ptr<evalue_state>;
using function_state_ptr = std::shared_ptr<function_state>;
using member_state_ptr = std::shared_ptr<member_state>;
@@ -119,6 +122,7 @@ namespace meta_hpp
class array_type;
class class_type;
class ctor_type;
class dtor_type;
class enum_type;
class function_type;
class member_type;
@@ -135,6 +139,7 @@ namespace meta_hpp
struct array_type_data;
struct class_type_data;
struct ctor_type_data;
struct dtor_type_data;
struct enum_type_data;
struct function_type_data;
struct member_type_data;
@@ -149,6 +154,7 @@ namespace meta_hpp
using array_type_data_ptr = std::shared_ptr<array_type_data>;
using class_type_data_ptr = std::shared_ptr<class_type_data>;
using ctor_type_data_ptr = std::shared_ptr<ctor_type_data>;
using dtor_type_data_ptr = std::shared_ptr<dtor_type_data>;
using enum_type_data_ptr = std::shared_ptr<enum_type_data>;
using function_type_data_ptr = std::shared_ptr<function_type_data>;
using member_type_data_ptr = std::shared_ptr<member_type_data>;
@@ -164,6 +170,7 @@ namespace meta_hpp
namespace meta_hpp
{
struct ctor_index;
struct dtor_index;
struct evalue_index;
struct function_index;
struct member_index;
@@ -178,6 +185,7 @@ namespace meta_hpp
using enum_map = std::map<std::string, enum_type, std::less<>>;
using ctor_map = std::map<ctor_index, ctor, std::less<>>;
using dtor_map = std::map<dtor_index, dtor, std::less<>>;
using evalue_map = std::map<evalue_index, evalue, std::less<>>;
using function_map = std::map<function_index, function, std::less<>>;
using member_map = std::map<member_index, member, std::less<>>;

View File

@@ -14,6 +14,7 @@ namespace meta_hpp
array_,
class_,
ctor_,
dtor_,
enum_,
function_,
member_,
@@ -100,6 +101,12 @@ namespace meta_hpp::detail
using kind_type_data = ctor_type_data;
};
template <>
struct type_kind_traits<type_kind::dtor_> {
using kind_type = dtor_type;
using kind_type_data = dtor_type_data;
};
template <>
struct type_kind_traits<type_kind::enum_> {
using kind_type = enum_type;

View File

@@ -18,6 +18,11 @@ namespace meta_hpp
class_kind<Class> &&
requires(Args&&... args) { { Class{std::forward<Args>(args)...} }; };
template < typename Class >
concept class_bind_dtor_kind =
class_kind<Class> &&
requires(Class&& inst) { { inst.~Class() }; };
template < typename Class, typename Base >
concept class_bind_base_kind =
class_kind<Class> && class_kind<Base> &&
@@ -45,6 +50,9 @@ namespace meta_hpp
class_bind& ctor_(Policy = Policy{})
requires detail::class_bind_ctor_kind<Class, Args...>;
class_bind& dtor_()
requires detail::class_bind_dtor_kind<Class>;
template < detail::class_kind Base >
class_bind& base_()
requires detail::class_bind_base_kind<Class, Base>;

View File

@@ -31,6 +31,15 @@ namespace meta_hpp
return *this;
}
template < detail::class_kind Class >
class_bind<Class>& class_bind<Class>::dtor_()
requires detail::class_bind_dtor_kind<Class>
{
auto dtor_state = detail::dtor_state::make<Class>();
data_->dtors.emplace(dtor_state->index, std::move(dtor_state));
return *this;
}
template < detail::class_kind Class >
template < detail::class_kind Base >
class_bind<Class>& class_bind<Class>::base_()

View File

@@ -17,6 +17,7 @@ namespace meta_hpp
template < typename T >
concept state_family =
std::is_same_v<T, ctor> ||
std::is_same_v<T, dtor> ||
std::is_same_v<T, evalue> ||
std::is_same_v<T, function> ||
std::is_same_v<T, member> ||
@@ -153,6 +154,32 @@ namespace meta_hpp
detail::ctor_state_ptr state_;
};
class dtor final {
public:
explicit dtor() = default;
explicit dtor(detail::dtor_state_ptr state);
[[nodiscard]] bool is_valid() const noexcept;
[[nodiscard]] explicit operator bool() const noexcept;
[[nodiscard]] const dtor_index& get_index() const noexcept;
[[nodiscard]] const dtor_type& get_type() const noexcept;
template < typename Arg >
void invoke(Arg&& ptr) const;
template < typename Arg >
void operator()(Arg&& ptr) const;
template < typename Arg >
[[nodiscard]] bool is_invocable_with() const noexcept;
template < typename Arg >
[[nodiscard]] bool is_invocable_with(Arg&& ptr) const noexcept;
private:
detail::dtor_state_ptr state_;
};
class evalue final {
public:
explicit evalue() = default;
@@ -339,6 +366,18 @@ namespace meta_hpp::detail
[[nodiscard]] static ctor_state_ptr make();
};
struct dtor_state final {
using invoke_impl = std::function<void(const arg&)>;
using is_invocable_with_impl = std::function<bool(const arg_base&)>;
const dtor_index index;
const invoke_impl invoke;
const is_invocable_with_impl is_invocable_with;
template < class_kind Class >
[[nodiscard]] static dtor_state_ptr make();
};
struct evalue_state final {
const evalue_index index;
const value enum_value;

View File

@@ -0,0 +1,114 @@
/*******************************************************************************
* 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_base.hpp"
#include "../meta_states.hpp"
#include "../meta_types/dtor_type.hpp"
namespace meta_hpp::detail
{
template < class_kind Class >
void raw_dtor_invoke(const arg& ptr) {
using dt = dtor_traits<Class>;
using class_type = typename dt::class_type;
if ( !ptr.can_cast_to<class_type*>() ) {
throw std::logic_error("an attempt to call a destructor with an incorrect argument type");
}
class_type* raw_ptr = ptr.cast<class_type*>();
if ( raw_ptr ) {
raw_ptr->~Class();
}
}
template < class_kind Class >
bool raw_dtor_is_invocable_with(const arg_base& ptr) {
using dt = dtor_traits<Class>;
using class_type = typename dt::class_type;
return ptr.can_cast_to<class_type*>();
}
}
namespace meta_hpp::detail
{
template < class_kind Class >
dtor_state::invoke_impl make_dtor_invoke() {
using namespace std::placeholders;
return std::bind(&raw_dtor_invoke<Class>, _1);
}
template < class_kind Class >
dtor_state::is_invocable_with_impl make_dtor_is_invocable_with() {
using namespace std::placeholders;
return std::bind(&raw_dtor_is_invocable_with<Class>, _1);
}
}
namespace meta_hpp::detail
{
template < class_kind Class >
dtor_state_ptr dtor_state::make() {
dtor_index index{dtor_type_data::get_static<Class>()};
return std::make_shared<dtor_state>(dtor_state{
.index{std::move(index)},
.invoke{make_dtor_invoke<Class>()},
.is_invocable_with{make_dtor_is_invocable_with<Class>()},
});
}
}
namespace meta_hpp
{
inline dtor::dtor(detail::dtor_state_ptr state)
: state_{std::move(state)} {}
inline bool dtor::is_valid() const noexcept {
return !!state_;
}
inline dtor::operator bool() const noexcept {
return is_valid();
}
inline const dtor_index& dtor::get_index() const noexcept {
return state_->index;
}
inline const dtor_type& dtor::get_type() const noexcept {
return state_->index.type;
}
template < typename Arg >
void dtor::invoke(Arg&& ptr) const {
using namespace detail;
const arg varg{std::forward<Arg>(ptr)};
state_->invoke(varg);
}
template < typename Arg >
void dtor::operator()(Arg&& ptr) const {
invoke(std::forward<Arg>(ptr));
}
template < typename Arg >
bool dtor::is_invocable_with() const noexcept {
using namespace detail;
const arg_base varg{type_list<Arg>{}};
return state_->is_invocable_with(varg);
}
template < typename Arg >
bool dtor::is_invocable_with(Arg&& ptr) const noexcept {
using namespace detail;
const arg_base varg{std::forward<Arg>(ptr)};
return state_->is_invocable_with(varg);
}
}

View File

@@ -20,6 +20,9 @@ namespace meta_hpp::detail
template < class_kind Class, typename... Args >
struct ctor_traits;
template < class_kind Class >
struct dtor_traits;
template < enum_kind Enum >
struct enum_traits;
@@ -61,6 +64,10 @@ namespace meta_hpp
is_noexcept = 1 << 0,
};
enum class dtor_flags : std::uint32_t {
is_noexcept = 1 << 0,
};
enum class enum_flags : std::uint32_t {
is_scoped = 1 << 0,
};
@@ -100,6 +107,7 @@ namespace meta_hpp
ENUM_HPP_OPERATORS_DECL(array_flags)
ENUM_HPP_OPERATORS_DECL(class_flags)
ENUM_HPP_OPERATORS_DECL(ctor_flags)
ENUM_HPP_OPERATORS_DECL(dtor_flags)
ENUM_HPP_OPERATORS_DECL(enum_flags)
ENUM_HPP_OPERATORS_DECL(function_flags)
ENUM_HPP_OPERATORS_DECL(member_flags)

View File

@@ -0,0 +1,28 @@
/*******************************************************************************
* 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_base.hpp"
#include "../meta_traits.hpp"
namespace meta_hpp::detail
{
template < class_kind Class >
struct dtor_traits {
using class_type = Class;
[[nodiscard]] static constexpr bitflags<dtor_flags> make_flags() noexcept {
bitflags<dtor_flags> flags;
if constexpr ( std::is_nothrow_destructible_v<Class> ) {
flags.set(dtor_flags::is_noexcept);
}
return flags;
}
};
}

View File

@@ -68,6 +68,7 @@ namespace meta_hpp
std::is_same_v<T, array_type> ||
std::is_same_v<T, class_type> ||
std::is_same_v<T, ctor_type> ||
std::is_same_v<T, dtor_type> ||
std::is_same_v<T, enum_type> ||
std::is_same_v<T, function_type> ||
std::is_same_v<T, member_type> ||
@@ -132,6 +133,7 @@ namespace meta_hpp
any_type(const array_type& other) noexcept;
any_type(const class_type& other) noexcept;
any_type(const ctor_type& other) noexcept;
any_type(const dtor_type& other) noexcept;
any_type(const enum_type& other) noexcept;
any_type(const function_type& other) noexcept;
any_type(const member_type& other) noexcept;
@@ -145,6 +147,7 @@ namespace meta_hpp
[[nodiscard]] bool is_array() const noexcept;
[[nodiscard]] bool is_class() const noexcept;
[[nodiscard]] bool is_ctor() const noexcept;
[[nodiscard]] bool is_dtor() const noexcept;
[[nodiscard]] bool is_enum() const noexcept;
[[nodiscard]] bool is_function() const noexcept;
[[nodiscard]] bool is_member() const noexcept;
@@ -158,6 +161,7 @@ namespace meta_hpp
[[nodiscard]] array_type as_array() const noexcept;
[[nodiscard]] class_type as_class() const noexcept;
[[nodiscard]] ctor_type as_ctor() const noexcept;
[[nodiscard]] dtor_type as_dtor() const noexcept;
[[nodiscard]] enum_type as_enum() const noexcept;
[[nodiscard]] function_type as_function() const noexcept;
[[nodiscard]] member_type as_member() const noexcept;
@@ -208,6 +212,7 @@ namespace meta_hpp
[[nodiscard]] const std::vector<any_type>& get_argument_types() const noexcept;
[[nodiscard]] const ctor_map& get_ctors() const noexcept;
[[nodiscard]] const dtor_map& get_dtors() const noexcept;
[[nodiscard]] const class_set& get_bases() const noexcept;
[[nodiscard]] const function_map& get_functions() const noexcept;
[[nodiscard]] const member_map& get_members() const noexcept;
@@ -220,6 +225,9 @@ namespace meta_hpp
template < typename... Args >
[[nodiscard]] std::optional<value> operator()(Args&&... args) const;
template < typename Arg >
bool destroy(Arg&& ptr) const;
template < detail::class_kind Derived >
[[nodiscard]] bool is_base_of() const noexcept;
[[nodiscard]] bool is_base_of(const class_type& derived) const noexcept;
@@ -272,6 +280,23 @@ namespace meta_hpp
friend auto detail::data_access<ctor_type>(const ctor_type&);
};
class dtor_type final {
public:
dtor_type() = default;
dtor_type(detail::dtor_type_data_ptr data);
[[nodiscard]] bool is_valid() const noexcept;
[[nodiscard]] explicit operator bool() const noexcept;
[[nodiscard]] type_id get_id() const noexcept;
[[nodiscard]] bitflags<dtor_flags> get_flags() const noexcept;
[[nodiscard]] any_type get_class_type() const noexcept;
private:
detail::dtor_type_data_ptr data_;
friend auto detail::data_access<dtor_type>(const dtor_type&);
};
class enum_type final {
public:
enum_type() = default;
@@ -465,6 +490,7 @@ namespace meta_hpp::detail
const std::vector<any_type> argument_types;
ctor_map ctors;
dtor_map dtors;
class_set bases;
function_map functions;
member_map members;
@@ -498,6 +524,17 @@ namespace meta_hpp::detail
[[nodiscard]] static ctor_type_data_ptr get_static();
};
struct dtor_type_data final : type_data_base {
const bitflags<dtor_flags> flags;
const any_type class_type;
template < class_kind Class >
explicit dtor_type_data(type_list<Class>);
template < class_kind Class >
[[nodiscard]] static dtor_type_data_ptr get_static();
};
struct enum_type_data final : type_data_base {
const bitflags<enum_flags> flags;
const number_type underlying_type;
@@ -615,6 +652,21 @@ namespace meta_hpp
}
};
struct dtor_index final {
const dtor_type type;
explicit dtor_index(dtor_type type)
: type{std::move(type)} {}
[[nodiscard]] friend bool operator<(const dtor_index& l, const dtor_index& r) noexcept {
return l.type < r.type;
}
[[nodiscard]] friend bool operator==(const dtor_index& l, const dtor_index& r) noexcept {
return l.type == r.type;
}
};
struct evalue_index final {
const enum_type type;
const std::string name;

View File

@@ -39,6 +39,9 @@ namespace meta_hpp
inline any_type::any_type(const ctor_type& other) noexcept
: data_{detail::data_access(other)} {}
inline any_type::any_type(const dtor_type& other) noexcept
: data_{detail::data_access(other)} {}
inline any_type::any_type(const enum_type& other) noexcept
: data_{detail::data_access(other)} {}
@@ -78,6 +81,10 @@ namespace meta_hpp
return data_ && data_->kind == type_kind::ctor_;
}
inline bool any_type::is_dtor() const noexcept {
return data_ && data_->kind == type_kind::dtor_;
}
inline bool any_type::is_enum() const noexcept {
return data_ && data_->kind == type_kind::enum_;
}
@@ -132,6 +139,12 @@ namespace meta_hpp
: ctor_type{};
}
inline dtor_type any_type::as_dtor() const noexcept {
return is_dtor()
? dtor_type{std::static_pointer_cast<detail::dtor_type_data>(data_)}
: dtor_type{};
}
inline enum_type any_type::as_enum() const noexcept {
return is_enum()
? enum_type{std::static_pointer_cast<detail::enum_type_data>(data_)}

View File

@@ -78,6 +78,10 @@ namespace meta_hpp
return data_->ctors;
}
inline const dtor_map& class_type::get_dtors() const noexcept {
return data_->dtors;
}
inline const class_set& class_type::get_bases() const noexcept {
return data_->bases;
}
@@ -113,6 +117,17 @@ namespace meta_hpp
return create(std::forward<Args>(args)...);
}
template < typename Arg >
bool class_type::destroy(Arg&& ptr) const {
for ( auto&& dtor : data_->dtors ) {
if ( dtor.second.is_invocable_with(std::forward<Arg>(ptr)) ) {
dtor.second.invoke(std::forward<Arg>(ptr));
return true;
}
}
return false;
}
template < detail::class_kind Derived >
bool class_type::is_base_of() const noexcept {
return is_base_of(resolve_type<Derived>());

View File

@@ -0,0 +1,57 @@
/*******************************************************************************
* 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_base.hpp"
#include "../meta_types.hpp"
#include "../meta_traits/dtor_traits.hpp"
namespace meta_hpp::detail
{
template < class_kind Class >
struct dtor_tag {};
template < class_kind Class >
// NOLINTNEXTLINE(readability-named-parameter)
dtor_type_data::dtor_type_data(type_list<Class>)
: type_data_base{type_id{type_list<dtor_tag<Class>>{}}, type_kind::dtor_}
, flags{dtor_traits<Class>::make_flags()}
, class_type{resolve_type<typename dtor_traits<Class>::class_type>()} {}
template < class_kind Class >
dtor_type_data_ptr dtor_type_data::get_static() {
static dtor_type_data_ptr data = std::make_shared<dtor_type_data>(type_list<Class>{});
return data;
}
}
namespace meta_hpp
{
inline dtor_type::dtor_type(detail::dtor_type_data_ptr data)
: data_{std::move(data)} {}
inline bool dtor_type::is_valid() const noexcept {
return !!data_;
}
inline dtor_type::operator bool() const noexcept {
return is_valid();
}
inline type_id dtor_type::get_id() const noexcept {
return data_->id;
}
inline bitflags<dtor_flags> dtor_type::get_flags() const noexcept {
return data_->flags;
}
inline any_type dtor_type::get_class_type() const noexcept {
return data_->class_type;
}
}

View File

@@ -62,12 +62,13 @@ namespace meta_hpp::detail
template < typename T >
concept arg_lvalue_ref_kind =
(decay_non_uvalue_kind<T>) &&
(std::is_lvalue_reference_v<T>);
template < typename T >
concept arg_rvalue_ref_kind =
(!std::is_reference_v<T>) ||
(std::is_rvalue_reference_v<T>);
(decay_non_uvalue_kind<T>) &&
(!std::is_reference_v<T> || std::is_rvalue_reference_v<T>);
template < typename T >
concept inst_class_ref_kind =
@@ -76,12 +77,13 @@ namespace meta_hpp::detail
template < typename T >
concept inst_class_lvalue_ref_kind =
(decay_non_uvalue_kind<T>) &&
(std::is_lvalue_reference_v<T> && std::is_class_v<std::remove_reference_t<T>>);
template < typename T >
concept inst_class_rvalue_ref_kind =
(std::is_class_v<T>) ||
(std::is_rvalue_reference_v<T> && std::is_class_v<std::remove_reference_t<T>>);
(decay_non_uvalue_kind<T>) &&
(std::is_class_v<T> || (std::is_rvalue_reference_v<T> && std::is_class_v<std::remove_reference_t<T>>));
}
namespace meta_hpp::detail
@@ -194,11 +196,9 @@ namespace meta_hpp::detail
explicit arg_base(T&& v);
template < arg_lvalue_ref_kind T >
requires decay_non_uvalue_kind<T>
explicit arg_base(type_list<T>);
template < arg_rvalue_ref_kind T >
requires decay_non_uvalue_kind<T>
explicit arg_base(type_list<T>);
explicit arg_base(value& v);
@@ -293,13 +293,13 @@ namespace meta_hpp::detail
[[nodiscard]] bool is_rvalue() const noexcept;
[[nodiscard]] ref_types get_ref_type() const noexcept;
[[nodiscard]] const class_type& get_raw_type() const noexcept;
[[nodiscard]] const any_type& get_raw_type() const noexcept;
template < inst_class_ref_kind Q >
[[nodiscard]] bool can_cast_to() const noexcept;
private:
ref_types ref_type_{};
class_type raw_type_{};
any_type raw_type_{};
};
}

View File

@@ -22,7 +22,6 @@ namespace meta_hpp::detail
: arg_base{type_list<T&&>{}} {}
template < arg_lvalue_ref_kind T >
requires decay_non_uvalue_kind<T>
// NOLINTNEXTLINE(readability-named-parameter)
arg_base::arg_base(type_list<T>)
: ref_type_{std::is_const_v<std::remove_reference_t<T>>
@@ -31,7 +30,6 @@ namespace meta_hpp::detail
, raw_type_{resolve_type<std::remove_cvref_t<T>>()} {}
template < arg_rvalue_ref_kind T >
requires decay_non_uvalue_kind<T>
// NOLINTNEXTLINE(readability-named-parameter)
arg_base::arg_base(type_list<T>)
: ref_type_{std::is_const_v<std::remove_reference_t<T>>

View File

@@ -90,35 +90,19 @@ namespace meta_hpp::detail
inline inst_base::inst_base(value& v)
: ref_type_{ref_types::lvalue}
, raw_type_{v.get_type().as_class()} {
if ( !v.get_type().is_class() ) {
throw std::logic_error("an attempt to create an instance with a non-class value type");
}
}
, raw_type_{v.get_type()} {}
inline inst_base::inst_base(const value& v)
: ref_type_{ref_types::const_lvalue}
, raw_type_{v.get_type().as_class()} {
if ( !v.get_type().is_class() ) {
throw std::logic_error("an attempt to create an instance with a non-class value type");
}
}
, raw_type_{v.get_type()} {}
inline inst_base::inst_base(value&& v)
: ref_type_{ref_types::rvalue}
, raw_type_{v.get_type().as_class()} {
if ( !v.get_type().is_class() ) {
throw std::logic_error("an attempt to create an instance with a non-class value type");
}
}
, raw_type_{v.get_type()} {}
inline inst_base::inst_base(const value&& v)
: ref_type_{ref_types::const_rvalue}
, raw_type_{v.get_type().as_class()} {
if ( !v.get_type().is_class() ) {
throw std::logic_error("an attempt to create an instance with a non-class value type");
}
}
, raw_type_{v.get_type()} {}
inline bool inst_base::is_const() const noexcept {
return ref_type_ == ref_types::const_lvalue
@@ -139,7 +123,7 @@ namespace meta_hpp::detail
return ref_type_;
}
inline const class_type& inst_base::get_raw_type() const noexcept {
inline const any_type& inst_base::get_raw_type() const noexcept {
return raw_type_;
}
@@ -148,11 +132,12 @@ namespace meta_hpp::detail
using inst_class = typename inst_traits<Q>::class_type;
using inst_method = typename inst_traits<Q>::method_type;
const class_type& from_type = get_raw_type();
const class_type& to_type = resolve_type<inst_class>();
const any_type& from_type = get_raw_type();
const any_type& to_type = resolve_type<inst_class>();
const auto is_a = [](const class_type& base, const class_type& derived){
return base == derived || base.is_base_of(derived);
const auto is_a = [](const any_type& base, const any_type& derived){
return (base == derived)
|| (base.is_class() && derived.is_class() && base.as_class().is_base_of(derived.as_class()));
};
const auto is_invocable = [this](){
@@ -197,10 +182,14 @@ namespace meta_hpp::detail
using inst_class_cv = std::remove_reference_t<Q>;
using inst_class = std::remove_cv_t<inst_class_cv>;
const class_type& from_type = get_raw_type();
const class_type& to_type = resolve_type<inst_class>();
const any_type& from_type = get_raw_type();
const any_type& to_type = resolve_type<inst_class>();
void* to_ptr = detail::pointer_upcast(data_, from_type, to_type);
if ( from_type.is_class() && to_type.is_class() ) {
const class_type& from_class = from_type.as_class();
const class_type& to_class = to_type.as_class();
void* to_ptr = detail::pointer_upcast(data_, from_class, to_class);
if constexpr ( !std::is_reference_v<Q> ) {
return *static_cast<inst_class_cv*>(to_ptr);
@@ -214,4 +203,7 @@ namespace meta_hpp::detail
return std::move(*static_cast<inst_class_cv*>(to_ptr));
}
}
throw std::logic_error("bad instance cast");
}
}

View File

@@ -8,60 +8,137 @@
namespace
{
struct clazz_1 {
template < std::size_t N >
struct clazz {
int i{};
clazz_1(int i) : i{i} {}
clazz(int i)
: i{i} {
++ctor_counter;
}
clazz(clazz&& other)
: i{other.i} {
other.i = 0;
++move_ctor_counter;
}
clazz(const clazz& other)
: i{other.i} {
++copy_ctor_counter;
}
clazz& operator=(clazz&& other) = delete;
clazz& operator=(const clazz& other) = delete;
~clazz() {
++dtor_counter;
}
public:
static int ctor_counter;
static int dtor_counter;
static int move_ctor_counter;
static int copy_ctor_counter;
};
struct clazz_2 {
int i{};
clazz_2(int i) : i{i} {}
};
template < std::size_t N >
int clazz<N>::ctor_counter{0};
struct clazz_3 {
int i{};
clazz_3(int i) : i{i} {}
};
template < std::size_t N >
int clazz<N>::dtor_counter{0};
template < std::size_t N >
int clazz<N>::move_ctor_counter{0};
template < std::size_t N >
int clazz<N>::copy_ctor_counter{0};
}
TEST_CASE("meta/meta_states/ctor") {
namespace meta = meta_hpp;
meta::class_<clazz_1>()
.ctor_<int>(meta::ctor_policy::as_object{});
meta::class_<clazz<1>>()
.ctor_<int>(meta::ctor_policy::as_object{})
.dtor_();
meta::class_<clazz_2>()
.ctor_<int>(meta::ctor_policy::as_raw_pointer{});
meta::class_<clazz<2>>()
.ctor_<int>(meta::ctor_policy::as_raw_pointer{})
.dtor_();
meta::class_<clazz_3>()
.ctor_<int>(meta::ctor_policy::as_shared_pointer{});
meta::class_<clazz<3>>()
.ctor_<int>(meta::ctor_policy::as_shared_pointer{})
.dtor_();
SUBCASE("clazz_1") {
const meta::class_type clazz_type = meta::resolve_type<clazz_1>();
clazz<1>::ctor_counter = 0;
clazz<1>::dtor_counter = 0;
clazz<1>::move_ctor_counter = 0;
clazz<1>::copy_ctor_counter = 0;
clazz<2>::ctor_counter = 0;
clazz<2>::dtor_counter = 0;
clazz<2>::move_ctor_counter = 0;
clazz<2>::copy_ctor_counter = 0;
clazz<3>::ctor_counter = 0;
clazz<3>::dtor_counter = 0;
clazz<3>::move_ctor_counter = 0;
clazz<3>::copy_ctor_counter = 0;
SUBCASE("clazz<1>") {
const meta::class_type clazz_type = meta::resolve_type<clazz<1>>();
REQUIRE(clazz_type);
{
const meta::value v = clazz_type.create(10).value();
CHECK(v.get_type() == meta::resolve_type<clazz_1>());
CHECK(v.cast<clazz_1>().i == 10);
CHECK(v.get_type() == meta::resolve_type<clazz<1>>());
CHECK(v.cast<clazz<1>>().i == 10);
CHECK(clazz_type.destroy(nullptr));
CHECK(clazz_type.destroy(meta::value{nullptr}));
}
SUBCASE("clazz_2") {
const meta::class_type clazz_type = meta::resolve_type<clazz_2>();
CHECK(clazz<1>::ctor_counter == 1);
CHECK(clazz<1>::dtor_counter == 4);
CHECK(clazz<1>::move_ctor_counter == 3);
CHECK(clazz<1>::copy_ctor_counter == 0);
}
SUBCASE("clazz<2>") {
const meta::class_type clazz_type = meta::resolve_type<clazz<2>>();
REQUIRE(clazz_type);
{
const meta::value v = clazz_type.create(20).value();
CHECK(v.get_type() == meta::resolve_type<clazz_2*>());
CHECK(v.cast<clazz_2*>()->i == 20);
CHECK(v.get_type() == meta::resolve_type<clazz<2>*>());
CHECK(v.cast<clazz<2>*>()->i == 20);
CHECK(clazz_type.destroy(v));
//TODO: dtor!!!
CHECK(clazz_type.destroy(nullptr));
CHECK(clazz_type.destroy(meta::value{nullptr}));
}
SUBCASE("clazz_3") {
const meta::class_type clazz_type = meta::resolve_type<clazz_3>();
CHECK(clazz<2>::ctor_counter == 1);
CHECK(clazz<2>::dtor_counter == 1);
CHECK(clazz<2>::move_ctor_counter == 0);
CHECK(clazz<2>::copy_ctor_counter == 0);
}
SUBCASE("clazz<3>") {
const meta::class_type clazz_type = meta::resolve_type<clazz<3>>();
REQUIRE(clazz_type);
{
const meta::value v = clazz_type.create(30).value();
CHECK(v.get_type() == meta::resolve_type<std::shared_ptr<clazz_3>>());
CHECK(v.cast<std::shared_ptr<clazz_3>>()->i == 30);
CHECK(v.get_type() == meta::resolve_type<std::shared_ptr<clazz<3>>>());
CHECK(v.cast<std::shared_ptr<clazz<3>>>()->i == 30);
CHECK(clazz_type.destroy(nullptr));
CHECK(clazz_type.destroy(meta::value{nullptr}));
}
CHECK(clazz<3>::ctor_counter == 1);
CHECK(clazz<3>::dtor_counter == 1);
CHECK(clazz<3>::move_ctor_counter == 0);
CHECK(clazz<3>::copy_ctor_counter == 0);
}
}