diff --git a/headers/meta.hpp/meta_utilities/arg.hpp b/headers/meta.hpp/meta_utilities/arg.hpp index 9e30664..529c24e 100644 --- a/headers/meta.hpp/meta_utilities/arg.hpp +++ b/headers/meta.hpp/meta_utilities/arg.hpp @@ -200,8 +200,7 @@ namespace meta_hpp::detail const any_type& from_data_type = from_type_array.get_data_type(); if ( to_data_type == from_data_type ) { - void* to_ptr = static_cast(data_); - return static_cast(to_ptr); + return static_cast(data_); } 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(data_); if ( to_data_type == from_data_type ) { - void* to_data_ptr = *from_data_ptr; - return static_cast(to_data_ptr); + return static_cast(*from_data_ptr); } 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& from_data_class = from_data_type.as_class(); - void* to_data_ptr = detail::pointer_upcast(*from_data_ptr, from_data_class, to_data_class); - return static_cast(to_data_ptr); + void* to_ptr = detail::pointer_upcast(*from_data_ptr, from_data_class, to_data_class); + return static_cast(to_ptr); } } } if constexpr ( std::is_reference_v ) { if ( to_type == from_type ) { - void* to_ptr = static_cast(data_); - if constexpr ( std::is_lvalue_reference_v ) { - return *static_cast(to_ptr); + return *static_cast(data_); } if constexpr ( std::is_rvalue_reference_v ) { - return std::move(*static_cast(to_ptr)); + return std::move(*static_cast(data_)); } } diff --git a/untests/meta_states/method_tests.cpp b/untests/meta_states/method_tests.cpp index 7ab50c6..884a049 100644 --- a/untests/meta_states/method_tests.cpp +++ b/untests/meta_states/method_tests.cpp @@ -8,7 +8,12 @@ namespace { - struct clazz { + struct base { + virtual ~base() = default; + virtual int pure_virtual_method() = 0; + }; + + struct clazz : base { clazz() = default; clazz(clazz&&) = delete; @@ -36,10 +41,14 @@ namespace int const_method_rref() const && { return 11; } int const_method_noexcept_rref() const && noexcept { return 12; } + + // + + int pure_virtual_method() override { return -1; } }; struct derived_clazz : clazz { - [[maybe_unused]] derived_clazz() = default; + int pure_virtual_method() override { return -2; } }; struct clazz2 {}; @@ -48,10 +57,12 @@ namespace TEST_CASE("meta/meta_states/method") { namespace meta = meta_hpp; - meta::class_() - .base_(); + meta::class_() + .method_("pure_virtual_method", &base::pure_virtual_method); meta::class_() + .base_() + .method_("non_const_method", &clazz::non_const_method) .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_noexcept_rref", &clazz::const_method_noexcept_rref); + meta::class_() + .base_(); + const meta::class_type ct = meta::resolve_type(); REQUIRE(ct); @@ -627,4 +641,30 @@ TEST_CASE("meta/meta_states/method") { static_assert(std::is_invocable_v); static_assert(std::is_invocable_v); } + + 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()); + CHECK(mi.get_type().get_return_type() == meta::resolve_type()); + CHECK(mi.get_type().get_flags() == meta::method_flags{}); + } + + { + clazz cl; + CHECK(mi.is_invocable_with()); + CHECK(mi.invoke(cl) == -1); + } + + { + derived_clazz dcl; + CHECK(mi.is_invocable_with()); + CHECK(mi.invoke(dcl) == -2); + } + } } diff --git a/untests/meta_utilities/arg6_tests.cpp b/untests/meta_utilities/arg6_tests.cpp new file mode 100644 index 0000000..25ea23f --- /dev/null +++ b/untests/meta_utilities/arg6_tests.cpp @@ -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()); + + 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()); + + 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); + } +}