check class member pointers arg

This commit is contained in:
BlackMATov
2022-01-14 10:44:57 +07:00
parent c277dbfc1c
commit 0a1303e215
3 changed files with 122 additions and 14 deletions

View File

@@ -200,8 +200,7 @@ namespace meta_hpp::detail
const any_type& from_data_type = from_type_array.get_data_type(); const any_type& from_data_type = from_type_array.get_data_type();
if ( to_data_type == from_data_type ) { if ( to_data_type == from_data_type ) {
void* to_ptr = static_cast<void*>(data_); return static_cast<to_raw_type_cv>(data_);
return static_cast<to_raw_type_cv>(to_ptr);
} }
if ( to_data_type.is_class() && from_data_type.is_class() ) { if ( to_data_type.is_class() && from_data_type.is_class() ) {
@@ -223,30 +222,27 @@ namespace meta_hpp::detail
void** from_data_ptr = static_cast<void**>(data_); void** from_data_ptr = static_cast<void**>(data_);
if ( to_data_type == from_data_type ) { if ( to_data_type == from_data_type ) {
void* to_data_ptr = *from_data_ptr; return static_cast<to_raw_type_cv>(*from_data_ptr);
return static_cast<to_raw_type_cv>(to_data_ptr);
} }
if ( to_data_type.is_class() && from_data_type.is_class() ) { if ( to_data_type.is_class() && from_data_type.is_class() ) {
const class_type& to_data_class = to_data_type.as_class(); const class_type& to_data_class = to_data_type.as_class();
const class_type& from_data_class = from_data_type.as_class(); const class_type& from_data_class = from_data_type.as_class();
void* to_data_ptr = detail::pointer_upcast(*from_data_ptr, from_data_class, to_data_class); void* to_ptr = detail::pointer_upcast(*from_data_ptr, from_data_class, to_data_class);
return static_cast<to_raw_type_cv>(to_data_ptr); return static_cast<to_raw_type_cv>(to_ptr);
} }
} }
} }
if constexpr ( std::is_reference_v<To> ) { if constexpr ( std::is_reference_v<To> ) {
if ( to_type == from_type ) { if ( to_type == from_type ) {
void* to_ptr = static_cast<void*>(data_);
if constexpr ( std::is_lvalue_reference_v<To> ) { if constexpr ( std::is_lvalue_reference_v<To> ) {
return *static_cast<to_raw_type_cv*>(to_ptr); return *static_cast<to_raw_type_cv*>(data_);
} }
if constexpr ( std::is_rvalue_reference_v<To> ) { if constexpr ( std::is_rvalue_reference_v<To> ) {
return std::move(*static_cast<to_raw_type_cv*>(to_ptr)); return std::move(*static_cast<to_raw_type_cv*>(data_));
} }
} }

View File

@@ -8,7 +8,12 @@
namespace namespace
{ {
struct clazz { struct base {
virtual ~base() = default;
virtual int pure_virtual_method() = 0;
};
struct clazz : base {
clazz() = default; clazz() = default;
clazz(clazz&&) = delete; clazz(clazz&&) = delete;
@@ -36,10 +41,14 @@ namespace
int const_method_rref() const && { return 11; } int const_method_rref() const && { return 11; }
int const_method_noexcept_rref() const && noexcept { return 12; } int const_method_noexcept_rref() const && noexcept { return 12; }
//
int pure_virtual_method() override { return -1; }
}; };
struct derived_clazz : clazz { struct derived_clazz : clazz {
[[maybe_unused]] derived_clazz() = default; int pure_virtual_method() override { return -2; }
}; };
struct clazz2 {}; struct clazz2 {};
@@ -48,10 +57,12 @@ namespace
TEST_CASE("meta/meta_states/method") { TEST_CASE("meta/meta_states/method") {
namespace meta = meta_hpp; namespace meta = meta_hpp;
meta::class_<derived_clazz>() meta::class_<base>()
.base_<clazz>(); .method_("pure_virtual_method", &base::pure_virtual_method);
meta::class_<clazz>() meta::class_<clazz>()
.base_<base>()
.method_("non_const_method", &clazz::non_const_method) .method_("non_const_method", &clazz::non_const_method)
.method_("non_const_method_noexcept", &clazz::non_const_method_noexcept) .method_("non_const_method_noexcept", &clazz::non_const_method_noexcept)
@@ -70,6 +81,9 @@ TEST_CASE("meta/meta_states/method") {
.method_("const_method_rref", &clazz::const_method_rref) .method_("const_method_rref", &clazz::const_method_rref)
.method_("const_method_noexcept_rref", &clazz::const_method_noexcept_rref); .method_("const_method_noexcept_rref", &clazz::const_method_noexcept_rref);
meta::class_<derived_clazz>()
.base_<clazz>();
const meta::class_type ct = meta::resolve_type<clazz>(); const meta::class_type ct = meta::resolve_type<clazz>();
REQUIRE(ct); REQUIRE(ct);
@@ -627,4 +641,30 @@ TEST_CASE("meta/meta_states/method") {
static_assert(std::is_invocable_v<decltype(&clazz::const_method_noexcept_rref), derived_clazz&&>); static_assert(std::is_invocable_v<decltype(&clazz::const_method_noexcept_rref), derived_clazz&&>);
static_assert(std::is_invocable_v<decltype(&clazz::const_method_noexcept_rref), const derived_clazz&&>); static_assert(std::is_invocable_v<decltype(&clazz::const_method_noexcept_rref), const derived_clazz&&>);
} }
SUBCASE("pure_virtual_method") {
const meta::method mi = ct.get_method("pure_virtual_method");
REQUIRE(mi);
CHECK(mi.get_name() == "pure_virtual_method");
{
CHECK(mi.get_type().get_arity() == 0);
CHECK(mi.get_type().get_owner_type() == meta::resolve_type<base>());
CHECK(mi.get_type().get_return_type() == meta::resolve_type<int>());
CHECK(mi.get_type().get_flags() == meta::method_flags{});
}
{
clazz cl;
CHECK(mi.is_invocable_with<clazz&>());
CHECK(mi.invoke(cl) == -1);
}
{
derived_clazz dcl;
CHECK(mi.is_invocable_with<derived_clazz&>());
CHECK(mi.invoke(dcl) == -2);
}
}
} }

View File

@@ -0,0 +1,72 @@
/*******************************************************************************
* This file is part of the "https://github.com/blackmatov/meta.hpp"
* For conditions of distribution and use, see copyright notice in LICENSE.md
* Copyright (C) 2021, by Matvey Cherevko (blackmatov@gmail.com)
******************************************************************************/
#include "../meta_untests.hpp"
namespace
{
struct base {
virtual ~base() = default;
virtual int int_method() const = 0;
};
struct clazz : base {
int int_member{42};
int int_method() const override { return int_member; }
};
using int_member_t = int clazz::*;
using int_method_t = int (clazz::*)() const;
int func_with_member(const clazz& cl, int_member_t m) {
return std::invoke(m, cl);
}
int func_with_method(const clazz& cl, int_method_t m) {
return std::invoke(m, cl);
}
}
TEST_CASE("meta/meta_utilities/arg6") {
namespace meta = meta_hpp;
using meta::detail::arg;
const meta::scope scope = meta::local_scope_("scope")
.function_("func_with_member", &func_with_member)
.function_("func_with_method", &func_with_method);
SUBCASE("int_member") {
static_assert(sizeof(int_member_t) == 8);
const meta::function f = scope.get_function("func_with_member");
REQUIRE(f);
clazz cl;
CHECK(f.is_invocable_with<clazz&, int_member_t>());
CHECK(f.is_invocable_with(cl, &clazz::int_member));
CHECK(f.invoke(cl, &clazz::int_member) == 42);
CHECK(f.is_invocable_with(meta::value{cl}, meta::value{&clazz::int_member}));
CHECK(f.invoke(meta::value{cl}, meta::value{&clazz::int_member}) == 42);
}
SUBCASE("int_method") {
static_assert(sizeof(int_method_t) == 16);
const meta::function f = scope.get_function("func_with_method");
REQUIRE(f);
clazz cl;
CHECK(f.is_invocable_with<clazz&, int_method_t>());
CHECK(f.is_invocable_with(cl, &clazz::int_method));
CHECK(f.invoke(cl, &clazz::int_method) == 42);
CHECK(f.is_invocable_with(meta::value{cl}, meta::value{&clazz::int_method}));
CHECK(f.invoke(meta::value{cl}, meta::value{&clazz::int_method}) == 42);
}
}