mirror of
https://github.com/BlackMATov/meta.hpp.git
synced 2025-12-14 11:40:35 +07:00
simple dtors
This commit is contained in:
@@ -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"
|
||||
|
||||
@@ -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<>>;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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_()
|
||||
|
||||
@@ -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;
|
||||
|
||||
114
headers/meta.hpp/meta_states/dtor.hpp
Normal file
114
headers/meta.hpp/meta_states/dtor.hpp
Normal 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);
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
28
headers/meta.hpp/meta_traits/dtor_traits.hpp
Normal file
28
headers/meta.hpp/meta_traits/dtor_traits.hpp
Normal 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;
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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_)}
|
||||
|
||||
@@ -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>());
|
||||
|
||||
57
headers/meta.hpp/meta_types/dtor_type.hpp
Normal file
57
headers/meta.hpp/meta_types/dtor_type.hpp
Normal 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;
|
||||
}
|
||||
}
|
||||
@@ -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_{};
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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>>
|
||||
|
||||
@@ -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,21 +182,28 @@ 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();
|
||||
|
||||
if constexpr ( !std::is_reference_v<Q> ) {
|
||||
return *static_cast<inst_class_cv*>(to_ptr);
|
||||
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);
|
||||
}
|
||||
|
||||
if constexpr ( std::is_lvalue_reference_v<Q> ) {
|
||||
return *static_cast<inst_class_cv*>(to_ptr);
|
||||
}
|
||||
|
||||
if constexpr ( std::is_rvalue_reference_v<Q> ) {
|
||||
return std::move(*static_cast<inst_class_cv*>(to_ptr));
|
||||
}
|
||||
}
|
||||
|
||||
if constexpr ( std::is_lvalue_reference_v<Q> ) {
|
||||
return *static_cast<inst_class_cv*>(to_ptr);
|
||||
}
|
||||
|
||||
if constexpr ( std::is_rvalue_reference_v<Q> ) {
|
||||
return std::move(*static_cast<inst_class_cv*>(to_ptr));
|
||||
}
|
||||
throw std::logic_error("bad instance cast");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
{
|
||||
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(clazz_type.destroy(nullptr));
|
||||
CHECK(clazz_type.destroy(meta::value{nullptr}));
|
||||
}
|
||||
|
||||
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>();
|
||||
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);
|
||||
{
|
||||
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(clazz_type.destroy(v));
|
||||
|
||||
//TODO: dtor!!!
|
||||
CHECK(clazz_type.destroy(nullptr));
|
||||
CHECK(clazz_type.destroy(meta::value{nullptr}));
|
||||
}
|
||||
|
||||
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>();
|
||||
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);
|
||||
{
|
||||
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(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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user