pointer instance support

This commit is contained in:
BlackMATov
2022-12-04 09:03:42 +07:00
parent a6ba69038c
commit a72101a092
7 changed files with 705 additions and 117 deletions

View File

@@ -32,6 +32,9 @@ namespace meta_hpp::detail
virtual ~uarg_base() = default;
template < typename T >
uarg_base(type_list<T>) = 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();

View File

@@ -32,6 +32,9 @@ namespace meta_hpp::detail
virtual ~uinst_base() = default;
template < typename T >
uinst_base(type_list<T>) = 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<inst_method, inst_class&>;
case ref_types::const_lvalue:
return std::is_invocable_v<inst_method, const inst_class&>;
case ref_types::rvalue:
return std::is_invocable_v<inst_method, inst_class&&>;
case ref_types::const_rvalue:
return std::is_invocable_v<inst_method, const inst_class&&>;
}
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<inst_method, inst_class&>;
case ref_types::const_lvalue:
return std::is_invocable_v<inst_method, const inst_class&>;
case ref_types::rvalue:
return std::is_invocable_v<inst_method, inst_class&&>;
case ref_types::const_rvalue:
return std::is_invocable_v<inst_method, const inst_class&&>;
}
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<inst_method, const inst_class&>
: std::is_invocable_v<inst_method, inst_class&>;
};
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<void**>(data_);
void* to_ptr = pointer_upcast(*from_data_ptr, from_data_class, to_class);
if constexpr ( !std::is_reference_v<Q> ) {
return *static_cast<inst_class_cv*>(to_ptr);
}
if constexpr ( std::is_lvalue_reference_v<Q> ) {
return *static_cast<inst_class_cv*>(to_ptr);
}
}
}
throw_exception_with("bad instance cast");
}
}

View File

@@ -52,12 +52,14 @@ namespace meta_hpp::detail
template < typename T >
concept inst_class_lvalue_ref_kind =
(decay_non_uvalue_kind<T>) &&
(std::is_lvalue_reference_v<T> && std::is_class_v<std::remove_reference_t<T>>);
(std::is_lvalue_reference_v<T>) &&
(std::is_class_v<std::remove_pointer_t<std::remove_reference_t<T>>>);
template < typename T >
concept inst_class_rvalue_ref_kind =
(decay_non_uvalue_kind<T>) &&
(std::is_class_v<T> || (std::is_rvalue_reference_v<T> && std::is_class_v<std::remove_reference_t<T>>));
(!std::is_reference_v<T> || std::is_rvalue_reference_v<T>) &&
(std::is_class_v<std::remove_pointer_t<std::remove_reference_t<T>>>);
}
namespace meta_hpp::detail

View File

@@ -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<const class_type>().*member;
if constexpr ( as_copy ) {
@@ -88,7 +88,7 @@ namespace meta_hpp::detail
if constexpr ( std::is_const_v<value_type> ) {
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<value_type>
&& !inst.is_const()
&& !inst.is_inst_const()
&& inst.can_cast_to<class_type>()
&& arg.can_cast_to<value_type>();
}

View File

@@ -4675,12 +4675,14 @@ namespace meta_hpp::detail
template < typename T >
concept inst_class_lvalue_ref_kind =
(decay_non_uvalue_kind<T>) &&
(std::is_lvalue_reference_v<T> && std::is_class_v<std::remove_reference_t<T>>);
(std::is_lvalue_reference_v<T>) &&
(std::is_class_v<std::remove_pointer_t<std::remove_reference_t<T>>>);
template < typename T >
concept inst_class_rvalue_ref_kind =
(decay_non_uvalue_kind<T>) &&
(std::is_class_v<T> || (std::is_rvalue_reference_v<T> && std::is_class_v<std::remove_reference_t<T>>));
(!std::is_reference_v<T> || std::is_rvalue_reference_v<T>) &&
(std::is_class_v<std::remove_pointer_t<std::remove_reference_t<T>>>);
}
namespace meta_hpp::detail
@@ -4795,6 +4797,9 @@ namespace meta_hpp::detail
virtual ~uarg_base() = default;
template < typename T >
uarg_base(type_list<T>) = 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<T>) = 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<inst_method, inst_class&>;
case ref_types::const_lvalue:
return std::is_invocable_v<inst_method, const inst_class&>;
case ref_types::rvalue:
return std::is_invocable_v<inst_method, inst_class&&>;
case ref_types::const_rvalue:
return std::is_invocable_v<inst_method, const inst_class&&>;
}
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<inst_method, inst_class&>;
case ref_types::const_lvalue:
return std::is_invocable_v<inst_method, const inst_class&>;
case ref_types::rvalue:
return std::is_invocable_v<inst_method, inst_class&&>;
case ref_types::const_rvalue:
return std::is_invocable_v<inst_method, const inst_class&&>;
}
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<inst_method, const inst_class&>
: std::is_invocable_v<inst_method, inst_class&>;
};
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<void**>(data_);
void* to_ptr = pointer_upcast(*from_data_ptr, from_data_class, to_class);
if constexpr ( !std::is_reference_v<Q> ) {
return *static_cast<inst_class_cv*>(to_ptr);
}
if constexpr ( std::is_lvalue_reference_v<Q> ) {
return *static_cast<inst_class_cv*>(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<const class_type>().*member;
if constexpr ( as_copy ) {
@@ -6162,7 +6194,7 @@ namespace meta_hpp::detail
if constexpr ( std::is_const_v<value_type> ) {
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<value_type>
&& !inst.is_const()
&& !inst.is_inst_const()
&& inst.can_cast_to<class_type>()
&& arg.can_cast_to<value_type>();
}

View File

@@ -57,77 +57,105 @@ TEST_CASE("meta/meta_states/member") {
{
CHECK(vm.is_gettable_with<clazz_1>());
CHECK(vm.is_gettable_with<clazz_1*>());
CHECK(vm.is_gettable_with<clazz_1&>());
CHECK(vm.is_gettable_with<clazz_1&&>());
CHECK(vm.is_gettable_with<const clazz_1>());
CHECK(vm.is_gettable_with<const clazz_1*>());
CHECK(vm.is_gettable_with<const clazz_1&>());
CHECK(vm.is_gettable_with<const clazz_1&&>());
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<clazz_2>());
CHECK_FALSE(vm.is_gettable_with<clazz_2*>());
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<clazz_1, int>());
CHECK(vm.is_settable_with<clazz_1*, int>());
CHECK(vm.is_settable_with<clazz_1&, int>());
CHECK(vm.is_settable_with<clazz_1&&, int>());
CHECK(vm.is_settable_with<clazz_1, int&&>());
CHECK(vm.is_settable_with<clazz_1*, int&&>());
CHECK(vm.is_settable_with<clazz_1&, int&&>());
CHECK(vm.is_settable_with<clazz_1&&, int&&>());
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<clazz_1, float>());
CHECK_FALSE(vm.is_settable_with<clazz_1*, float>());
CHECK_FALSE(vm.is_settable_with<clazz_1&, float>());
CHECK_FALSE(vm.is_settable_with<clazz_1&&, float>());
CHECK_FALSE(vm.is_settable_with<const clazz_1, int>());
CHECK_FALSE(vm.is_settable_with<const clazz_1*, int>());
CHECK_FALSE(vm.is_settable_with<const clazz_1&, int>());
CHECK_FALSE(vm.is_settable_with<const clazz_1&&, int>());
CHECK_FALSE(vm.is_settable_with<clazz_2*, int>());
CHECK_FALSE(vm.is_settable_with<clazz_2&, int>());
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<clazz_1>());
CHECK(vm.is_gettable_with<clazz_1*>());
CHECK(vm.is_gettable_with<clazz_1&>());
CHECK(vm.is_gettable_with<clazz_1&&>());
CHECK(vm.is_gettable_with<const clazz_1>());
CHECK(vm.is_gettable_with<const clazz_1*>());
CHECK(vm.is_gettable_with<const clazz_1&>());
CHECK(vm.is_gettable_with<const clazz_1&&>());
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<clazz_2>());
CHECK_FALSE(vm.is_gettable_with<clazz_2*>());
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<clazz_1, int>());
CHECK_FALSE(vm.is_settable_with<clazz_1*, int>());
CHECK_FALSE(vm.is_settable_with<clazz_1&, int>());
CHECK_FALSE(vm.is_settable_with<clazz_1&&, int>());
CHECK_FALSE(vm.is_settable_with<clazz_1, int&&>());
CHECK_FALSE(vm.is_settable_with<clazz_1*, int&&>());
CHECK_FALSE(vm.is_settable_with<clazz_1&, int&&>());
CHECK_FALSE(vm.is_settable_with<clazz_1&&, int&&>());
CHECK_FALSE(vm.is_settable_with<clazz_1, float>());
CHECK_FALSE(vm.is_settable_with<clazz_1*, float>());
CHECK_FALSE(vm.is_settable_with<clazz_1&, float>());
CHECK_FALSE(vm.is_settable_with<clazz_1&&, float>());
CHECK_FALSE(vm.is_settable_with<const clazz_1, int>());
CHECK_FALSE(vm.is_settable_with<const clazz_1*, int>());
CHECK_FALSE(vm.is_settable_with<const clazz_1&, int>());
CHECK_FALSE(vm.is_settable_with<const clazz_1&&, int>());
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<clazz_2*, int>());
CHECK_FALSE(vm.is_settable_with<clazz_2&, int>());
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);
}
}

View File

@@ -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<const derived_clazz&>());
CHECK(mi.is_invocable_with<derived_clazz&&>());
CHECK_FALSE(mi.is_invocable_with<const derived_clazz&&>());
CHECK(mi.is_invocable_with<clazz*>());
CHECK_FALSE(mi.is_invocable_with<const clazz*>());
CHECK(mi.is_invocable_with<derived_clazz*>());
CHECK_FALSE(mi.is_invocable_with<const derived_clazz*>());
}
{
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<decltype(&clazz::non_const_method), clazz&>);
@@ -170,15 +218,56 @@ TEST_CASE("meta/meta_states/method") {
CHECK_FALSE(mi.is_invocable_with<const derived_clazz&>());
CHECK(mi.is_invocable_with<derived_clazz&&>());
CHECK_FALSE(mi.is_invocable_with<const derived_clazz&&>());
CHECK(mi.is_invocable_with<clazz*>());
CHECK_FALSE(mi.is_invocable_with<const clazz*>());
CHECK(mi.is_invocable_with<derived_clazz*>());
CHECK_FALSE(mi.is_invocable_with<const derived_clazz*>());
}
{
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<decltype(&clazz::non_const_method_noexcept), clazz&>);
@@ -215,15 +304,56 @@ TEST_CASE("meta/meta_states/method") {
CHECK(mi.is_invocable_with<const derived_clazz&>());
CHECK(mi.is_invocable_with<derived_clazz&&>());
CHECK(mi.is_invocable_with<const derived_clazz&&>());
CHECK(mi.is_invocable_with<clazz*>());
CHECK(mi.is_invocable_with<const clazz*>());
CHECK(mi.is_invocable_with<derived_clazz*>());
CHECK(mi.is_invocable_with<const derived_clazz*>());
}
{
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<decltype(&clazz::const_method), clazz&>);
@@ -260,15 +390,56 @@ TEST_CASE("meta/meta_states/method") {
CHECK(mi.is_invocable_with<const derived_clazz&>());
CHECK(mi.is_invocable_with<derived_clazz&&>());
CHECK(mi.is_invocable_with<const derived_clazz&&>());
CHECK(mi.is_invocable_with<clazz*>());
CHECK(mi.is_invocable_with<const clazz*>());
CHECK(mi.is_invocable_with<derived_clazz*>());
CHECK(mi.is_invocable_with<const derived_clazz*>());
}
{
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<decltype(&clazz::const_method_noexcept), clazz&>);
@@ -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<decltype(&clazz::non_const_method_ref), clazz&>);
@@ -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<decltype(&clazz::non_const_method_noexcept_ref), clazz&>);
@@ -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<decltype(&clazz::const_method_ref), clazz&>);
@@ -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<decltype(&clazz::const_method_noexcept_ref), clazz&>);
@@ -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<decltype(&clazz::non_const_method_rref), clazz&>);
@@ -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<decltype(&clazz::non_const_method_noexcept_rref), clazz&>);
@@ -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<decltype(&clazz::const_method_rref), clazz&>);
@@ -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<decltype(&clazz::const_method_noexcept_rref), clazz&>);
@@ -661,10 +1120,22 @@ TEST_CASE("meta/meta_states/method") {
CHECK(mi.invoke(cl) == -1);
}
{
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);
}
{
derived_clazz dcl;
CHECK(mi.is_invocable_with<derived_clazz*>());
CHECK(mi.invoke(&dcl) == -2);
}
}
}