mirror of
https://github.com/BlackMATov/meta.hpp.git
synced 2025-12-15 03:45:30 +07:00
164 lines
5.3 KiB
C++
164 lines
5.3 KiB
C++
/*******************************************************************************
|
|
* 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-2023, by Matvey Cherevko (blackmatov@gmail.com)
|
|
******************************************************************************/
|
|
|
|
#pragma once
|
|
|
|
#include "../meta_base.hpp"
|
|
#include "../meta_states.hpp"
|
|
|
|
#include "../meta_detail/type_registry.hpp"
|
|
#include "../meta_detail/value_utilities/uarg.hpp"
|
|
#include "../meta_types/destructor_type.hpp"
|
|
|
|
namespace meta_hpp::detail
|
|
{
|
|
template < class_kind Class >
|
|
void raw_destructor_destroy(type_registry& registry, const uarg& arg) {
|
|
using dt = destructor_traits<Class>;
|
|
using class_type = typename dt::class_type;
|
|
|
|
META_HPP_ASSERT( //
|
|
arg.can_cast_to<class_type*>(registry) //
|
|
&& "an attempt to call a destructor with an incorrect argument type"
|
|
);
|
|
|
|
std::unique_ptr<class_type>{arg.cast<class_type*>(registry)}.reset();
|
|
}
|
|
|
|
template < class_kind Class >
|
|
void raw_destructor_destroy_at(void* mem) {
|
|
using dt = destructor_traits<Class>;
|
|
using class_type = typename dt::class_type;
|
|
|
|
std::destroy_at(static_cast<class_type*>(mem));
|
|
}
|
|
|
|
template < class_kind Class >
|
|
uerror raw_destructor_destroy_error(type_registry& registry, const uarg_base& arg) noexcept {
|
|
using dt = destructor_traits<Class>;
|
|
using class_type = typename dt::class_type;
|
|
|
|
if ( !arg.can_cast_to<class_type*>(registry) ) {
|
|
return uerror{error_code::argument_type_mismatch};
|
|
}
|
|
|
|
return uerror{error_code::no_error};
|
|
}
|
|
}
|
|
|
|
namespace meta_hpp::detail
|
|
{
|
|
template < class_kind Class >
|
|
destructor_state::destroy_impl make_destructor_destroy(type_registry& registry) {
|
|
return [®istry](const uarg& arg) { //
|
|
return raw_destructor_destroy<Class>(registry, arg);
|
|
};
|
|
}
|
|
|
|
template < class_kind Class >
|
|
destructor_state::destroy_at_impl make_destructor_destroy_at() {
|
|
return &raw_destructor_destroy_at<Class>;
|
|
}
|
|
|
|
template < class_kind Class >
|
|
destructor_state::destroy_error_impl make_destructor_destroy_error(type_registry& registry) {
|
|
return [®istry](const uarg_base& arg) { //
|
|
return raw_destructor_destroy_error<Class>(registry, arg);
|
|
};
|
|
}
|
|
}
|
|
|
|
namespace meta_hpp::detail
|
|
{
|
|
inline destructor_state::destructor_state(destructor_index nindex, metadata_map nmetadata)
|
|
: index{nindex}
|
|
, metadata{std::move(nmetadata)} {}
|
|
|
|
template < class_kind Class >
|
|
destructor_state_ptr destructor_state::make(metadata_map metadata) {
|
|
type_registry& registry{type_registry::instance()};
|
|
|
|
destructor_state state{
|
|
destructor_index{registry.resolve_destructor_type<Class>()},
|
|
std::move(metadata),
|
|
};
|
|
|
|
state.destroy = make_destructor_destroy<Class>(registry);
|
|
state.destroy_at = make_destructor_destroy_at<Class>();
|
|
state.destroy_error = make_destructor_destroy_error<Class>(registry);
|
|
|
|
return make_intrusive<destructor_state>(std::move(state));
|
|
}
|
|
}
|
|
|
|
namespace meta_hpp
|
|
{
|
|
inline destructor_type destructor::get_type() const noexcept {
|
|
return state_->index.get_type();
|
|
}
|
|
|
|
template < typename Arg >
|
|
void destructor::destroy(Arg&& arg) const {
|
|
using namespace detail;
|
|
type_registry& registry{type_registry::instance()};
|
|
const uarg varg{registry, META_HPP_FWD(arg)};
|
|
return state_->destroy(varg);
|
|
}
|
|
|
|
template < typename Arg >
|
|
uresult destructor::try_destroy(Arg&& arg) const {
|
|
using namespace detail;
|
|
type_registry& registry{type_registry::instance()};
|
|
|
|
{
|
|
// doesn't actually move an 'arg', just checks conversion errors
|
|
const uarg_base varg{registry, META_HPP_FWD(arg)};
|
|
if ( const uerror err = state_->destroy_error(varg) ) {
|
|
return err;
|
|
}
|
|
}
|
|
|
|
const uarg varg{registry, META_HPP_FWD(arg)};
|
|
state_->destroy(varg);
|
|
return uerror{error_code::no_error};
|
|
}
|
|
|
|
inline void destructor::destroy_at(void* mem) const {
|
|
state_->destroy_at(mem);
|
|
}
|
|
|
|
inline uresult destructor::try_destroy_at(void* mem) const {
|
|
state_->destroy_at(mem);
|
|
return uerror{error_code::no_error};
|
|
}
|
|
|
|
template < typename Arg >
|
|
bool destructor::is_invocable_with() const noexcept {
|
|
return !check_invocable_error<Arg>();
|
|
}
|
|
|
|
template < typename Arg >
|
|
bool destructor::is_invocable_with(Arg&& arg) const noexcept {
|
|
return !check_invocable_error(META_HPP_FWD(arg));
|
|
}
|
|
|
|
template < typename Arg >
|
|
uerror destructor::check_invocable_error() const noexcept {
|
|
using namespace detail;
|
|
type_registry& registry{type_registry::instance()};
|
|
const uarg_base varg{registry, type_list<Arg>{}};
|
|
return state_->destroy_error(varg);
|
|
}
|
|
|
|
template < typename Arg >
|
|
uerror destructor::check_invocable_error(Arg&& arg) const noexcept {
|
|
using namespace detail;
|
|
type_registry& registry{type_registry::instance()};
|
|
const uarg_base varg{registry, META_HPP_FWD(arg)};
|
|
return state_->destroy_error(varg);
|
|
}
|
|
}
|