use uerror in is_invokable_with functions

This commit is contained in:
BlackMATov
2023-02-17 22:29:21 +07:00
parent 72c4d54b60
commit 36e76ccd93
16 changed files with 638 additions and 374 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -128,7 +128,7 @@ namespace
[[maybe_unused]] [[maybe_unused]]
void meta_invoke_function_1(benchmark::State &state) { void meta_invoke_function_1(benchmark::State &state) {
meta::function f = meta_bench_scope.get_function("static_function_1"); meta::function f = meta_bench_scope.get_function("static_function_1");
META_HPP_ASSERT(f.is_valid()); META_HPP_ASSERT(!f.is_empty());
for ( auto _ : state ) { for ( auto _ : state ) {
f(static_angle); f(static_angle);
@@ -138,7 +138,7 @@ namespace
[[maybe_unused]] [[maybe_unused]]
void meta_invoke_function_2(benchmark::State &state) { void meta_invoke_function_2(benchmark::State &state) {
meta::function f = meta_bench_scope.get_function("static_function_2"); meta::function f = meta_bench_scope.get_function("static_function_2");
META_HPP_ASSERT(f.is_valid()); META_HPP_ASSERT(!f.is_empty());
for ( auto _ : state ) { for ( auto _ : state ) {
f(static_angle, vmath::unit3_x<float>); f(static_angle, vmath::unit3_x<float>);
@@ -148,7 +148,7 @@ namespace
[[maybe_unused]] [[maybe_unused]]
void meta_invoke_function_3(benchmark::State &state) { void meta_invoke_function_3(benchmark::State &state) {
meta::function f = meta_bench_scope.get_function("static_function_3"); meta::function f = meta_bench_scope.get_function("static_function_3");
META_HPP_ASSERT(f.is_valid()); META_HPP_ASSERT(!f.is_empty());
for ( auto _ : state ) { for ( auto _ : state ) {
f(static_angle, vmath::unit3_x<float>, 2.f); f(static_angle, vmath::unit3_x<float>, 2.f);
@@ -158,7 +158,7 @@ namespace
[[maybe_unused]] [[maybe_unused]]
void meta_invoke_function_4(benchmark::State &state) { void meta_invoke_function_4(benchmark::State &state) {
meta::function f = meta_bench_scope.get_function("static_function_4"); meta::function f = meta_bench_scope.get_function("static_function_4");
META_HPP_ASSERT(f.is_valid()); META_HPP_ASSERT(!f.is_empty());
for ( auto _ : state ) { for ( auto _ : state ) {
f(static_angle, vmath::unit3_x<float>, 2.f, vmath::midentity3<float>); f(static_angle, vmath::unit3_x<float>, 2.f, vmath::midentity3<float>);

View File

@@ -59,6 +59,13 @@ TEST_CASE("meta/meta_states/dtor") {
CHECK(dtor.get_type().get_owner_type() == meta::resolve_type<clazz_opened_dtor>()); CHECK(dtor.get_type().get_owner_type() == meta::resolve_type<clazz_opened_dtor>());
CHECK(dtor.get_type().get_flags() == meta::destructor_flags::is_noexcept); CHECK(dtor.get_type().get_flags() == meta::destructor_flags::is_noexcept);
CHECK(dtor.is_invocable_with<clazz_opened_dtor*>());
CHECK(dtor.is_invocable_with(meta::make_uvalue<clazz_opened_dtor*>(nullptr)));
CHECK_FALSE(dtor.is_invocable_with<clazz_opened_dtor>());
CHECK_FALSE(dtor.is_invocable_with<clazz_closed_dtor*>());
CHECK_FALSE(dtor.is_invocable_with<const clazz_opened_dtor*>());
} }
SUBCASE("virtual_dtor") { SUBCASE("virtual_dtor") {

View File

@@ -23,6 +23,7 @@ namespace meta_hpp::detail
enum class error_code { enum class error_code {
no_error, no_error,
bad_const_access,
bad_uvalue_access, bad_uvalue_access,
bad_uresult_access, bad_uresult_access,
@@ -32,13 +33,15 @@ namespace meta_hpp::detail
arity_mismatch, arity_mismatch,
instance_type_mismatch, instance_type_mismatch,
argument_types_mismatch, argument_type_mismatch,
}; };
inline const char* get_error_code_message(error_code error) noexcept { inline const char* get_error_code_message(error_code error) noexcept {
switch ( error ) { switch ( error ) {
case error_code::no_error: case error_code::no_error:
return "no error"; return "no error";
case error_code::bad_const_access:
return "bad const access";
case error_code::bad_uvalue_access: case error_code::bad_uvalue_access:
return "bad uvalue access"; return "bad uvalue access";
case error_code::bad_uresult_access: case error_code::bad_uresult_access:
@@ -53,8 +56,8 @@ namespace meta_hpp::detail
return "arity mismatch"; return "arity mismatch";
case error_code::instance_type_mismatch: case error_code::instance_type_mismatch:
return "instance type mismatch"; return "instance type mismatch";
case error_code::argument_types_mismatch: case error_code::argument_type_mismatch:
return "argument types mismatch"; return "argument type mismatch";
} }
META_HPP_ASSERT(false); META_HPP_ASSERT(false);

View File

@@ -362,9 +362,8 @@ namespace meta_hpp::detail
} }
break; break;
} }
throw_exception(error_code::bad_argument_cast);
} }
throw_exception(error_code::bad_argument_cast);
} }
} }

View File

@@ -83,7 +83,7 @@ namespace meta_hpp
using namespace detail; using namespace detail;
type_registry& registry{type_registry::instance()}; type_registry& registry{type_registry::instance()};
const std::array<uarg_base, sizeof...(Args)> vargs{uarg_base{registry, type_list<Args>{}}...}; const std::array<uarg_base, sizeof...(Args)> vargs{uarg_base{registry, type_list<Args>{}}...};
return raw_function_is_invocable_with<Function>(registry, vargs); return !raw_function_invoke_error<Function>(registry, vargs);
} }
template < detail::function_pointer_kind Function, typename... Args > template < detail::function_pointer_kind Function, typename... Args >
@@ -91,7 +91,7 @@ namespace meta_hpp
using namespace detail; using namespace detail;
type_registry& registry{type_registry::instance()}; type_registry& registry{type_registry::instance()};
const std::array<uarg_base, sizeof...(Args)> vargs{uarg_base{registry, std::forward<Args>(args)}...}; const std::array<uarg_base, sizeof...(Args)> vargs{uarg_base{registry, std::forward<Args>(args)}...};
return raw_function_is_invocable_with<Function>(registry, vargs); return !raw_function_invoke_error<Function>(registry, vargs);
} }
} }
@@ -112,7 +112,7 @@ namespace meta_hpp
using namespace detail; using namespace detail;
type_registry& registry{type_registry::instance()}; type_registry& registry{type_registry::instance()};
const uinst_base vinst{registry, type_list<Instance>{}}; const uinst_base vinst{registry, type_list<Instance>{}};
return raw_member_is_gettable_with<Member>(registry, vinst); return !raw_member_getter_error<Member>(registry, vinst);
} }
template < detail::member_pointer_kind Member, typename Instance > template < detail::member_pointer_kind Member, typename Instance >
@@ -120,7 +120,7 @@ namespace meta_hpp
using namespace detail; using namespace detail;
type_registry& registry{type_registry::instance()}; type_registry& registry{type_registry::instance()};
const uinst_base vinst{registry, std::forward<Instance>(instance)}; const uinst_base vinst{registry, std::forward<Instance>(instance)};
return raw_member_is_gettable_with<Member>(registry, vinst); return !raw_member_getter_error<Member>(registry, vinst);
} }
} }
@@ -142,7 +142,7 @@ namespace meta_hpp
type_registry& registry{type_registry::instance()}; type_registry& registry{type_registry::instance()};
const uinst_base vinst{registry, type_list<Instance>{}}; const uinst_base vinst{registry, type_list<Instance>{}};
const std::array<uarg_base, sizeof...(Args)> vargs{uarg_base{registry, type_list<Args>{}}...}; const std::array<uarg_base, sizeof...(Args)> vargs{uarg_base{registry, type_list<Args>{}}...};
return raw_method_is_invocable_with<Method>(registry, vinst, vargs); return !raw_method_invoke_error<Method>(registry, vinst, vargs);
} }
template < detail::method_pointer_kind Method, typename Instance, typename... Args > template < detail::method_pointer_kind Method, typename Instance, typename... Args >
@@ -151,6 +151,6 @@ namespace meta_hpp
type_registry& registry{type_registry::instance()}; type_registry& registry{type_registry::instance()};
const uinst_base vinst{registry, std::forward<Instance>(instance)}; const uinst_base vinst{registry, std::forward<Instance>(instance)};
const std::array<uarg_base, sizeof...(Args)> vargs{uarg_base{registry, std::forward<Args>(args)}...}; const std::array<uarg_base, sizeof...(Args)> vargs{uarg_base{registry, std::forward<Args>(args)}...};
return raw_method_is_invocable_with<Method>(registry, vinst, vargs); return !raw_method_invoke_error<Method>(registry, vinst, vargs);
} }
} }

View File

@@ -9,6 +9,7 @@
#include "meta_base.hpp" #include "meta_base.hpp"
#include "meta_indices.hpp" #include "meta_indices.hpp"
#include "meta_types.hpp" #include "meta_types.hpp"
#include "meta_uresult.hpp"
#include "meta_uvalue.hpp" #include "meta_uvalue.hpp"
#include "meta_detail/state_family.hpp" #include "meta_detail/state_family.hpp"
@@ -81,34 +82,34 @@ namespace meta_hpp
} }
template < typename Policy > template < typename Policy >
concept constructor_policy_kind // concept constructor_policy_kind //
= std::is_same_v<Policy, constructor_policy::as_object_t> // = std::is_same_v<Policy, constructor_policy::as_object_t> //
|| std::is_same_v<Policy, constructor_policy::as_raw_pointer_t> // || std::is_same_v<Policy, constructor_policy::as_raw_pointer_t> //
|| std::is_same_v<Policy, constructor_policy::as_shared_pointer_t>; // || std::is_same_v<Policy, constructor_policy::as_shared_pointer_t>;
template < typename Policy > template < typename Policy >
concept function_policy_kind // concept function_policy_kind //
= std::is_same_v<Policy, function_policy::as_copy_t> // = std::is_same_v<Policy, function_policy::as_copy_t> //
|| std::is_same_v<Policy, function_policy::discard_return_t> // || std::is_same_v<Policy, function_policy::discard_return_t> //
|| std::is_same_v<Policy, function_policy::return_reference_as_pointer_t>; // || std::is_same_v<Policy, function_policy::return_reference_as_pointer_t>;
template < typename Policy > template < typename Policy >
concept member_policy_kind // concept member_policy_kind //
= std::is_same_v<Policy, member_policy::as_copy_t> // = std::is_same_v<Policy, member_policy::as_copy_t> //
|| std::is_same_v<Policy, member_policy::as_pointer_t> // || std::is_same_v<Policy, member_policy::as_pointer_t> //
|| std::is_same_v<Policy, member_policy::as_reference_wrapper_t>; // || std::is_same_v<Policy, member_policy::as_reference_wrapper_t>;
template < typename Policy > template < typename Policy >
concept method_policy_kind // concept method_policy_kind //
= std::is_same_v<Policy, method_policy::as_copy_t> // = std::is_same_v<Policy, method_policy::as_copy_t> //
|| std::is_same_v<Policy, method_policy::discard_return_t> // || std::is_same_v<Policy, method_policy::discard_return_t> //
|| std::is_same_v<Policy, method_policy::return_reference_as_pointer_t>; // || std::is_same_v<Policy, method_policy::return_reference_as_pointer_t>;
template < typename Policy > template < typename Policy >
concept variable_policy_kind // concept variable_policy_kind //
= std::is_same_v<Policy, variable_policy::as_copy_t> // = std::is_same_v<Policy, variable_policy::as_copy_t> //
|| std::is_same_v<Policy, variable_policy::as_pointer_t> // || std::is_same_v<Policy, variable_policy::as_pointer_t> //
|| std::is_same_v<Policy, variable_policy::as_reference_wrapper_t>; // || std::is_same_v<Policy, variable_policy::as_reference_wrapper_t>;
} }
namespace meta_hpp namespace meta_hpp
@@ -202,9 +203,15 @@ namespace meta_hpp
[[nodiscard]] destructor_type get_type() const noexcept; [[nodiscard]] destructor_type get_type() const noexcept;
template < typename Arg > template < typename Arg >
bool destroy(Arg&& arg) const; void destroy(Arg&& arg) const;
void destroy_at(void* mem) const; void destroy_at(void* mem) const;
template < typename Arg >
[[nodiscard]] bool is_invocable_with() const noexcept;
template < typename Arg >
[[nodiscard]] bool is_invocable_with(Arg&& arg) const noexcept;
}; };
class evalue final : public state_base<evalue> { class evalue final : public state_base<evalue> {
@@ -313,6 +320,9 @@ namespace meta_hpp
template < typename Instance, typename... Args > template < typename Instance, typename... Args >
std::optional<uvalue> safe_invoke(Instance&& instance, Args&&... args) const; std::optional<uvalue> safe_invoke(Instance&& instance, Args&&... args) const;
template < typename Instance, typename... Args >
uresult try_invoke(Instance&& instance, Args&&... args) const;
template < typename Instance, typename... Args > template < typename Instance, typename... Args >
uvalue operator()(Instance&& instance, Args&&... args) const; uvalue operator()(Instance&& instance, Args&&... args) const;
@@ -439,14 +449,14 @@ namespace meta_hpp::detail
struct constructor_state final : intrusive_ref_counter<constructor_state> { struct constructor_state final : intrusive_ref_counter<constructor_state> {
using create_impl = fixed_function<uvalue(std::span<const uarg>)>; using create_impl = fixed_function<uvalue(std::span<const uarg>)>;
using create_at_impl = fixed_function<uvalue(void*, std::span<const uarg>)>; using create_at_impl = fixed_function<uvalue(void*, std::span<const uarg>)>;
using is_invocable_with_impl = fixed_function<bool(std::span<const uarg_base>)>; using create_error_impl = fixed_function<uerror(std::span<const uarg_base>)>;
constructor_index index; constructor_index index;
metadata_map metadata; metadata_map metadata;
create_impl create{}; create_impl create{};
create_at_impl create_at{}; create_at_impl create_at{};
is_invocable_with_impl is_invocable_with{}; create_error_impl create_error{};
argument_list arguments{}; argument_list arguments{};
template < constructor_policy_kind Policy, class_kind Class, typename... Args > template < constructor_policy_kind Policy, class_kind Class, typename... Args >
@@ -455,14 +465,16 @@ namespace meta_hpp::detail
}; };
struct destructor_state final : intrusive_ref_counter<destructor_state> { struct destructor_state final : intrusive_ref_counter<destructor_state> {
using destroy_impl = fixed_function<bool(const uarg&)>; using destroy_impl = fixed_function<void(const uarg&)>;
using destroy_at_impl = fixed_function<void(void*)>; using destroy_at_impl = fixed_function<void(void*)>;
using destroy_error_impl = fixed_function<uerror(const uarg_base&)>;
destructor_index index; destructor_index index;
metadata_map metadata; metadata_map metadata;
destroy_impl destroy{}; destroy_impl destroy{};
destroy_at_impl destroy_at{}; destroy_at_impl destroy_at{};
destroy_error_impl destroy_error{};
template < class_kind Class > template < class_kind Class >
[[nodiscard]] static destructor_state_ptr make(metadata_map metadata); [[nodiscard]] static destructor_state_ptr make(metadata_map metadata);
@@ -483,13 +495,13 @@ namespace meta_hpp::detail
struct function_state final : intrusive_ref_counter<function_state> { struct function_state final : intrusive_ref_counter<function_state> {
using invoke_impl = fixed_function<uvalue(std::span<const uarg>)>; using invoke_impl = fixed_function<uvalue(std::span<const uarg>)>;
using is_invocable_with_impl = fixed_function<bool(std::span<const uarg_base>)>; using invoke_error_impl = fixed_function<uerror(std::span<const uarg_base>)>;
function_index index; function_index index;
metadata_map metadata; metadata_map metadata;
invoke_impl invoke{}; invoke_impl invoke{};
is_invocable_with_impl is_invocable_with{}; invoke_error_impl invoke_error{};
argument_list arguments{}; argument_list arguments{};
template < function_policy_kind Policy, function_pointer_kind Function > template < function_policy_kind Policy, function_pointer_kind Function >
@@ -501,16 +513,16 @@ namespace meta_hpp::detail
using getter_impl = fixed_function<uvalue(const uinst&)>; using getter_impl = fixed_function<uvalue(const uinst&)>;
using setter_impl = fixed_function<void(const uinst&, const uarg&)>; using setter_impl = fixed_function<void(const uinst&, const uarg&)>;
using is_gettable_with_impl = fixed_function<bool(const uinst_base&)>; using getter_error_impl = fixed_function<uerror(const uinst_base&)>;
using is_settable_with_impl = fixed_function<bool(const uinst_base&, const uarg_base&)>; using setter_error_impl = fixed_function<uerror(const uinst_base&, const uarg_base&)>;
member_index index; member_index index;
metadata_map metadata; metadata_map metadata;
getter_impl getter{}; getter_impl getter{};
setter_impl setter{}; setter_impl setter{};
is_gettable_with_impl is_gettable_with{}; getter_error_impl getter_error{};
is_settable_with_impl is_settable_with{}; setter_error_impl setter_error{};
template < member_policy_kind Policy, member_pointer_kind Member > template < member_policy_kind Policy, member_pointer_kind Member >
[[nodiscard]] static member_state_ptr make(std::string name, Member member_ptr, metadata_map metadata); [[nodiscard]] static member_state_ptr make(std::string name, Member member_ptr, metadata_map metadata);
@@ -519,13 +531,13 @@ namespace meta_hpp::detail
struct method_state final : intrusive_ref_counter<method_state> { struct method_state final : intrusive_ref_counter<method_state> {
using invoke_impl = fixed_function<uvalue(const uinst&, std::span<const uarg>)>; using invoke_impl = fixed_function<uvalue(const uinst&, std::span<const uarg>)>;
using is_invocable_with_impl = fixed_function<bool(const uinst_base&, std::span<const uarg_base>)>; using invoke_error_impl = fixed_function<uerror(const uinst_base&, std::span<const uarg_base>)>;
method_index index; method_index index;
metadata_map metadata; metadata_map metadata;
invoke_impl invoke{}; invoke_impl invoke{};
is_invocable_with_impl is_invocable_with{}; invoke_error_impl invoke_error{};
argument_list arguments{}; argument_list arguments{};
template < method_policy_kind Policy, method_pointer_kind Method > template < method_policy_kind Policy, method_pointer_kind Method >
@@ -548,14 +560,14 @@ namespace meta_hpp::detail
struct variable_state final : intrusive_ref_counter<variable_state> { struct variable_state final : intrusive_ref_counter<variable_state> {
using getter_impl = fixed_function<uvalue()>; using getter_impl = fixed_function<uvalue()>;
using setter_impl = fixed_function<void(const uarg&)>; using setter_impl = fixed_function<void(const uarg&)>;
using is_settable_with_impl = fixed_function<bool(const uarg_base&)>; using setter_error_impl = fixed_function<uerror(const uarg_base&)>;
variable_index index; variable_index index;
metadata_map metadata; metadata_map metadata;
getter_impl getter{}; getter_impl getter{};
setter_impl setter{}; setter_impl setter{};
is_settable_with_impl is_settable_with{}; setter_error_impl setter_error{};
template < variable_policy_kind Policy, pointer_kind Pointer > template < variable_policy_kind Policy, pointer_kind Pointer >
[[nodiscard]] static variable_state_ptr make(std::string name, Pointer variable_ptr, metadata_map metadata); [[nodiscard]] static variable_state_ptr make(std::string name, Pointer variable_ptr, metadata_map metadata);

View File

@@ -80,12 +80,19 @@ namespace meta_hpp::detail
} }
template < class_kind Class, typename... Args > template < class_kind Class, typename... Args >
bool raw_constructor_is_invocable_with(type_registry& registry, std::span<const uarg_base> args) { uerror raw_constructor_create_error(type_registry& registry, std::span<const uarg_base> args) {
using ct = constructor_traits<Class, Args...>; using ct = constructor_traits<Class, Args...>;
using argument_types = typename ct::argument_types; using argument_types = typename ct::argument_types;
return args.size() == ct::arity // if ( args.size() != ct::arity ) {
&& can_cast_all_uargs<argument_types>(registry, args); return uerror{error_code::arity_mismatch};
}
if ( !can_cast_all_uargs<argument_types>(registry, args) ) {
return uerror{error_code::argument_type_mismatch};
}
return uerror{error_code::no_error};
} }
} }
@@ -106,9 +113,9 @@ namespace meta_hpp::detail
} }
template < class_kind Class, typename... Args > template < class_kind Class, typename... Args >
constructor_state::is_invocable_with_impl make_constructor_is_invocable_with(type_registry& registry) { constructor_state::create_error_impl make_constructor_create_error(type_registry& registry) {
return [&registry](std::span<const uarg_base> args) { // return [&registry](std::span<const uarg_base> args) { //
return raw_constructor_is_invocable_with<Class, Args...>(registry, args); return raw_constructor_create_error<Class, Args...>(registry, args);
}; };
} }
@@ -140,7 +147,7 @@ namespace meta_hpp::detail
constructor_state state{constructor_index{registry.resolve_constructor_type<Class, Args...>()}, std::move(metadata)}; constructor_state state{constructor_index{registry.resolve_constructor_type<Class, Args...>()}, std::move(metadata)};
state.create = make_constructor_create<Policy, Class, Args...>(registry); state.create = make_constructor_create<Policy, Class, Args...>(registry);
state.create_at = make_constructor_create_at<Class, Args...>(registry); state.create_at = make_constructor_create_at<Class, Args...>(registry);
state.is_invocable_with = make_constructor_is_invocable_with<Class, Args...>(registry); state.create_error = make_constructor_create_error<Class, Args...>(registry);
state.arguments = make_constructor_arguments<Class, Args...>(); state.arguments = make_constructor_arguments<Class, Args...>();
return make_intrusive<constructor_state>(std::move(state)); return make_intrusive<constructor_state>(std::move(state));
} }
@@ -189,7 +196,7 @@ namespace meta_hpp
using namespace detail; using namespace detail;
type_registry& registry{type_registry::instance()}; type_registry& registry{type_registry::instance()};
const std::array<uarg_base, sizeof...(Args)> vargs{uarg_base{registry, type_list<Args>{}}...}; const std::array<uarg_base, sizeof...(Args)> vargs{uarg_base{registry, type_list<Args>{}}...};
return state_->is_invocable_with(vargs); return !state_->create_error(vargs);
} }
template < typename... Args > template < typename... Args >
@@ -197,7 +204,7 @@ namespace meta_hpp
using namespace detail; using namespace detail;
type_registry& registry{type_registry::instance()}; type_registry& registry{type_registry::instance()};
const std::array<uarg_base, sizeof...(Args)> vargs{uarg_base{registry, std::forward<Args>(args)}...}; const std::array<uarg_base, sizeof...(Args)> vargs{uarg_base{registry, std::forward<Args>(args)}...};
return state_->is_invocable_with(vargs); return !state_->create_error(vargs);
} }
inline argument constructor::get_argument(std::size_t position) const noexcept { inline argument constructor::get_argument(std::size_t position) const noexcept {

View File

@@ -16,16 +16,16 @@
namespace meta_hpp::detail namespace meta_hpp::detail
{ {
template < class_kind Class > template < class_kind Class >
bool raw_destructor_destroy(type_registry& registry, const uarg& arg) { void raw_destructor_destroy(type_registry& registry, const uarg& arg) {
using dt = destructor_traits<Class>; using dt = destructor_traits<Class>;
using class_type = typename dt::class_type; using class_type = typename dt::class_type;
if ( !arg.can_cast_to<class_type*>(registry) ) { META_HPP_ASSERT( //
return false; 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(); std::unique_ptr<class_type>{arg.cast<class_type*>(registry)}.reset();
return true;
} }
template < class_kind Class > template < class_kind Class >
@@ -35,6 +35,18 @@ namespace meta_hpp::detail
std::destroy_at(static_cast<class_type*>(mem)); std::destroy_at(static_cast<class_type*>(mem));
} }
template < class_kind Class >
uerror raw_destructor_destroy_error(type_registry& registry, const uarg_base& arg) {
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 namespace meta_hpp::detail
@@ -50,6 +62,13 @@ namespace meta_hpp::detail
destructor_state::destroy_at_impl make_destructor_destroy_at() { destructor_state::destroy_at_impl make_destructor_destroy_at() {
return &raw_destructor_destroy_at<Class>; return &raw_destructor_destroy_at<Class>;
} }
template < class_kind Class >
destructor_state::destroy_error_impl make_destructor_destroy_error(type_registry& registry) {
return [&registry](const uarg_base& arg) { //
return raw_destructor_destroy_error<Class>(registry, arg);
};
}
} }
namespace meta_hpp::detail namespace meta_hpp::detail
@@ -64,6 +83,7 @@ namespace meta_hpp::detail
destructor_state state{destructor_index{registry.resolve_destructor_type<Class>()}, std::move(metadata)}; destructor_state state{destructor_index{registry.resolve_destructor_type<Class>()}, std::move(metadata)};
state.destroy = make_destructor_destroy<Class>(registry); state.destroy = make_destructor_destroy<Class>(registry);
state.destroy_at = make_destructor_destroy_at<Class>(); 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)); return make_intrusive<destructor_state>(std::move(state));
} }
} }
@@ -75,7 +95,7 @@ namespace meta_hpp
} }
template < typename Arg > template < typename Arg >
bool destructor::destroy(Arg&& arg) const { void destructor::destroy(Arg&& arg) const {
using namespace detail; using namespace detail;
type_registry& registry{type_registry::instance()}; type_registry& registry{type_registry::instance()};
const uarg varg{registry, std::forward<Arg>(arg)}; const uarg varg{registry, std::forward<Arg>(arg)};
@@ -85,4 +105,20 @@ namespace meta_hpp
inline void destructor::destroy_at(void* mem) const { inline void destructor::destroy_at(void* mem) const {
state_->destroy_at(mem); state_->destroy_at(mem);
} }
template < typename Arg >
bool destructor::is_invocable_with() 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 >
bool destructor::is_invocable_with(Arg&& arg) const noexcept {
using namespace detail;
type_registry& registry{type_registry::instance()};
const uarg_base varg{registry, std::forward<Arg>(arg)};
return !state_->destroy_error(varg);
}
} }

View File

@@ -64,12 +64,19 @@ namespace meta_hpp::detail
} }
template < function_pointer_kind Function > template < function_pointer_kind Function >
bool raw_function_is_invocable_with(type_registry& registry, std::span<const uarg_base> args) { uerror raw_function_invoke_error(type_registry& registry, std::span<const uarg_base> args) {
using ft = function_traits<Function>; using ft = function_traits<Function>;
using argument_types = typename ft::argument_types; using argument_types = typename ft::argument_types;
return args.size() == ft::arity // if ( args.size() != ft::arity ) {
&& can_cast_all_uargs<argument_types>(registry, args); return uerror{error_code::arity_mismatch};
}
if ( !can_cast_all_uargs<argument_types>(registry, args) ) {
return uerror{error_code::argument_type_mismatch};
}
return uerror{error_code::no_error};
} }
} }
@@ -83,9 +90,9 @@ namespace meta_hpp::detail
} }
template < function_pointer_kind Function > template < function_pointer_kind Function >
function_state::is_invocable_with_impl make_function_is_invocable_with(type_registry& registry) { function_state::invoke_error_impl make_function_invoke_error(type_registry& registry) {
return [&registry](std::span<const uarg_base> args) { // return [&registry](std::span<const uarg_base> args) { //
return raw_function_is_invocable_with<Function>(registry, args); return raw_function_invoke_error<Function>(registry, args);
}; };
} }
@@ -116,7 +123,7 @@ namespace meta_hpp::detail
type_registry& registry{type_registry::instance()}; type_registry& registry{type_registry::instance()};
function_state state{function_index{registry.resolve_type<Function>(), std::move(name)}, std::move(metadata)}; function_state state{function_index{registry.resolve_type<Function>(), std::move(name)}, std::move(metadata)};
state.invoke = make_function_invoke<Policy>(registry, function_ptr); state.invoke = make_function_invoke<Policy>(registry, function_ptr);
state.is_invocable_with = make_function_is_invocable_with<Function>(registry); state.invoke_error = make_function_invoke_error<Function>(registry);
state.arguments = make_function_arguments<Function>(); state.arguments = make_function_arguments<Function>();
return make_intrusive<function_state>(std::move(state)); return make_intrusive<function_state>(std::move(state));
} }
@@ -158,7 +165,7 @@ namespace meta_hpp
using namespace detail; using namespace detail;
type_registry& registry{type_registry::instance()}; type_registry& registry{type_registry::instance()};
const std::array<uarg_base, sizeof...(Args)> vargs{uarg_base{registry, type_list<Args>{}}...}; const std::array<uarg_base, sizeof...(Args)> vargs{uarg_base{registry, type_list<Args>{}}...};
return state_->is_invocable_with(vargs); return !state_->invoke_error(vargs);
} }
template < typename... Args > template < typename... Args >
@@ -166,7 +173,7 @@ namespace meta_hpp
using namespace detail; using namespace detail;
type_registry& registry{type_registry::instance()}; type_registry& registry{type_registry::instance()};
const std::array<uarg_base, sizeof...(Args)> vargs{uarg_base{registry, std::forward<Args>(args)}...}; const std::array<uarg_base, sizeof...(Args)> vargs{uarg_base{registry, std::forward<Args>(args)}...};
return state_->is_invocable_with(vargs); return !state_->invoke_error(vargs);
} }
inline argument function::get_argument(std::size_t position) const noexcept { inline argument function::get_argument(std::size_t position) const noexcept {

View File

@@ -76,11 +76,21 @@ namespace meta_hpp::detail
} }
template < member_pointer_kind Member > template < member_pointer_kind Member >
bool raw_member_is_gettable_with(type_registry& registry, const uinst_base& inst) { uerror raw_member_getter_error(type_registry& registry, const uinst_base& inst) {
using mt = member_traits<Member>; using mt = member_traits<Member>;
using class_type = typename mt::class_type; using class_type = typename mt::class_type;
return inst.can_cast_to<const class_type>(registry); if ( inst.is_inst_const() ) {
if ( !inst.can_cast_to<const class_type>(registry) ) {
return uerror{error_code::bad_instance_cast};
}
} else {
if ( !inst.can_cast_to<class_type>(registry) ) {
return uerror{error_code::bad_instance_cast};
}
}
return uerror{error_code::no_error};
} }
} }
@@ -119,7 +129,7 @@ namespace meta_hpp::detail
} }
template < member_pointer_kind Member > template < member_pointer_kind Member >
bool raw_member_is_settable_with(type_registry& registry, const uinst_base& inst, const uarg_base& arg) { uerror raw_member_setter_error(type_registry& registry, const uinst_base& inst, const uarg_base& arg) {
using mt = member_traits<Member>; using mt = member_traits<Member>;
using class_type = typename mt::class_type; using class_type = typename mt::class_type;
using value_type = typename mt::value_type; using value_type = typename mt::value_type;
@@ -128,11 +138,21 @@ namespace meta_hpp::detail
(void)registry; (void)registry;
(void)inst; (void)inst;
(void)arg; (void)arg;
return false; return uerror{error_code::bad_const_access};
} else { } else {
return !inst.is_inst_const() // if ( inst.is_inst_const() ) {
&& inst.can_cast_to<class_type>(registry) // return uerror{error_code::bad_const_access};
&& arg.can_cast_to<value_type>(registry); // }
if ( !inst.can_cast_to<class_type>(registry) ) {
return uerror{error_code::instance_type_mismatch};
}
if ( !arg.can_cast_to<value_type>(registry) ) {
return uerror{error_code::argument_type_mismatch};
}
return uerror{error_code::no_error};
} }
} }
} }
@@ -147,9 +167,9 @@ namespace meta_hpp::detail
} }
template < member_pointer_kind Member > template < member_pointer_kind Member >
member_state::is_gettable_with_impl make_member_is_gettable_with(type_registry& registry) { member_state::getter_error_impl make_member_getter_error(type_registry& registry) {
return [&registry](const uinst_base& inst) { // return [&registry](const uinst_base& inst) { //
return raw_member_is_gettable_with<Member>(registry, inst); return raw_member_getter_error<Member>(registry, inst);
}; };
} }
@@ -161,9 +181,9 @@ namespace meta_hpp::detail
} }
template < member_pointer_kind Member > template < member_pointer_kind Member >
member_state::is_settable_with_impl make_member_is_settable_with(type_registry& registry) { member_state::setter_error_impl make_member_setter_error(type_registry& registry) {
return [&registry](const uinst_base& inst, const uarg_base& arg) { // return [&registry](const uinst_base& inst, const uarg_base& arg) { //
return raw_member_is_settable_with<Member>(registry, inst, arg); return raw_member_setter_error<Member>(registry, inst, arg);
}; };
} }
} }
@@ -180,8 +200,8 @@ namespace meta_hpp::detail
member_state state{member_index{registry.resolve_type<Member>(), std::move(name)}, std::move(metadata)}; member_state state{member_index{registry.resolve_type<Member>(), std::move(name)}, std::move(metadata)};
state.getter = make_member_getter<Policy>(registry, member_ptr); state.getter = make_member_getter<Policy>(registry, member_ptr);
state.setter = make_member_setter(registry, member_ptr); state.setter = make_member_setter(registry, member_ptr);
state.is_gettable_with = make_member_is_gettable_with<Member>(registry); state.getter_error = make_member_getter_error<Member>(registry);
state.is_settable_with = make_member_is_settable_with<Member>(registry); state.setter_error = make_member_setter_error<Member>(registry);
return make_intrusive<member_state>(std::move(state)); return make_intrusive<member_state>(std::move(state));
} }
} }
@@ -255,7 +275,7 @@ namespace meta_hpp
using namespace detail; using namespace detail;
type_registry& registry{type_registry::instance()}; type_registry& registry{type_registry::instance()};
const uinst_base vinst{registry, type_list<Instance>{}}; const uinst_base vinst{registry, type_list<Instance>{}};
return state_->is_gettable_with(vinst); return !state_->getter_error(vinst);
} }
template < typename Instance > template < typename Instance >
@@ -263,7 +283,7 @@ namespace meta_hpp
using namespace detail; using namespace detail;
type_registry& registry{type_registry::instance()}; type_registry& registry{type_registry::instance()};
const uinst_base vinst{registry, std::forward<Instance>(instance)}; const uinst_base vinst{registry, std::forward<Instance>(instance)};
return state_->is_gettable_with(vinst); return !state_->getter_error(vinst);
} }
template < typename Instance, typename Value > template < typename Instance, typename Value >
@@ -272,7 +292,7 @@ namespace meta_hpp
type_registry& registry{type_registry::instance()}; type_registry& registry{type_registry::instance()};
const uinst_base vinst{registry, type_list<Instance>{}}; const uinst_base vinst{registry, type_list<Instance>{}};
const uarg_base vvalue{registry, type_list<Value>{}}; const uarg_base vvalue{registry, type_list<Value>{}};
return state_->is_settable_with(vinst, vvalue); return !state_->setter_error(vinst, vvalue);
} }
template < typename Instance, typename Value > template < typename Instance, typename Value >
@@ -281,6 +301,6 @@ namespace meta_hpp
type_registry& registry{type_registry::instance()}; type_registry& registry{type_registry::instance()};
const uinst_base vinst{registry, std::forward<Instance>(instance)}; const uinst_base vinst{registry, std::forward<Instance>(instance)};
const uarg_base vvalue{registry, std::forward<Value>(value)}; const uarg_base vvalue{registry, std::forward<Value>(value)};
return state_->is_settable_with(vinst, vvalue); return !state_->setter_error(vinst, vvalue);
} }
} }

View File

@@ -71,14 +71,24 @@ namespace meta_hpp::detail
} }
template < method_pointer_kind Method > template < method_pointer_kind Method >
bool raw_method_is_invocable_with(type_registry& registry, const uinst_base& inst, std::span<const uarg_base> args) { uerror raw_method_invoke_error(type_registry& registry, const uinst_base& inst, std::span<const uarg_base> args) {
using mt = method_traits<Method>; using mt = method_traits<Method>;
using qualified_type = typename mt::qualified_type; using qualified_type = typename mt::qualified_type;
using argument_types = typename mt::argument_types; using argument_types = typename mt::argument_types;
return args.size() == mt::arity // if ( args.size() != mt::arity ) {
&& inst.can_cast_to<qualified_type>(registry) // return uerror{error_code::arity_mismatch};
&& can_cast_all_uargs<argument_types>(registry, args); }
if ( !inst.can_cast_to<qualified_type>(registry) ) {
return uerror{error_code::instance_type_mismatch};
}
if ( !can_cast_all_uargs<argument_types>(registry, args) ) {
return uerror{error_code::argument_type_mismatch};
}
return uerror{error_code::no_error};
} }
} }
@@ -92,9 +102,9 @@ namespace meta_hpp::detail
} }
template < method_pointer_kind Method > template < method_pointer_kind Method >
method_state::is_invocable_with_impl make_method_is_invocable_with(type_registry& registry) { method_state::invoke_error_impl make_method_invoke_error(type_registry& registry) {
return [&registry](const uinst_base& inst, std::span<const uarg_base> args) { return [&registry](const uinst_base& inst, std::span<const uarg_base> args) {
return raw_method_is_invocable_with<Method>(registry, inst, args); return raw_method_invoke_error<Method>(registry, inst, args);
}; };
} }
@@ -125,7 +135,7 @@ namespace meta_hpp::detail
type_registry& registry{type_registry::instance()}; type_registry& registry{type_registry::instance()};
method_state state{method_index{registry.resolve_type<Method>(), std::move(name)}, std::move(metadata)}; method_state state{method_index{registry.resolve_type<Method>(), std::move(name)}, std::move(metadata)};
state.invoke = make_method_invoke<Policy>(registry, method_ptr); state.invoke = make_method_invoke<Policy>(registry, method_ptr);
state.is_invocable_with = make_method_is_invocable_with<Method>(registry); state.invoke_error = make_method_invoke_error<Method>(registry);
state.arguments = make_method_arguments<Method>(); state.arguments = make_method_arguments<Method>();
return make_intrusive<method_state>(std::move(state)); return make_intrusive<method_state>(std::move(state));
} }
@@ -158,6 +168,24 @@ namespace meta_hpp
return std::nullopt; return std::nullopt;
} }
template < typename Instance, typename... Args >
uresult method::try_invoke(Instance&& instance, Args&&... args) const {
using namespace detail;
type_registry& registry{type_registry::instance()};
{
const uinst_base vinst{registry, type_list<Instance>{}};
const std::array<uarg_base, sizeof...(Args)> vargs{uarg_base{registry, type_list<Args>{}}...};
if ( const uerror err = state_->invoke_error(vinst, vargs) ) {
return err;
}
}
const uinst vinst{registry, std::forward<Instance>(instance)};
const std::array<uarg, sizeof...(Args)> vargs{uarg{registry, std::forward<Args>(args)}...};
return state_->invoke(vinst, vargs);
}
template < typename Instance, typename... Args > template < typename Instance, typename... Args >
uvalue method::operator()(Instance&& instance, Args&&... args) const { uvalue method::operator()(Instance&& instance, Args&&... args) const {
return invoke(std::forward<Instance>(instance), std::forward<Args>(args)...); return invoke(std::forward<Instance>(instance), std::forward<Args>(args)...);
@@ -169,7 +197,7 @@ namespace meta_hpp
type_registry& registry{type_registry::instance()}; type_registry& registry{type_registry::instance()};
const uinst_base vinst{registry, type_list<Instance>{}}; const uinst_base vinst{registry, type_list<Instance>{}};
const std::array<uarg_base, sizeof...(Args)> vargs{uarg_base{registry, type_list<Args>{}}...}; const std::array<uarg_base, sizeof...(Args)> vargs{uarg_base{registry, type_list<Args>{}}...};
return state_->is_invocable_with(vinst, vargs); return !state_->invoke_error(vinst, vargs);
} }
template < typename Instance, typename... Args > template < typename Instance, typename... Args >
@@ -178,7 +206,7 @@ namespace meta_hpp
type_registry& registry{type_registry::instance()}; type_registry& registry{type_registry::instance()};
const uinst_base vinst{registry, std::forward<Instance>(instance)}; const uinst_base vinst{registry, std::forward<Instance>(instance)};
const std::array<uarg_base, sizeof...(Args)> vargs{uarg_base{registry, std::forward<Args>(args)}...}; const std::array<uarg_base, sizeof...(Args)> vargs{uarg_base{registry, std::forward<Args>(args)}...};
return state_->is_invocable_with(vinst, vargs); return !state_->invoke_error(vinst, vargs);
} }
inline argument method::get_argument(std::size_t position) const noexcept { inline argument method::get_argument(std::size_t position) const noexcept {

View File

@@ -68,16 +68,19 @@ namespace meta_hpp::detail
} }
template < pointer_kind Pointer > template < pointer_kind Pointer >
bool raw_variable_is_settable_with(type_registry& registry, const uarg_base& arg) { uerror raw_variable_setter_error(type_registry& registry, const uarg_base& arg) {
using pt = pointer_traits<Pointer>; using pt = pointer_traits<Pointer>;
using data_type = typename pt::data_type; using data_type = typename pt::data_type;
if constexpr ( std::is_const_v<data_type> ) { if constexpr ( std::is_const_v<data_type> ) {
(void)registry; (void)registry;
(void)arg; (void)arg;
return false; return uerror{error_code::bad_const_access};
} else { } else {
return arg.can_cast_to<data_type>(registry); if ( !arg.can_cast_to<data_type>(registry) ) {
return uerror{error_code::argument_type_mismatch};
}
return uerror{error_code::no_error};
} }
} }
} }
@@ -99,9 +102,9 @@ namespace meta_hpp::detail
} }
template < pointer_kind Pointer > template < pointer_kind Pointer >
variable_state::is_settable_with_impl make_variable_is_settable_with(type_registry& registry) { variable_state::setter_error_impl make_variable_setter_error(type_registry& registry) {
return [&registry](const uarg_base& arg) { // return [&registry](const uarg_base& arg) { //
return raw_variable_is_settable_with<Pointer>(registry, arg); return raw_variable_setter_error<Pointer>(registry, arg);
}; };
} }
} }
@@ -118,7 +121,7 @@ namespace meta_hpp::detail
variable_state state{variable_index{registry.resolve_type<Pointer>(), std::move(name)}, std::move(metadata)}; variable_state state{variable_index{registry.resolve_type<Pointer>(), std::move(name)}, std::move(metadata)};
state.getter = make_variable_getter<Policy>(registry, variable_ptr); state.getter = make_variable_getter<Policy>(registry, variable_ptr);
state.setter = make_variable_setter(registry, variable_ptr); state.setter = make_variable_setter(registry, variable_ptr);
state.is_settable_with = make_variable_is_settable_with<Pointer>(registry); state.setter_error = make_variable_setter_error<Pointer>(registry);
return make_intrusive<variable_state>(std::move(state)); return make_intrusive<variable_state>(std::move(state));
} }
} }
@@ -182,7 +185,7 @@ namespace meta_hpp
using namespace detail; using namespace detail;
type_registry& registry{type_registry::instance()}; type_registry& registry{type_registry::instance()};
const uarg_base vvalue{registry, type_list<Value>{}}; const uarg_base vvalue{registry, type_list<Value>{}};
return state_->is_settable_with(vvalue); return !state_->setter_error(vvalue);
} }
template < typename Value > template < typename Value >
@@ -190,6 +193,6 @@ namespace meta_hpp
using namespace detail; using namespace detail;
type_registry& registry{type_registry::instance()}; type_registry& registry{type_registry::instance()};
const uarg_base vvalue{registry, std::forward<Value>(value)}; const uarg_base vvalue{registry, std::forward<Value>(value)};
return state_->is_settable_with(vvalue); return !state_->setter_error(vvalue);
} }
} }

View File

@@ -113,7 +113,10 @@ namespace meta_hpp
template < typename Arg > template < typename Arg >
bool class_type::destroy(Arg&& arg) const { bool class_type::destroy(Arg&& arg) const {
if ( const destructor& dtor = get_destructor() ) { if ( const destructor& dtor = get_destructor() ) {
return dtor.destroy(std::forward<Arg>(arg)); if ( dtor.is_invocable_with(std::forward<Arg>(arg)) ) {
dtor.destroy(std::forward<Arg>(arg));
return true;
}
} }
return false; return false;
} }

View File

@@ -25,6 +25,9 @@ namespace meta_hpp
explicit uerror(error_code error) noexcept; explicit uerror(error_code error) noexcept;
uerror& operator=(error_code error) noexcept; uerror& operator=(error_code error) noexcept;
[[nodiscard]] bool has_error() const noexcept;
[[nodiscard]] explicit operator bool() const noexcept;
[[nodiscard]] error_code get_error() const noexcept; [[nodiscard]] error_code get_error() const noexcept;
void reset() noexcept; void reset() noexcept;
@@ -120,9 +123,6 @@ namespace meta_hpp
[[nodiscard]] bool has_value() const noexcept; [[nodiscard]] bool has_value() const noexcept;
[[nodiscard]] explicit operator bool() const noexcept; [[nodiscard]] explicit operator bool() const noexcept;
void reset() noexcept;
void swap(uresult& other) noexcept;
[[nodiscard]] uvalue& get_value() &; [[nodiscard]] uvalue& get_value() &;
[[nodiscard]] uvalue&& get_value() &&; [[nodiscard]] uvalue&& get_value() &&;
[[nodiscard]] const uvalue& get_value() const&; [[nodiscard]] const uvalue& get_value() const&;
@@ -130,6 +130,9 @@ namespace meta_hpp
[[nodiscard]] error_code get_error() const noexcept; [[nodiscard]] error_code get_error() const noexcept;
void reset() noexcept;
void swap(uresult& other) noexcept;
private: private:
uvalue value_{}; uvalue value_{};
error_code error_{error_code::no_error}; error_code error_{error_code::no_error};

View File

@@ -21,6 +21,14 @@ namespace meta_hpp
return *this; return *this;
} }
inline bool uerror::has_error() const noexcept {
return error_ != error_code::no_error;
}
inline uerror::operator bool() const noexcept {
return has_error();
}
inline error_code uerror::get_error() const noexcept { inline error_code uerror::get_error() const noexcept {
return error_; return error_;
} }
@@ -112,17 +120,6 @@ namespace meta_hpp
return has_value(); return has_value();
} }
inline void uresult::reset() noexcept {
value_ = uvalue{};
error_ = error_code::no_error;
}
inline void uresult::swap(uresult& other) noexcept {
using std::swap;
swap(value_, other.value_);
swap(error_, other.error_);
}
inline uvalue& uresult::get_value() & { inline uvalue& uresult::get_value() & {
return value_; return value_;
} }
@@ -143,4 +140,15 @@ namespace meta_hpp
inline error_code uresult::get_error() const noexcept { inline error_code uresult::get_error() const noexcept {
return error_; return error_;
} }
inline void uresult::reset() noexcept {
value_ = uvalue{};
error_ = error_code::no_error;
}
inline void uresult::swap(uresult& other) noexcept {
using std::swap;
swap(value_, other.value_);
swap(error_, other.error_);
}
} }