diff --git a/headers/meta.hpp/meta_detail/value_utilities/uarg.hpp b/headers/meta.hpp/meta_detail/value_utilities/uarg.hpp index 46dfff0..b9fb976 100644 --- a/headers/meta.hpp/meta_detail/value_utilities/uarg.hpp +++ b/headers/meta.hpp/meta_detail/value_utilities/uarg.hpp @@ -32,6 +32,9 @@ namespace meta_hpp::detail virtual ~uarg_base() = default; + template < typename T > + uarg_base(type_list) = delete; + template < decay_value_kind T > // NOLINTNEXTLINE(*-forwarding-reference-overload) explicit uarg_base(T&&) @@ -72,21 +75,11 @@ namespace meta_hpp::detail : ref_type_{ref_types::const_rvalue} , raw_type_{v.get_type()} {} - [[nodiscard]] bool is_const() const noexcept { + [[nodiscard]] bool is_ref_const() const noexcept { return ref_type_ == ref_types::const_lvalue || ref_type_ == ref_types::const_rvalue; } - [[nodiscard]] bool is_lvalue() const noexcept { - return ref_type_ == ref_types::lvalue - || ref_type_ == ref_types::const_lvalue; - } - - [[nodiscard]] bool is_rvalue() const noexcept { - return ref_type_ == ref_types::rvalue - || ref_type_ == ref_types::const_rvalue; - } - [[nodiscard]] ref_types get_ref_type() const noexcept { return ref_type_; } @@ -168,7 +161,7 @@ namespace meta_hpp::detail const bool to_type_ptr_readonly = to_type_ptr.get_flags().has(pointer_flags::is_readonly); const array_type& from_type_array = from_type.as_array(); - const bool from_type_array_readonly = is_const(); + const bool from_type_array_readonly = is_ref_const(); const any_type& to_data_type = to_type_ptr.get_data_type(); const any_type& from_data_type = from_type_array.get_data_type(); diff --git a/headers/meta.hpp/meta_detail/value_utilities/uinst.hpp b/headers/meta.hpp/meta_detail/value_utilities/uinst.hpp index 6ae886a..edaf144 100644 --- a/headers/meta.hpp/meta_detail/value_utilities/uinst.hpp +++ b/headers/meta.hpp/meta_detail/value_utilities/uinst.hpp @@ -32,6 +32,9 @@ namespace meta_hpp::detail virtual ~uinst_base() = default; + template < typename T > + uinst_base(type_list) = delete; + template < decay_value_kind T > // NOLINTNEXTLINE(*-forwarding-reference-overload) explicit uinst_base(T&&) @@ -72,21 +75,16 @@ namespace meta_hpp::detail : ref_type_{ref_types::const_rvalue} , raw_type_{v.get_type()} {} - [[nodiscard]] bool is_const() const noexcept { + [[nodiscard]] bool is_inst_const() const noexcept { + if ( raw_type_.is_pointer() ) { + const pointer_type& from_type_ptr = raw_type_.as_pointer(); + const bool from_type_ptr_readonly = from_type_ptr.get_flags().has(pointer_flags::is_readonly); + return from_type_ptr_readonly; + } return ref_type_ == ref_types::const_lvalue || ref_type_ == ref_types::const_rvalue; } - [[nodiscard]] bool is_lvalue() const noexcept { - return ref_type_ == ref_types::lvalue - || ref_type_ == ref_types::const_lvalue; - } - - [[nodiscard]] bool is_rvalue() const noexcept { - return ref_type_ == ref_types::rvalue - || ref_type_ == ref_types::const_rvalue; - } - [[nodiscard]] ref_types get_ref_type() const noexcept { return ref_type_; } @@ -153,21 +151,39 @@ namespace meta_hpp::detail || (base.is_class() && derived.is_class() && base.as_class().is_base_of(derived.as_class())); }; - const auto is_invocable = [this](){ - switch ( get_ref_type() ) { - case ref_types::lvalue: - return std::is_invocable_v; - case ref_types::const_lvalue: - return std::is_invocable_v; - case ref_types::rvalue: - return std::is_invocable_v; - case ref_types::const_rvalue: - return std::is_invocable_v; - } - return false; - }; + if ( from_type.is_class() ) { + const auto is_invocable = [this](){ + switch ( get_ref_type() ) { + case ref_types::lvalue: + return std::is_invocable_v; + case ref_types::const_lvalue: + return std::is_invocable_v; + case ref_types::rvalue: + return std::is_invocable_v; + case ref_types::const_rvalue: + return std::is_invocable_v; + } + return false; + }; - return is_a(to_type, from_type) && is_invocable(); + return is_invocable() && is_a(to_type, from_type); + } + + if ( from_type.is_pointer() ) { + const pointer_type& from_type_ptr = from_type.as_pointer(); + const bool from_type_ptr_readonly = from_type_ptr.get_flags().has(pointer_flags::is_readonly); + const any_type& from_data_type = from_type_ptr.get_data_type(); + + const auto is_invocable = [from_type_ptr_readonly](){ + return from_type_ptr_readonly + ? std::is_invocable_v + : std::is_invocable_v; + }; + + return is_invocable() && is_a(to_type, from_data_type); + } + + return false; } } @@ -204,6 +220,27 @@ namespace meta_hpp::detail } } + if ( from_type.is_pointer() ) { + const pointer_type& from_type_ptr = from_type.as_pointer(); + const any_type& from_data_type = from_type_ptr.get_data_type(); + + if ( from_data_type.is_class() && to_type.is_class() ) { + const class_type& from_data_class = from_data_type.as_class(); + const class_type& to_class = to_type.as_class(); + + void** from_data_ptr = static_cast(data_); + void* to_ptr = pointer_upcast(*from_data_ptr, from_data_class, to_class); + + if constexpr ( !std::is_reference_v ) { + return *static_cast(to_ptr); + } + + if constexpr ( std::is_lvalue_reference_v ) { + return *static_cast(to_ptr); + } + } + } + throw_exception_with("bad instance cast"); } } diff --git a/headers/meta.hpp/meta_detail/value_utilities/utraits.hpp b/headers/meta.hpp/meta_detail/value_utilities/utraits.hpp index 7ccd92a..655cba8 100644 --- a/headers/meta.hpp/meta_detail/value_utilities/utraits.hpp +++ b/headers/meta.hpp/meta_detail/value_utilities/utraits.hpp @@ -52,12 +52,14 @@ namespace meta_hpp::detail template < typename T > concept inst_class_lvalue_ref_kind = (decay_non_uvalue_kind) && - (std::is_lvalue_reference_v && std::is_class_v>); + (std::is_lvalue_reference_v) && + (std::is_class_v>>); template < typename T > concept inst_class_rvalue_ref_kind = (decay_non_uvalue_kind) && - (std::is_class_v || (std::is_rvalue_reference_v && std::is_class_v>)); + (!std::is_reference_v || std::is_rvalue_reference_v) && + (std::is_class_v>>); } namespace meta_hpp::detail diff --git a/headers/meta.hpp/meta_states/member.hpp b/headers/meta.hpp/meta_states/member.hpp index 56e0093..8707cdb 100644 --- a/headers/meta.hpp/meta_states/member.hpp +++ b/headers/meta.hpp/meta_states/member.hpp @@ -37,7 +37,7 @@ namespace meta_hpp::detail throw_exception_with("an attempt to get a member with an incorrect instance type"); } - if ( inst.is_const() ) { + if ( inst.is_inst_const() ) { auto&& return_value = inst.cast().*member; if constexpr ( as_copy ) { @@ -88,7 +88,7 @@ namespace meta_hpp::detail if constexpr ( std::is_const_v ) { throw_exception_with("an attempt to set a constant member"); } else { - if ( inst.is_const() ) { + if ( inst.is_inst_const() ) { throw_exception_with("an attempt to set a member with an const instance type"); } @@ -111,7 +111,7 @@ namespace meta_hpp::detail using value_type = typename mt::value_type; return !std::is_const_v - && !inst.is_const() + && !inst.is_inst_const() && inst.can_cast_to() && arg.can_cast_to(); } diff --git a/singles/headers/meta.hpp/meta_all.hpp b/singles/headers/meta.hpp/meta_all.hpp index def2dc6..10de81d 100644 --- a/singles/headers/meta.hpp/meta_all.hpp +++ b/singles/headers/meta.hpp/meta_all.hpp @@ -4675,12 +4675,14 @@ namespace meta_hpp::detail template < typename T > concept inst_class_lvalue_ref_kind = (decay_non_uvalue_kind) && - (std::is_lvalue_reference_v && std::is_class_v>); + (std::is_lvalue_reference_v) && + (std::is_class_v>>); template < typename T > concept inst_class_rvalue_ref_kind = (decay_non_uvalue_kind) && - (std::is_class_v || (std::is_rvalue_reference_v && std::is_class_v>)); + (!std::is_reference_v || std::is_rvalue_reference_v) && + (std::is_class_v>>); } namespace meta_hpp::detail @@ -4795,6 +4797,9 @@ namespace meta_hpp::detail virtual ~uarg_base() = default; + template < typename T > + uarg_base(type_list) = delete; + template < decay_value_kind T > // NOLINTNEXTLINE(*-forwarding-reference-overload) explicit uarg_base(T&&) @@ -4835,21 +4840,11 @@ namespace meta_hpp::detail : ref_type_{ref_types::const_rvalue} , raw_type_{v.get_type()} {} - [[nodiscard]] bool is_const() const noexcept { + [[nodiscard]] bool is_ref_const() const noexcept { return ref_type_ == ref_types::const_lvalue || ref_type_ == ref_types::const_rvalue; } - [[nodiscard]] bool is_lvalue() const noexcept { - return ref_type_ == ref_types::lvalue - || ref_type_ == ref_types::const_lvalue; - } - - [[nodiscard]] bool is_rvalue() const noexcept { - return ref_type_ == ref_types::rvalue - || ref_type_ == ref_types::const_rvalue; - } - [[nodiscard]] ref_types get_ref_type() const noexcept { return ref_type_; } @@ -4931,7 +4926,7 @@ namespace meta_hpp::detail const bool to_type_ptr_readonly = to_type_ptr.get_flags().has(pointer_flags::is_readonly); const array_type& from_type_array = from_type.as_array(); - const bool from_type_array_readonly = is_const(); + const bool from_type_array_readonly = is_ref_const(); const any_type& to_data_type = to_type_ptr.get_data_type(); const any_type& from_data_type = from_type_array.get_data_type(); @@ -5911,6 +5906,9 @@ namespace meta_hpp::detail virtual ~uinst_base() = default; + template < typename T > + uinst_base(type_list) = delete; + template < decay_value_kind T > // NOLINTNEXTLINE(*-forwarding-reference-overload) explicit uinst_base(T&&) @@ -5951,21 +5949,16 @@ namespace meta_hpp::detail : ref_type_{ref_types::const_rvalue} , raw_type_{v.get_type()} {} - [[nodiscard]] bool is_const() const noexcept { + [[nodiscard]] bool is_inst_const() const noexcept { + if ( raw_type_.is_pointer() ) { + const pointer_type& from_type_ptr = raw_type_.as_pointer(); + const bool from_type_ptr_readonly = from_type_ptr.get_flags().has(pointer_flags::is_readonly); + return from_type_ptr_readonly; + } return ref_type_ == ref_types::const_lvalue || ref_type_ == ref_types::const_rvalue; } - [[nodiscard]] bool is_lvalue() const noexcept { - return ref_type_ == ref_types::lvalue - || ref_type_ == ref_types::const_lvalue; - } - - [[nodiscard]] bool is_rvalue() const noexcept { - return ref_type_ == ref_types::rvalue - || ref_type_ == ref_types::const_rvalue; - } - [[nodiscard]] ref_types get_ref_type() const noexcept { return ref_type_; } @@ -6032,21 +6025,39 @@ namespace meta_hpp::detail || (base.is_class() && derived.is_class() && base.as_class().is_base_of(derived.as_class())); }; - const auto is_invocable = [this](){ - switch ( get_ref_type() ) { - case ref_types::lvalue: - return std::is_invocable_v; - case ref_types::const_lvalue: - return std::is_invocable_v; - case ref_types::rvalue: - return std::is_invocable_v; - case ref_types::const_rvalue: - return std::is_invocable_v; - } - return false; - }; + if ( from_type.is_class() ) { + const auto is_invocable = [this](){ + switch ( get_ref_type() ) { + case ref_types::lvalue: + return std::is_invocable_v; + case ref_types::const_lvalue: + return std::is_invocable_v; + case ref_types::rvalue: + return std::is_invocable_v; + case ref_types::const_rvalue: + return std::is_invocable_v; + } + return false; + }; - return is_a(to_type, from_type) && is_invocable(); + return is_invocable() && is_a(to_type, from_type); + } + + if ( from_type.is_pointer() ) { + const pointer_type& from_type_ptr = from_type.as_pointer(); + const bool from_type_ptr_readonly = from_type_ptr.get_flags().has(pointer_flags::is_readonly); + const any_type& from_data_type = from_type_ptr.get_data_type(); + + const auto is_invocable = [from_type_ptr_readonly](){ + return from_type_ptr_readonly + ? std::is_invocable_v + : std::is_invocable_v; + }; + + return is_invocable() && is_a(to_type, from_data_type); + } + + return false; } } @@ -6083,6 +6094,27 @@ namespace meta_hpp::detail } } + if ( from_type.is_pointer() ) { + const pointer_type& from_type_ptr = from_type.as_pointer(); + const any_type& from_data_type = from_type_ptr.get_data_type(); + + if ( from_data_type.is_class() && to_type.is_class() ) { + const class_type& from_data_class = from_data_type.as_class(); + const class_type& to_class = to_type.as_class(); + + void** from_data_ptr = static_cast(data_); + void* to_ptr = pointer_upcast(*from_data_ptr, from_data_class, to_class); + + if constexpr ( !std::is_reference_v ) { + return *static_cast(to_ptr); + } + + if constexpr ( std::is_lvalue_reference_v ) { + return *static_cast(to_ptr); + } + } + } + throw_exception_with("bad instance cast"); } } @@ -6111,7 +6143,7 @@ namespace meta_hpp::detail throw_exception_with("an attempt to get a member with an incorrect instance type"); } - if ( inst.is_const() ) { + if ( inst.is_inst_const() ) { auto&& return_value = inst.cast().*member; if constexpr ( as_copy ) { @@ -6162,7 +6194,7 @@ namespace meta_hpp::detail if constexpr ( std::is_const_v ) { throw_exception_with("an attempt to set a constant member"); } else { - if ( inst.is_const() ) { + if ( inst.is_inst_const() ) { throw_exception_with("an attempt to set a member with an const instance type"); } @@ -6185,7 +6217,7 @@ namespace meta_hpp::detail using value_type = typename mt::value_type; return !std::is_const_v - && !inst.is_const() + && !inst.is_inst_const() && inst.can_cast_to() && arg.can_cast_to(); } diff --git a/untests/meta_states/member_tests.cpp b/untests/meta_states/member_tests.cpp index 5c87403..4aee00c 100644 --- a/untests/meta_states/member_tests.cpp +++ b/untests/meta_states/member_tests.cpp @@ -57,77 +57,105 @@ TEST_CASE("meta/meta_states/member") { { CHECK(vm.is_gettable_with()); + CHECK(vm.is_gettable_with()); CHECK(vm.is_gettable_with()); CHECK(vm.is_gettable_with()); CHECK(vm.is_gettable_with()); + CHECK(vm.is_gettable_with()); CHECK(vm.is_gettable_with()); CHECK(vm.is_gettable_with()); CHECK(vm.is_gettable_with(v)); + CHECK(vm.is_gettable_with(&v)); CHECK(vm.is_gettable_with(std::as_const(v))); + CHECK(vm.is_gettable_with(&std::as_const(v))); CHECK(vm.is_gettable_with(std::move(v))); CHECK(vm.is_gettable_with(std::move(std::as_const(v)))); CHECK_FALSE(vm.is_gettable_with()); + CHECK_FALSE(vm.is_gettable_with()); CHECK_FALSE(vm.is_gettable_with(v2)); + CHECK_FALSE(vm.is_gettable_with(&v2)); } { CHECK(vm.get(v) == 1); + CHECK(vm.get(&v) == 1); CHECK(vm.get(std::as_const(v)) == 1); + CHECK(vm.get(&std::as_const(v)) == 1); CHECK(vm.get(std::move(v)) == 1); CHECK(vm.get(std::move(std::as_const(v))) == 1); CHECK(vm(v) == 1); + CHECK(vm(&v) == 1); CHECK(vm(std::as_const(v)) == 1); + CHECK(vm(&std::as_const(v)) == 1); CHECK(vm(std::move(v)) == 1); CHECK(vm(std::move(std::as_const(v))) == 1); CHECK_THROWS(std::ignore = vm.get(v2)); + CHECK_THROWS(std::ignore = vm.get(&v2)); CHECK_THROWS(std::ignore = vm(v2)); + CHECK_THROWS(std::ignore = vm(&v2)); } { CHECK(vm.is_settable_with()); + CHECK(vm.is_settable_with()); CHECK(vm.is_settable_with()); CHECK(vm.is_settable_with()); CHECK(vm.is_settable_with()); + CHECK(vm.is_settable_with()); CHECK(vm.is_settable_with()); CHECK(vm.is_settable_with()); CHECK(vm.is_settable_with(v, 10)); + CHECK(vm.is_settable_with(&v, 10)); CHECK(vm.is_settable_with(std::move(v), 12)); CHECK_FALSE(vm.is_settable_with()); + CHECK_FALSE(vm.is_settable_with()); CHECK_FALSE(vm.is_settable_with()); CHECK_FALSE(vm.is_settable_with()); CHECK_FALSE(vm.is_settable_with()); + CHECK_FALSE(vm.is_settable_with()); CHECK_FALSE(vm.is_settable_with()); CHECK_FALSE(vm.is_settable_with()); + CHECK_FALSE(vm.is_settable_with()); CHECK_FALSE(vm.is_settable_with()); CHECK_FALSE(vm.is_settable_with(v2, 10)); + CHECK_FALSE(vm.is_settable_with(&v2, 10)); CHECK_FALSE(vm.is_settable_with(std::move(v2), 10)); CHECK_FALSE(vm.is_settable_with(v, 10.0)); + CHECK_FALSE(vm.is_settable_with(&v, 10.0)); CHECK_FALSE(vm.is_settable_with(std::move(v), 12.0)); } { CHECK_NOTHROW(vm.set(v, 10)); CHECK(vm.get(v) == 10); - CHECK_THROWS(vm.set(std::as_const(v), 11)); CHECK(vm.get(v) == 10); + CHECK_NOTHROW(vm.set(&v, 100)); CHECK(vm.get(v) == 100); + CHECK_THROWS(vm.set(std::as_const(v), 11)); CHECK(vm.get(v) == 100); + CHECK_THROWS(vm.set(&std::as_const(v), 11)); CHECK(vm.get(v) == 100); + CHECK_NOTHROW(vm.set(std::move(v), 12)); CHECK(vm.get(v) == 12); CHECK_THROWS(vm.set(std::move(std::as_const(v)), 13)); CHECK(vm.get(v) == 12); CHECK_NOTHROW(vm(v, 13)); CHECK(vm(v) == 13); - CHECK_THROWS(vm(std::as_const(v), 14)); CHECK(vm(v) == 13); + CHECK_NOTHROW(vm(&v, 130)); CHECK(vm(v) == 130); + CHECK_THROWS(vm(std::as_const(v), 14)); CHECK(vm(v) == 130); + CHECK_THROWS(vm(std::as_const(v), 14)); CHECK(vm(v) == 130); + CHECK_NOTHROW(vm(std::move(v), 15)); CHECK(vm(v) == 15); CHECK_THROWS(vm(std::move(std::as_const(v)), 16)); CHECK(vm(v) == 15); CHECK_THROWS(vm.set(v2, 17)); + CHECK_THROWS(vm.set(&v2, 17)); CHECK_THROWS(vm(v2, 17)); + CHECK_THROWS(vm(&v2, 17)); CHECK(vm(v) == 15); } } @@ -144,74 +172,99 @@ TEST_CASE("meta/meta_states/member") { { CHECK(vm.is_gettable_with()); + CHECK(vm.is_gettable_with()); CHECK(vm.is_gettable_with()); CHECK(vm.is_gettable_with()); CHECK(vm.is_gettable_with()); + CHECK(vm.is_gettable_with()); CHECK(vm.is_gettable_with()); CHECK(vm.is_gettable_with()); CHECK(vm.is_gettable_with(v)); + CHECK(vm.is_gettable_with(&v)); CHECK(vm.is_gettable_with(std::as_const(v))); + CHECK(vm.is_gettable_with(&std::as_const(v))); CHECK(vm.is_gettable_with(std::move(v))); CHECK(vm.is_gettable_with(std::move(std::as_const(v)))); CHECK_FALSE(vm.is_gettable_with()); + CHECK_FALSE(vm.is_gettable_with()); CHECK_FALSE(vm.is_gettable_with(v2)); + CHECK_FALSE(vm.is_gettable_with(&v2)); } { CHECK(vm.get(v) == 2); + CHECK(vm.get(&v) == 2); CHECK(vm.get(std::as_const(v)) == 2); + CHECK(vm.get(&std::as_const(v)) == 2); CHECK(vm.get(std::move(v)) == 2); CHECK(vm.get(std::move(std::as_const(v))) == 2); CHECK(vm(v) == 2); + CHECK(vm(&v) == 2); CHECK(vm(std::as_const(v)) == 2); + CHECK(vm(&std::as_const(v)) == 2); CHECK(vm(std::move(v)) == 2); CHECK(vm(std::move(std::as_const(v))) == 2); CHECK_THROWS(std::ignore = vm.get(v2)); + CHECK_THROWS(std::ignore = vm.get(&v2)); CHECK_THROWS(std::ignore = vm(v2)); + CHECK_THROWS(std::ignore = vm(&v2)); } { CHECK_FALSE(vm.is_settable_with()); + CHECK_FALSE(vm.is_settable_with()); CHECK_FALSE(vm.is_settable_with()); CHECK_FALSE(vm.is_settable_with()); CHECK_FALSE(vm.is_settable_with()); + CHECK_FALSE(vm.is_settable_with()); CHECK_FALSE(vm.is_settable_with()); CHECK_FALSE(vm.is_settable_with()); CHECK_FALSE(vm.is_settable_with()); + CHECK_FALSE(vm.is_settable_with()); CHECK_FALSE(vm.is_settable_with()); CHECK_FALSE(vm.is_settable_with()); CHECK_FALSE(vm.is_settable_with()); + CHECK_FALSE(vm.is_settable_with()); CHECK_FALSE(vm.is_settable_with()); CHECK_FALSE(vm.is_settable_with()); CHECK_FALSE(vm.is_settable_with(v, 10)); + CHECK_FALSE(vm.is_settable_with(&v, 10)); CHECK_FALSE(vm.is_settable_with(std::move(v), 12)); + CHECK_FALSE(vm.is_settable_with()); CHECK_FALSE(vm.is_settable_with()); CHECK_FALSE(vm.is_settable_with(v2, 10)); + CHECK_FALSE(vm.is_settable_with(&v2, 10)); CHECK_FALSE(vm.is_settable_with(std::move(v2), 12)); } { CHECK_THROWS(vm.set(v, 10)); CHECK(vm.get(v) == 2); + CHECK_THROWS(vm.set(&v, 10)); CHECK(vm.get(v) == 2); CHECK_THROWS(vm.set(std::as_const(v), 11)); CHECK(vm.get(v) == 2); + CHECK_THROWS(vm.set(&std::as_const(v), 11)); CHECK(vm.get(v) == 2); CHECK_THROWS(vm.set(std::move(v), 12)); CHECK(vm.get(v) == 2); CHECK_THROWS(vm.set(std::move(std::as_const(v)), 16)); CHECK(vm.get(v) == 2); CHECK_THROWS(vm(v, 13)); CHECK(vm(v) == 2); + CHECK_THROWS(vm(&v, 13)); CHECK(vm(v) == 2); CHECK_THROWS(vm(std::as_const(v), 14)); CHECK(vm(v) == 2); + CHECK_THROWS(vm(&std::as_const(v), 14)); CHECK(vm(v) == 2); CHECK_THROWS(vm(std::move(v), 15)); CHECK(vm(v) == 2); CHECK_THROWS(vm(std::move(std::as_const(v)), 16)); CHECK(vm(v) == 2); CHECK_THROWS(vm.set(v2, 17)); + CHECK_THROWS(vm.set(&v2, 17)); CHECK_THROWS(vm(v2, 17)); + CHECK_THROWS(vm(&v2, 17)); CHECK(vm(v) == 2); } } diff --git a/untests/meta_states/method_tests.cpp b/untests/meta_states/method_tests.cpp index 041be66..b32a294 100644 --- a/untests/meta_states/method_tests.cpp +++ b/untests/meta_states/method_tests.cpp @@ -8,46 +8,53 @@ namespace { + struct fake { + int i = 10; + }; + struct base { + base() = default; + [[maybe_unused]] base(base&&) = default; + [[maybe_unused]] base(const base&) = default; virtual ~base() = default; virtual int pure_virtual_method() = 0; }; struct clazz : base { clazz() = default; - - clazz(clazz&&) = delete; - clazz(const clazz&) = delete; - - clazz& operator=(clazz&&) = delete; - clazz& operator=(const clazz&) = delete; + [[maybe_unused]] clazz(clazz&&) = default; + [[maybe_unused]] clazz(const clazz&) = default; // - int non_const_method() { return 1; } - int non_const_method_noexcept() noexcept { return 2; } + int non_const_method() { return ii + 1; } + int non_const_method_noexcept() noexcept { return ii + 2; } - int const_method() const { return 3; } - int const_method_noexcept() const noexcept { return 4; } + int const_method() const { return ii + 3; } + int const_method_noexcept() const noexcept { return ii + 4; } - int non_const_method_ref() & { return 5; } - int non_const_method_noexcept_ref() & noexcept { return 6; } + int non_const_method_ref() & { return ii + 5; } + int non_const_method_noexcept_ref() & noexcept { return ii + 6; } - int const_method_ref() const & { return 7; } - int const_method_noexcept_ref() const & noexcept { return 8; } + int const_method_ref() const & { return ii + 7; } + int const_method_noexcept_ref() const & noexcept { return ii + 8; } - int non_const_method_rref() && { return 9; } - int non_const_method_noexcept_rref() && noexcept { return 10; } + int non_const_method_rref() && { return ii + 9; } + int non_const_method_noexcept_rref() && noexcept { return ii + 10; } - int const_method_rref() const && { return 11; } - int const_method_noexcept_rref() const && noexcept { return 12; } + int const_method_rref() const && { return ii + 11; } + int const_method_noexcept_rref() const && noexcept { return ii + 12; } // int pure_virtual_method() override { return -1; } + + // + + int ii = 0; }; - struct derived_clazz : clazz { + struct derived_clazz : fake, clazz { int pure_virtual_method() override { return -2; } }; @@ -125,15 +132,56 @@ TEST_CASE("meta/meta_states/method") { CHECK_FALSE(mi.is_invocable_with()); CHECK(mi.is_invocable_with()); CHECK_FALSE(mi.is_invocable_with()); + + CHECK(mi.is_invocable_with()); + CHECK_FALSE(mi.is_invocable_with()); + CHECK(mi.is_invocable_with()); + CHECK_FALSE(mi.is_invocable_with()); } { - clazz cl; + derived_clazz cl; + meta::uvalue clv{cl}; CHECK(mi.invoke(cl) == 1); CHECK_THROWS(mi.invoke(std::as_const(cl))); CHECK(mi.invoke(std::move(cl)) == 1); CHECK_THROWS(mi.invoke(std::move(std::as_const(cl)))); + + CHECK(mi.invoke(clv) == 1); + CHECK_THROWS(mi.invoke(std::as_const(clv))); + CHECK(mi.invoke(std::move(clv)) == 1); + CHECK_THROWS(mi.invoke(std::move(std::as_const(clv)))); + } + + { + derived_clazz cl; + + derived_clazz* cl1 = &cl; + const derived_clazz* cl2 = &cl; + + meta::uvalue cl1v{cl1}; + meta::uvalue cl2v{cl2}; + + CHECK(mi.invoke(cl1) == 1); + CHECK(mi.invoke(std::as_const(cl1)) == 1); + CHECK(mi.invoke(std::move(cl1)) == 1); + CHECK(mi.invoke(std::move(std::as_const(cl1))) == 1); + + CHECK(mi.invoke(cl1v) == 1); + CHECK(mi.invoke(std::as_const(cl1v)) == 1); + CHECK(mi.invoke(std::move(cl1v)) == 1); + CHECK(mi.invoke(std::move(std::as_const(cl1v))) == 1); + + CHECK_THROWS(mi.invoke(cl2)); + CHECK_THROWS(mi.invoke(std::as_const(cl2))); + CHECK_THROWS(mi.invoke(std::move(cl2))); + CHECK_THROWS(mi.invoke(std::move(std::as_const(cl2)))); + + CHECK_THROWS(mi.invoke(cl2v)); + CHECK_THROWS(mi.invoke(std::as_const(cl2v))); + CHECK_THROWS(mi.invoke(std::move(cl2v))); + CHECK_THROWS(mi.invoke(std::move(std::as_const(cl2v)))); } static_assert(std::is_invocable_v); @@ -170,15 +218,56 @@ TEST_CASE("meta/meta_states/method") { CHECK_FALSE(mi.is_invocable_with()); CHECK(mi.is_invocable_with()); CHECK_FALSE(mi.is_invocable_with()); + + CHECK(mi.is_invocable_with()); + CHECK_FALSE(mi.is_invocable_with()); + CHECK(mi.is_invocable_with()); + CHECK_FALSE(mi.is_invocable_with()); } { - clazz cl; + derived_clazz cl; + meta::uvalue clv{cl}; CHECK(mi.invoke(cl) == 2); CHECK_THROWS(mi.invoke(std::as_const(cl))); CHECK(mi.invoke(std::move(cl)) == 2); CHECK_THROWS(mi.invoke(std::move(std::as_const(cl)))); + + CHECK(mi.invoke(clv) == 2); + CHECK_THROWS(mi.invoke(std::as_const(clv))); + CHECK(mi.invoke(std::move(clv)) == 2); + CHECK_THROWS(mi.invoke(std::move(std::as_const(clv)))); + } + + { + derived_clazz cl; + + derived_clazz* cl1 = &cl; + const derived_clazz* cl2 = &cl; + + meta::uvalue cl1v{cl1}; + meta::uvalue cl2v{cl2}; + + CHECK(mi.invoke(cl1) == 2); + CHECK(mi.invoke(std::as_const(cl1)) == 2); + CHECK(mi.invoke(std::move(cl1)) == 2); + CHECK(mi.invoke(std::move(std::as_const(cl1))) == 2); + + CHECK(mi.invoke(cl1v) == 2); + CHECK(mi.invoke(std::as_const(cl1v)) == 2); + CHECK(mi.invoke(std::move(cl1v)) == 2); + CHECK(mi.invoke(std::move(std::as_const(cl1v))) == 2); + + CHECK_THROWS(mi.invoke(cl2)); + CHECK_THROWS(mi.invoke(std::as_const(cl2))); + CHECK_THROWS(mi.invoke(std::move(cl2))); + CHECK_THROWS(mi.invoke(std::move(std::as_const(cl2)))); + + CHECK_THROWS(mi.invoke(cl2v)); + CHECK_THROWS(mi.invoke(std::as_const(cl2v))); + CHECK_THROWS(mi.invoke(std::move(cl2v))); + CHECK_THROWS(mi.invoke(std::move(std::as_const(cl2v)))); } static_assert(std::is_invocable_v); @@ -215,15 +304,56 @@ TEST_CASE("meta/meta_states/method") { CHECK(mi.is_invocable_with()); CHECK(mi.is_invocable_with()); CHECK(mi.is_invocable_with()); + + CHECK(mi.is_invocable_with()); + CHECK(mi.is_invocable_with()); + CHECK(mi.is_invocable_with()); + CHECK(mi.is_invocable_with()); } { - clazz cl; + derived_clazz cl; + meta::uvalue clv{cl}; CHECK(mi.invoke(cl) == 3); CHECK(mi.invoke(std::as_const(cl)) == 3); CHECK(mi.invoke(std::move(cl)) == 3); CHECK(mi.invoke(std::move(std::as_const(cl))) == 3); + + CHECK(mi.invoke(clv) == 3); + CHECK(mi.invoke(std::as_const(clv)) == 3); + CHECK(mi.invoke(std::move(clv)) == 3); + CHECK(mi.invoke(std::move(std::as_const(clv))) == 3); + } + + { + derived_clazz cl; + + derived_clazz* cl1 = &cl; + const derived_clazz* cl2 = &cl; + + meta::uvalue cl1v{cl1}; + meta::uvalue cl2v{cl2}; + + CHECK(mi.invoke(cl1) == 3); + CHECK(mi.invoke(std::as_const(cl1)) == 3); + CHECK(mi.invoke(std::move(cl1)) == 3); + CHECK(mi.invoke(std::move(std::as_const(cl1))) == 3); + + CHECK(mi.invoke(cl1v) == 3); + CHECK(mi.invoke(std::as_const(cl1v)) == 3); + CHECK(mi.invoke(std::move(cl1v)) == 3); + CHECK(mi.invoke(std::move(std::as_const(cl1v))) == 3); + + CHECK(mi.invoke(cl2) == 3); + CHECK(mi.invoke(std::as_const(cl2)) == 3); + CHECK(mi.invoke(std::move(cl2)) == 3); + CHECK(mi.invoke(std::move(std::as_const(cl2))) == 3); + + CHECK(mi.invoke(cl2v) == 3); + CHECK(mi.invoke(std::as_const(cl2v)) == 3); + CHECK(mi.invoke(std::move(cl2v)) == 3); + CHECK(mi.invoke(std::move(std::as_const(cl2v))) == 3); } static_assert(std::is_invocable_v); @@ -260,15 +390,56 @@ TEST_CASE("meta/meta_states/method") { CHECK(mi.is_invocable_with()); CHECK(mi.is_invocable_with()); CHECK(mi.is_invocable_with()); + + CHECK(mi.is_invocable_with()); + CHECK(mi.is_invocable_with()); + CHECK(mi.is_invocable_with()); + CHECK(mi.is_invocable_with()); } { - clazz cl; + derived_clazz cl; + meta::uvalue clv{cl}; CHECK(mi.invoke(cl) == 4); CHECK(mi.invoke(std::as_const(cl)) == 4); CHECK(mi.invoke(std::move(cl)) == 4); CHECK(mi.invoke(std::move(std::as_const(cl))) == 4); + + CHECK(mi.invoke(clv) == 4); + CHECK(mi.invoke(std::as_const(clv)) == 4); + CHECK(mi.invoke(std::move(clv)) == 4); + CHECK(mi.invoke(std::move(std::as_const(clv))) == 4); + } + + { + derived_clazz cl; + + derived_clazz* cl1 = &cl; + const derived_clazz* cl2 = &cl; + + meta::uvalue cl1v{cl1}; + meta::uvalue cl2v{cl2}; + + CHECK(mi.invoke(cl1) == 4); + CHECK(mi.invoke(std::as_const(cl1)) == 4); + CHECK(mi.invoke(std::move(cl1)) == 4); + CHECK(mi.invoke(std::move(std::as_const(cl1))) == 4); + + CHECK(mi.invoke(cl1v) == 4); + CHECK(mi.invoke(std::as_const(cl1v)) == 4); + CHECK(mi.invoke(std::move(cl1v)) == 4); + CHECK(mi.invoke(std::move(std::as_const(cl1v))) == 4); + + CHECK(mi.invoke(cl2) == 4); + CHECK(mi.invoke(std::as_const(cl2)) == 4); + CHECK(mi.invoke(std::move(cl2)) == 4); + CHECK(mi.invoke(std::move(std::as_const(cl2))) == 4); + + CHECK(mi.invoke(cl2v) == 4); + CHECK(mi.invoke(std::as_const(cl2v)) == 4); + CHECK(mi.invoke(std::move(cl2v)) == 4); + CHECK(mi.invoke(std::move(std::as_const(cl2v))) == 4); } static_assert(std::is_invocable_v); @@ -308,12 +479,48 @@ TEST_CASE("meta/meta_states/method") { } { - clazz cl; + derived_clazz cl; + meta::uvalue clv{cl}; CHECK(mi.invoke(cl) == 5); CHECK_THROWS(mi.invoke(std::as_const(cl))); CHECK_THROWS(mi.invoke(std::move(cl))); CHECK_THROWS(mi.invoke(std::move(std::as_const(cl)))); + + CHECK(mi.invoke(clv) == 5); + CHECK_THROWS(mi.invoke(std::as_const(clv))); + CHECK_THROWS(mi.invoke(std::move(clv))); + CHECK_THROWS(mi.invoke(std::move(std::as_const(clv)))); + } + + { + derived_clazz cl; + + derived_clazz* cl1 = &cl; + const derived_clazz* cl2 = &cl; + + meta::uvalue cl1v{cl1}; + meta::uvalue cl2v{cl2}; + + CHECK(mi.invoke(cl1) == 5); + CHECK(mi.invoke(std::as_const(cl1)) == 5); + CHECK(mi.invoke(std::move(cl1)) == 5); + CHECK(mi.invoke(std::move(std::as_const(cl1))) == 5); + + CHECK(mi.invoke(cl1v) == 5); + CHECK(mi.invoke(std::as_const(cl1v)) == 5); + CHECK(mi.invoke(std::move(cl1v)) == 5); + CHECK(mi.invoke(std::move(std::as_const(cl1v))) == 5); + + CHECK_THROWS(mi.invoke(cl2)); + CHECK_THROWS(mi.invoke(std::as_const(cl2))); + CHECK_THROWS(mi.invoke(std::move(cl2))); + CHECK_THROWS(mi.invoke(std::move(std::as_const(cl2)))); + + CHECK_THROWS(mi.invoke(cl2v)); + CHECK_THROWS(mi.invoke(std::as_const(cl2v))); + CHECK_THROWS(mi.invoke(std::move(cl2v))); + CHECK_THROWS(mi.invoke(std::move(std::as_const(cl2v)))); } static_assert(std::is_invocable_v); @@ -353,12 +560,48 @@ TEST_CASE("meta/meta_states/method") { } { - clazz cl; + derived_clazz cl; + meta::uvalue clv{cl}; CHECK(mi.invoke(cl) == 6); CHECK_THROWS(mi.invoke(std::as_const(cl))); CHECK_THROWS(mi.invoke(std::move(cl))); CHECK_THROWS(mi.invoke(std::move(std::as_const(cl)))); + + CHECK(mi.invoke(clv) == 6); + CHECK_THROWS(mi.invoke(std::as_const(clv))); + CHECK_THROWS(mi.invoke(std::move(clv))); + CHECK_THROWS(mi.invoke(std::move(std::as_const(clv)))); + } + + { + derived_clazz cl; + + derived_clazz* cl1 = &cl; + const derived_clazz* cl2 = &cl; + + meta::uvalue cl1v{cl1}; + meta::uvalue cl2v{cl2}; + + CHECK(mi.invoke(cl1) == 6); + CHECK(mi.invoke(std::as_const(cl1)) == 6); + CHECK(mi.invoke(std::move(cl1)) == 6); + CHECK(mi.invoke(std::move(std::as_const(cl1))) == 6); + + CHECK(mi.invoke(cl1v) == 6); + CHECK(mi.invoke(std::as_const(cl1v)) == 6); + CHECK(mi.invoke(std::move(cl1v)) == 6); + CHECK(mi.invoke(std::move(std::as_const(cl1v))) == 6); + + CHECK_THROWS(mi.invoke(cl2)); + CHECK_THROWS(mi.invoke(std::as_const(cl2))); + CHECK_THROWS(mi.invoke(std::move(cl2))); + CHECK_THROWS(mi.invoke(std::move(std::as_const(cl2)))); + + CHECK_THROWS(mi.invoke(cl2v)); + CHECK_THROWS(mi.invoke(std::as_const(cl2v))); + CHECK_THROWS(mi.invoke(std::move(cl2v))); + CHECK_THROWS(mi.invoke(std::move(std::as_const(cl2v)))); } static_assert(std::is_invocable_v); @@ -398,12 +641,48 @@ TEST_CASE("meta/meta_states/method") { } { - clazz cl; + derived_clazz cl; + meta::uvalue clv{cl}; CHECK(mi.invoke(cl) == 7); CHECK(mi.invoke(std::as_const(cl)) == 7); CHECK(mi.invoke(std::move(cl)) == 7); CHECK(mi.invoke(std::move(std::as_const(cl))) == 7); + + CHECK(mi.invoke(clv) == 7); + CHECK(mi.invoke(std::as_const(clv)) == 7); + CHECK(mi.invoke(std::move(clv)) == 7); + CHECK(mi.invoke(std::move(std::as_const(clv))) == 7); + } + + { + derived_clazz cl; + + derived_clazz* cl1 = &cl; + const derived_clazz* cl2 = &cl; + + meta::uvalue cl1v{cl1}; + meta::uvalue cl2v{cl2}; + + CHECK(mi.invoke(cl1) == 7); + CHECK(mi.invoke(std::as_const(cl1)) == 7); + CHECK(mi.invoke(std::move(cl1)) == 7); + CHECK(mi.invoke(std::move(std::as_const(cl1))) == 7); + + CHECK(mi.invoke(cl1v) == 7); + CHECK(mi.invoke(std::as_const(cl1v)) == 7); + CHECK(mi.invoke(std::move(cl1v)) == 7); + CHECK(mi.invoke(std::move(std::as_const(cl1v))) == 7); + + CHECK(mi.invoke(cl2) == 7); + CHECK(mi.invoke(std::as_const(cl2)) == 7); + CHECK(mi.invoke(std::move(cl2)) == 7); + CHECK(mi.invoke(std::move(std::as_const(cl2))) == 7); + + CHECK(mi.invoke(cl2v) == 7); + CHECK(mi.invoke(std::as_const(cl2v)) == 7); + CHECK(mi.invoke(std::move(cl2v)) == 7); + CHECK(mi.invoke(std::move(std::as_const(cl2v))) == 7); } static_assert(std::is_invocable_v); @@ -443,12 +722,48 @@ TEST_CASE("meta/meta_states/method") { } { - clazz cl; + derived_clazz cl; + meta::uvalue clv{cl}; CHECK(mi.invoke(cl) == 8); CHECK(mi.invoke(std::as_const(cl)) == 8); CHECK(mi.invoke(std::move(cl)) == 8); CHECK(mi.invoke(std::move(std::as_const(cl))) == 8); + + CHECK(mi.invoke(clv) == 8); + CHECK(mi.invoke(std::as_const(clv)) == 8); + CHECK(mi.invoke(std::move(clv)) == 8); + CHECK(mi.invoke(std::move(std::as_const(clv))) == 8); + } + + { + derived_clazz cl; + + derived_clazz* cl1 = &cl; + const derived_clazz* cl2 = &cl; + + meta::uvalue cl1v{cl1}; + meta::uvalue cl2v{cl2}; + + CHECK(mi.invoke(cl1) == 8); + CHECK(mi.invoke(std::as_const(cl1)) == 8); + CHECK(mi.invoke(std::move(cl1)) == 8); + CHECK(mi.invoke(std::move(std::as_const(cl1))) == 8); + + CHECK(mi.invoke(cl1v) == 8); + CHECK(mi.invoke(std::as_const(cl1v)) == 8); + CHECK(mi.invoke(std::move(cl1v)) == 8); + CHECK(mi.invoke(std::move(std::as_const(cl1v))) == 8); + + CHECK(mi.invoke(cl2) == 8); + CHECK(mi.invoke(std::as_const(cl2)) == 8); + CHECK(mi.invoke(std::move(cl2)) == 8); + CHECK(mi.invoke(std::move(std::as_const(cl2))) == 8); + + CHECK(mi.invoke(cl2v) == 8); + CHECK(mi.invoke(std::as_const(cl2v)) == 8); + CHECK(mi.invoke(std::move(cl2v)) == 8); + CHECK(mi.invoke(std::move(std::as_const(cl2v))) == 8); } static_assert(std::is_invocable_v); @@ -488,12 +803,48 @@ TEST_CASE("meta/meta_states/method") { } { - clazz cl; + derived_clazz cl; + meta::uvalue clv{cl}; CHECK_THROWS(mi.invoke(cl)); CHECK_THROWS(mi.invoke(std::as_const(cl))); CHECK(mi.invoke(std::move(cl)) == 9); CHECK_THROWS(mi.invoke(std::move(std::as_const(cl)))); + + CHECK_THROWS(mi.invoke(clv)); + CHECK_THROWS(mi.invoke(std::as_const(clv))); + CHECK(mi.invoke(std::move(clv)) == 9); + CHECK_THROWS(mi.invoke(std::move(std::as_const(clv)))); + } + + { + derived_clazz cl; + + derived_clazz* cl1 = &cl; + const derived_clazz* cl2 = &cl; + + meta::uvalue cl1v{cl1}; + meta::uvalue cl2v{cl2}; + + CHECK_THROWS(mi.invoke(cl1)); + CHECK_THROWS(mi.invoke(std::as_const(cl1))); + CHECK_THROWS(mi.invoke(std::move(cl1))); + CHECK_THROWS(mi.invoke(std::move(std::as_const(cl1)))); + + CHECK_THROWS(mi.invoke(cl1v)); + CHECK_THROWS(mi.invoke(std::as_const(cl1v))); + CHECK_THROWS(mi.invoke(std::move(cl1v))); + CHECK_THROWS(mi.invoke(std::move(std::as_const(cl1v)))); + + CHECK_THROWS(mi.invoke(cl2)); + CHECK_THROWS(mi.invoke(std::as_const(cl2))); + CHECK_THROWS(mi.invoke(std::move(cl2))); + CHECK_THROWS(mi.invoke(std::move(std::as_const(cl2)))); + + CHECK_THROWS(mi.invoke(cl2v)); + CHECK_THROWS(mi.invoke(std::as_const(cl2v))); + CHECK_THROWS(mi.invoke(std::move(cl2v))); + CHECK_THROWS(mi.invoke(std::move(std::as_const(cl2v)))); } static_assert(!std::is_invocable_v); @@ -533,12 +884,48 @@ TEST_CASE("meta/meta_states/method") { } { - clazz cl; + derived_clazz cl; + meta::uvalue clv{cl}; CHECK_THROWS(mi.invoke(cl)); CHECK_THROWS(mi.invoke(std::as_const(cl))); CHECK(mi.invoke(std::move(cl)) == 10); CHECK_THROWS(mi.invoke(std::move(std::as_const(cl)))); + + CHECK_THROWS(mi.invoke(clv)); + CHECK_THROWS(mi.invoke(std::as_const(clv))); + CHECK(mi.invoke(std::move(clv)) == 10); + CHECK_THROWS(mi.invoke(std::move(std::as_const(clv)))); + } + + { + derived_clazz cl; + + derived_clazz* cl1 = &cl; + const derived_clazz* cl2 = &cl; + + meta::uvalue cl1v{cl1}; + meta::uvalue cl2v{cl2}; + + CHECK_THROWS(mi.invoke(cl1)); + CHECK_THROWS(mi.invoke(std::as_const(cl1))); + CHECK_THROWS(mi.invoke(std::move(cl1))); + CHECK_THROWS(mi.invoke(std::move(std::as_const(cl1)))); + + CHECK_THROWS(mi.invoke(cl1v)); + CHECK_THROWS(mi.invoke(std::as_const(cl1v))); + CHECK_THROWS(mi.invoke(std::move(cl1v))); + CHECK_THROWS(mi.invoke(std::move(std::as_const(cl1v)))); + + CHECK_THROWS(mi.invoke(cl2)); + CHECK_THROWS(mi.invoke(std::as_const(cl2))); + CHECK_THROWS(mi.invoke(std::move(cl2))); + CHECK_THROWS(mi.invoke(std::move(std::as_const(cl2)))); + + CHECK_THROWS(mi.invoke(cl2v)); + CHECK_THROWS(mi.invoke(std::as_const(cl2v))); + CHECK_THROWS(mi.invoke(std::move(cl2v))); + CHECK_THROWS(mi.invoke(std::move(std::as_const(cl2v)))); } static_assert(!std::is_invocable_v); @@ -578,12 +965,48 @@ TEST_CASE("meta/meta_states/method") { } { - clazz cl; + derived_clazz cl; + meta::uvalue clv{cl}; CHECK_THROWS(mi.invoke(cl)); CHECK_THROWS(mi.invoke(std::as_const(cl))); CHECK(mi.invoke(std::move(cl)) == 11); CHECK(mi.invoke(std::move(std::as_const(cl))) == 11); + + CHECK_THROWS(mi.invoke(clv)); + CHECK_THROWS(mi.invoke(std::as_const(clv))); + CHECK(mi.invoke(std::move(clv)) == 11); + CHECK(mi.invoke(std::move(std::as_const(clv))) == 11); + } + + { + derived_clazz cl; + + derived_clazz* cl1 = &cl; + const derived_clazz* cl2 = &cl; + + meta::uvalue cl1v{cl1}; + meta::uvalue cl2v{cl2}; + + CHECK_THROWS(mi.invoke(cl1)); + CHECK_THROWS(mi.invoke(std::as_const(cl1))); + CHECK_THROWS(mi.invoke(std::move(cl1))); + CHECK_THROWS(mi.invoke(std::move(std::as_const(cl1)))); + + CHECK_THROWS(mi.invoke(cl1v)); + CHECK_THROWS(mi.invoke(std::as_const(cl1v))); + CHECK_THROWS(mi.invoke(std::move(cl1v))); + CHECK_THROWS(mi.invoke(std::move(std::as_const(cl1v)))); + + CHECK_THROWS(mi.invoke(cl2)); + CHECK_THROWS(mi.invoke(std::as_const(cl2))); + CHECK_THROWS(mi.invoke(std::move(cl2))); + CHECK_THROWS(mi.invoke(std::move(std::as_const(cl2)))); + + CHECK_THROWS(mi.invoke(cl2v)); + CHECK_THROWS(mi.invoke(std::as_const(cl2v))); + CHECK_THROWS(mi.invoke(std::move(cl2v))); + CHECK_THROWS(mi.invoke(std::move(std::as_const(cl2v)))); } static_assert(!std::is_invocable_v); @@ -623,12 +1046,48 @@ TEST_CASE("meta/meta_states/method") { } { - clazz cl; + derived_clazz cl; + meta::uvalue clv{cl}; CHECK_THROWS(mi.invoke(cl)); CHECK_THROWS(mi.invoke(std::as_const(cl))); CHECK(mi.invoke(std::move(cl)) == 12); CHECK(mi.invoke(std::move(std::as_const(cl))) == 12); + + CHECK_THROWS(mi.invoke(clv)); + CHECK_THROWS(mi.invoke(std::as_const(clv))); + CHECK(mi.invoke(std::move(clv)) == 12); + CHECK(mi.invoke(std::move(std::as_const(clv))) == 12); + } + + { + derived_clazz cl; + + derived_clazz* cl1 = &cl; + const derived_clazz* cl2 = &cl; + + meta::uvalue cl1v{cl1}; + meta::uvalue cl2v{cl2}; + + CHECK_THROWS(mi.invoke(cl1)); + CHECK_THROWS(mi.invoke(std::as_const(cl1))); + CHECK_THROWS(mi.invoke(std::move(cl1))); + CHECK_THROWS(mi.invoke(std::move(std::as_const(cl1)))); + + CHECK_THROWS(mi.invoke(cl1v)); + CHECK_THROWS(mi.invoke(std::as_const(cl1v))); + CHECK_THROWS(mi.invoke(std::move(cl1v))); + CHECK_THROWS(mi.invoke(std::move(std::as_const(cl1v)))); + + CHECK_THROWS(mi.invoke(cl2)); + CHECK_THROWS(mi.invoke(std::as_const(cl2))); + CHECK_THROWS(mi.invoke(std::move(cl2))); + CHECK_THROWS(mi.invoke(std::move(std::as_const(cl2)))); + + CHECK_THROWS(mi.invoke(cl2v)); + CHECK_THROWS(mi.invoke(std::as_const(cl2v))); + CHECK_THROWS(mi.invoke(std::move(cl2v))); + CHECK_THROWS(mi.invoke(std::move(std::as_const(cl2v)))); } static_assert(!std::is_invocable_v); @@ -661,10 +1120,22 @@ TEST_CASE("meta/meta_states/method") { CHECK(mi.invoke(cl) == -1); } + { + 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); } + + { + derived_clazz dcl; + CHECK(mi.is_invocable_with()); + CHECK(mi.invoke(&dcl) == -2); + } } }