diff --git a/CMakeLists.txt b/CMakeLists.txt index 59dfac6..d4d87f3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,6 +31,7 @@ target_compile_options(${PROJECT_NAME} -Wno-exit-time-destructors -Wno-float-equal -Wno-padded + -Wno-shadow-field -Wno-shadow-field-in-constructor -Wno-unknown-warning-option -Wno-weak-vtables diff --git a/headers/meta.hpp/meta_utilities.hpp b/headers/meta.hpp/meta_utilities.hpp index e59abc4..ac698ef 100644 --- a/headers/meta.hpp/meta_utilities.hpp +++ b/headers/meta.hpp/meta_utilities.hpp @@ -97,12 +97,12 @@ namespace meta_hpp::detail arg_base& operator=(const arg_base&) = delete; template < typename T, std::enable_if_t< - std::is_pointer_v || std::is_lvalue_reference_v + (std::is_pointer_v || std::is_lvalue_reference_v) , int> = 0 > explicit arg_base(type_list); template < typename T, std::enable_if_t< - std::is_rvalue_reference_v || + (std::is_rvalue_reference_v) || (!std::is_pointer_v && !std::is_reference_v) , int> = 0 > explicit arg_base(type_list); @@ -139,17 +139,16 @@ namespace meta_hpp::detail arg(const arg&) = delete; arg& operator=(const arg&) = delete; + template < typename T, typename Tp = std::decay_t + , std::enable_if_t, int> = 0 > + explicit arg(T&& v); + template < typename T, typename Tp = std::decay_t , std::enable_if_t, int> = 0 , std::enable_if_t, int> = 0 , std::enable_if_t, int> = 0 > explicit arg(T&& v); - explicit arg(value& v); - explicit arg(value&& v); - explicit arg(const value& v); - explicit arg(const value&& v); - template < typename To > To cast() const; private: @@ -177,12 +176,12 @@ namespace meta_hpp::detail inst_base& operator=(const inst_base&) = delete; template < typename T, std::enable_if_t< - std::is_lvalue_reference_v && std::is_class_v> + (std::is_lvalue_reference_v && std::is_class_v>) , int> = 0> explicit inst_base(type_list); template < typename T, std::enable_if_t< - std::is_class_v || + (std::is_class_v) || (std::is_rvalue_reference_v && std::is_class_v>) , int> = 0> explicit inst_base(type_list); @@ -196,14 +195,17 @@ namespace meta_hpp::detail bool is_lvalue() const noexcept; bool is_rvalue() const noexcept; - any_type get_raw_type() const noexcept; ref_types get_ref_type() const noexcept; + const class_type& get_raw_type() const noexcept; - template < typename To > + template < typename To, std::enable_if_t< + (std::is_class_v) || + (std::is_reference_v && std::is_class_v>) + , int> = 0> bool can_cast_to() const noexcept; private: - any_type raw_type_{}; ref_types ref_type_{}; + class_type raw_type_{}; }; } @@ -220,17 +222,19 @@ namespace meta_hpp::detail inst& operator=(const inst&) = delete; template < typename T, typename Tp = std::decay_t + , std::enable_if_t, int> = 0 > + explicit inst(T&& v); + + template < typename T, class_kind Tp = std::decay_t , std::enable_if_t, int> = 0 , std::enable_if_t, int> = 0 , std::enable_if_t, int> = 0 > explicit inst(T&& v); - explicit inst(value& v); - explicit inst(value&& v); - explicit inst(const value& v); - explicit inst(const value&& v); - - template < typename To > + template < typename To, std::enable_if_t< + (std::is_class_v) || + (std::is_reference_v && std::is_class_v>) + , int> = 0> decltype(auto) cast() const; private: void* data_{}; diff --git a/headers/meta.hpp/meta_utilities/arg.hpp b/headers/meta.hpp/meta_utilities/arg.hpp index 1679ebd..0ef3082 100644 --- a/headers/meta.hpp/meta_utilities/arg.hpp +++ b/headers/meta.hpp/meta_utilities/arg.hpp @@ -12,14 +12,14 @@ namespace meta_hpp::detail { template < typename T, std::enable_if_t< - std::is_pointer_v || std::is_lvalue_reference_v + (std::is_pointer_v || std::is_lvalue_reference_v) , int> > arg_base::arg_base(type_list) : raw_type_{resolve_type>()} , ref_type_{std::is_const_v> ? ref_types::cref : ref_types::ref} {} template < typename T, std::enable_if_t< - std::is_rvalue_reference_v || + (std::is_rvalue_reference_v) || (!std::is_pointer_v && !std::is_reference_v) , int> > arg_base::arg_base(type_list) @@ -126,6 +126,12 @@ namespace meta_hpp::detail namespace meta_hpp::detail { + template < typename T, typename Tp + , std::enable_if_t, int> > + arg::arg(T&& v) + : arg_base{std::forward(v)} + , data_{const_cast(v.data())} {} + template < typename T, typename Tp , std::enable_if_t, int> , std::enable_if_t, int> @@ -134,22 +140,6 @@ namespace meta_hpp::detail : arg_base{type_list{}} , data_{const_cast*>(std::addressof(v))} {} - inline arg::arg(value& v) - : arg_base{v} - , data_{const_cast(v.data())} {} - - inline arg::arg(value&& v) - : arg_base{v} - , data_{const_cast(v.data())} {} - - inline arg::arg(const value& v) - : arg_base{v} - , data_{const_cast(v.data())} {} - - inline arg::arg(const value&& v) - : arg_base{v} - , data_{const_cast(v.data())} {} - template < typename To > To arg::cast() const { if ( !can_cast_to() ) { diff --git a/headers/meta.hpp/meta_utilities/inst.hpp b/headers/meta.hpp/meta_utilities/inst.hpp index fdd374b..b4b7397 100644 --- a/headers/meta.hpp/meta_utilities/inst.hpp +++ b/headers/meta.hpp/meta_utilities/inst.hpp @@ -12,35 +12,51 @@ namespace meta_hpp::detail { template < typename T, std::enable_if_t< - std::is_lvalue_reference_v && std::is_class_v> + (std::is_lvalue_reference_v && std::is_class_v>) , int> > inst_base::inst_base(type_list) - : raw_type_{resolve_type>()} - , ref_type_{std::is_const_v> ? ref_types::cref : ref_types::ref} {} + : ref_type_{std::is_const_v> ? ref_types::cref : ref_types::ref} + , raw_type_{resolve_type>()} {} template < typename T, std::enable_if_t< - std::is_class_v || + (std::is_class_v) || (std::is_rvalue_reference_v && std::is_class_v>) , int> > inst_base::inst_base(type_list) - : raw_type_{resolve_type>()} - , ref_type_{std::is_const_v> ? ref_types::crref : ref_types::rref} {} + : ref_type_{std::is_const_v> ? ref_types::crref : ref_types::rref} + , raw_type_{resolve_type>()} {} inline inst_base::inst_base(value& v) - : raw_type_{v.get_type()} - , ref_type_{ref_types::ref} {} + : ref_type_{ref_types::ref} + , raw_type_{v.get_type().as_class()} { + if ( !v.get_type().is_class() ) { + throw std::logic_error("an attempt to create an instance with a non-class value type"); + } + } inline inst_base::inst_base(value&& v) - : raw_type_{v.get_type()} - , ref_type_{ref_types::rref} {} + : ref_type_{ref_types::rref} + , raw_type_{v.get_type().as_class()} { + if ( !v.get_type().is_class() ) { + throw std::logic_error("an attempt to create an instance with a non-class value type"); + } + } inline inst_base::inst_base(const value& v) - : raw_type_{v.get_type()} - , ref_type_{ref_types::cref} {} + : ref_type_{ref_types::cref} + , raw_type_{v.get_type().as_class()} { + if ( !v.get_type().is_class() ) { + throw std::logic_error("an attempt to create an instance with a non-class value type"); + } + } inline inst_base::inst_base(const value&& v) - : raw_type_{v.get_type()} - , ref_type_{ref_types::crref} {} + : ref_type_{ref_types::crref} + , raw_type_{v.get_type().as_class()} { + if ( !v.get_type().is_class() ) { + throw std::logic_error("an attempt to create an instance with a non-class value type"); + } + } inline bool inst_base::is_const() const noexcept { return ref_type_ == ref_types::cref @@ -57,20 +73,19 @@ namespace meta_hpp::detail || ref_type_ == ref_types::crref; } - inline any_type inst_base::get_raw_type() const noexcept { - return raw_type_; - } - inline inst_base::ref_types inst_base::get_ref_type() const noexcept { return ref_type_; } - template < typename To > - bool inst_base::can_cast_to() const noexcept { - static_assert( - std::is_class_v || - (std::is_reference_v && std::is_class_v>)); + inline const class_type& inst_base::get_raw_type() const noexcept { + return raw_type_; + } + template < typename To, std::enable_if_t< + (std::is_class_v) || + (std::is_reference_v && std::is_class_v>) + , int> > + bool inst_base::can_cast_to() const noexcept { constexpr bool to_const = std::is_const_v>; if constexpr ( !to_const ) { @@ -92,13 +107,21 @@ namespace meta_hpp::detail } using to_raw_type = std::remove_cvref_t; - return get_raw_type() == resolve_type(); + + return get_raw_type() == resolve_type() + || get_raw_type().is_derived_from(resolve_type()); } } namespace meta_hpp::detail { template < typename T, typename Tp + , std::enable_if_t, int> > + inst::inst(T&& v) + : inst_base{std::forward(v)} + , data_{const_cast(v.data())} {} + + template < typename T, class_kind Tp , std::enable_if_t, int> , std::enable_if_t, int> , std::enable_if_t, int> > @@ -106,26 +129,13 @@ namespace meta_hpp::detail : inst_base{type_list{}} , data_{const_cast*>(std::addressof(v))} {} - inline inst::inst(value& v) - : inst_base{v} - , data_{const_cast(v.data())} {} - - inline inst::inst(value&& v) - : inst_base{v} - , data_{const_cast(v.data())} {} - - inline inst::inst(const value& v) - : inst_base{v} - , data_{const_cast(v.data())} {} - - inline inst::inst(const value&& v) - : inst_base{v} - , data_{const_cast(v.data())} {} - - template < typename To > + template < typename To, std::enable_if_t< + (std::is_class_v) || + (std::is_reference_v && std::is_class_v>) + , int> > decltype(auto) inst::cast() const { if ( !can_cast_to() ) { - throw std::logic_error("bad inst cast"); + throw std::logic_error("bad an instance cast"); } if constexpr ( std::is_reference_v ) { diff --git a/untests/meta_states/method_tests.cpp b/untests/meta_states/method_tests.cpp index 7258f3b..c8c6635 100644 --- a/untests/meta_states/method_tests.cpp +++ b/untests/meta_states/method_tests.cpp @@ -58,12 +58,19 @@ namespace int const_method_noexcept_rref_volatile() volatile const && noexcept { return 12; } }; + struct derived_clazz : clazz { + [[maybe_unused]] derived_clazz() = default; + }; + struct clazz2 {}; } TEST_CASE("meta/meta_states/method") { namespace meta = meta_hpp; + meta::class_() + .base_(); + meta::class_() .method_("non_const_method", &clazz::non_const_method) .method_("non_const_method_noexcept", &clazz::non_const_method_noexcept) @@ -151,6 +158,16 @@ TEST_CASE("meta/meta_states/method") { CHECK_FALSE(mi2.is_invocable_with()); CHECK(mi2.is_invocable_with()); CHECK_FALSE(mi2.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(mi2.is_invocable_with()); + CHECK_FALSE(mi2.is_invocable_with()); + CHECK(mi2.is_invocable_with()); + CHECK_FALSE(mi2.is_invocable_with()); } { @@ -176,6 +193,16 @@ TEST_CASE("meta/meta_states/method") { static_assert(!std::is_invocable_v); static_assert(std::is_invocable_v); static_assert(!std::is_invocable_v); + + static_assert(std::is_invocable_v); + static_assert(!std::is_invocable_v); + static_assert(std::is_invocable_v); + static_assert(!std::is_invocable_v); + + static_assert(std::is_invocable_v); + static_assert(!std::is_invocable_v); + static_assert(std::is_invocable_v); + static_assert(!std::is_invocable_v); } SUBCASE("non_const_method_noexcept") { @@ -210,6 +237,16 @@ TEST_CASE("meta/meta_states/method") { CHECK_FALSE(mi2.is_invocable_with()); CHECK(mi2.is_invocable_with()); CHECK_FALSE(mi2.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(mi2.is_invocable_with()); + CHECK_FALSE(mi2.is_invocable_with()); + CHECK(mi2.is_invocable_with()); + CHECK_FALSE(mi2.is_invocable_with()); } { @@ -235,6 +272,16 @@ TEST_CASE("meta/meta_states/method") { static_assert(!std::is_invocable_v); static_assert(std::is_invocable_v); static_assert(!std::is_invocable_v); + + static_assert(std::is_invocable_v); + static_assert(!std::is_invocable_v); + static_assert(std::is_invocable_v); + static_assert(!std::is_invocable_v); + + static_assert(std::is_invocable_v); + static_assert(!std::is_invocable_v); + static_assert(std::is_invocable_v); + static_assert(!std::is_invocable_v); } SUBCASE("const_method") { @@ -269,6 +316,16 @@ TEST_CASE("meta/meta_states/method") { CHECK(mi2.is_invocable_with()); CHECK(mi2.is_invocable_with()); CHECK(mi2.is_invocable_with()); + + CHECK(mi.is_invocable_with()); + CHECK(mi.is_invocable_with()); + CHECK(mi.is_invocable_with()); + CHECK(mi.is_invocable_with()); + + CHECK(mi2.is_invocable_with()); + CHECK(mi2.is_invocable_with()); + CHECK(mi2.is_invocable_with()); + CHECK(mi2.is_invocable_with()); } { @@ -294,6 +351,16 @@ TEST_CASE("meta/meta_states/method") { static_assert(std::is_invocable_v); static_assert(std::is_invocable_v); static_assert(std::is_invocable_v); + + static_assert(std::is_invocable_v); + static_assert(std::is_invocable_v); + static_assert(std::is_invocable_v); + static_assert(std::is_invocable_v); + + static_assert(std::is_invocable_v); + static_assert(std::is_invocable_v); + static_assert(std::is_invocable_v); + static_assert(std::is_invocable_v); } SUBCASE("const_method_noexcept") { @@ -328,6 +395,16 @@ TEST_CASE("meta/meta_states/method") { CHECK(mi2.is_invocable_with()); CHECK(mi2.is_invocable_with()); CHECK(mi2.is_invocable_with()); + + CHECK(mi.is_invocable_with()); + CHECK(mi.is_invocable_with()); + CHECK(mi.is_invocable_with()); + CHECK(mi.is_invocable_with()); + + CHECK(mi2.is_invocable_with()); + CHECK(mi2.is_invocable_with()); + CHECK(mi2.is_invocable_with()); + CHECK(mi2.is_invocable_with()); } { @@ -353,6 +430,16 @@ TEST_CASE("meta/meta_states/method") { static_assert(std::is_invocable_v); static_assert(std::is_invocable_v); static_assert(std::is_invocable_v); + + static_assert(std::is_invocable_v); + static_assert(std::is_invocable_v); + static_assert(std::is_invocable_v); + static_assert(std::is_invocable_v); + + static_assert(std::is_invocable_v); + static_assert(std::is_invocable_v); + static_assert(std::is_invocable_v); + static_assert(std::is_invocable_v); } SUBCASE("non_const_method_ref") { @@ -387,6 +474,16 @@ TEST_CASE("meta/meta_states/method") { CHECK_FALSE(mi2.is_invocable_with()); CHECK_FALSE(mi2.is_invocable_with()); CHECK_FALSE(mi2.is_invocable_with()); + + CHECK(mi.is_invocable_with()); + CHECK_FALSE(mi.is_invocable_with()); + CHECK_FALSE(mi.is_invocable_with()); + CHECK_FALSE(mi.is_invocable_with()); + + CHECK(mi2.is_invocable_with()); + CHECK_FALSE(mi2.is_invocable_with()); + CHECK_FALSE(mi2.is_invocable_with()); + CHECK_FALSE(mi2.is_invocable_with()); } { @@ -412,6 +509,16 @@ TEST_CASE("meta/meta_states/method") { static_assert(!std::is_invocable_v); static_assert(!std::is_invocable_v); static_assert(!std::is_invocable_v); + + static_assert(std::is_invocable_v); + static_assert(!std::is_invocable_v); + static_assert(!std::is_invocable_v); + static_assert(!std::is_invocable_v); + + static_assert(std::is_invocable_v); + static_assert(!std::is_invocable_v); + static_assert(!std::is_invocable_v); + static_assert(!std::is_invocable_v); } SUBCASE("non_const_method_noexcept_ref") { @@ -446,6 +553,16 @@ TEST_CASE("meta/meta_states/method") { CHECK_FALSE(mi2.is_invocable_with()); CHECK_FALSE(mi2.is_invocable_with()); CHECK_FALSE(mi2.is_invocable_with()); + + CHECK(mi.is_invocable_with()); + CHECK_FALSE(mi.is_invocable_with()); + CHECK_FALSE(mi.is_invocable_with()); + CHECK_FALSE(mi.is_invocable_with()); + + CHECK(mi2.is_invocable_with()); + CHECK_FALSE(mi2.is_invocable_with()); + CHECK_FALSE(mi2.is_invocable_with()); + CHECK_FALSE(mi2.is_invocable_with()); } { @@ -471,6 +588,16 @@ TEST_CASE("meta/meta_states/method") { static_assert(!std::is_invocable_v); static_assert(!std::is_invocable_v); static_assert(!std::is_invocable_v); + + static_assert(std::is_invocable_v); + static_assert(!std::is_invocable_v); + static_assert(!std::is_invocable_v); + static_assert(!std::is_invocable_v); + + static_assert(std::is_invocable_v); + static_assert(!std::is_invocable_v); + static_assert(!std::is_invocable_v); + static_assert(!std::is_invocable_v); } SUBCASE("const_method_ref") { @@ -505,6 +632,16 @@ TEST_CASE("meta/meta_states/method") { CHECK(mi2.is_invocable_with()); CHECK_FALSE(mi2.is_invocable_with()); CHECK_FALSE(mi2.is_invocable_with()); + + CHECK(mi.is_invocable_with()); + CHECK(mi.is_invocable_with()); + CHECK_FALSE(mi.is_invocable_with()); + CHECK_FALSE(mi.is_invocable_with()); + + CHECK(mi2.is_invocable_with()); + CHECK(mi2.is_invocable_with()); + CHECK_FALSE(mi2.is_invocable_with()); + CHECK_FALSE(mi2.is_invocable_with()); } { @@ -530,6 +667,16 @@ TEST_CASE("meta/meta_states/method") { static_assert(std::is_invocable_v); static_assert(!std::is_invocable_v); static_assert(!std::is_invocable_v); + + static_assert(std::is_invocable_v); + static_assert(std::is_invocable_v); + //static_assert(!std::is_invocable_v); // msvc issue + //static_assert(!std::is_invocable_v); // msvc issue + + static_assert(std::is_invocable_v); + static_assert(std::is_invocable_v); + static_assert(!std::is_invocable_v); + static_assert(!std::is_invocable_v); } SUBCASE("const_method_noexcept_ref") { @@ -564,6 +711,16 @@ TEST_CASE("meta/meta_states/method") { CHECK(mi2.is_invocable_with()); CHECK_FALSE(mi2.is_invocable_with()); CHECK_FALSE(mi2.is_invocable_with()); + + CHECK(mi.is_invocable_with()); + CHECK(mi.is_invocable_with()); + CHECK_FALSE(mi.is_invocable_with()); + CHECK_FALSE(mi.is_invocable_with()); + + CHECK(mi2.is_invocable_with()); + CHECK(mi2.is_invocable_with()); + CHECK_FALSE(mi2.is_invocable_with()); + CHECK_FALSE(mi2.is_invocable_with()); } { @@ -589,6 +746,16 @@ TEST_CASE("meta/meta_states/method") { static_assert(std::is_invocable_v); static_assert(!std::is_invocable_v); static_assert(!std::is_invocable_v); + + static_assert(std::is_invocable_v); + static_assert(std::is_invocable_v); + //static_assert(!std::is_invocable_v); // msvc issue + //static_assert(!std::is_invocable_v); // msvc issue + + static_assert(std::is_invocable_v); + static_assert(std::is_invocable_v); + static_assert(!std::is_invocable_v); + static_assert(!std::is_invocable_v); } SUBCASE("non_const_method_rref") { @@ -623,6 +790,16 @@ TEST_CASE("meta/meta_states/method") { CHECK_FALSE(mi2.is_invocable_with()); CHECK(mi2.is_invocable_with()); CHECK_FALSE(mi2.is_invocable_with()); + + CHECK_FALSE(mi.is_invocable_with()); + CHECK_FALSE(mi.is_invocable_with()); + CHECK(mi.is_invocable_with()); + CHECK_FALSE(mi.is_invocable_with()); + + CHECK_FALSE(mi2.is_invocable_with()); + CHECK_FALSE(mi2.is_invocable_with()); + CHECK(mi2.is_invocable_with()); + CHECK_FALSE(mi2.is_invocable_with()); } { @@ -648,6 +825,16 @@ TEST_CASE("meta/meta_states/method") { static_assert(!std::is_invocable_v); static_assert(std::is_invocable_v); static_assert(!std::is_invocable_v); + + static_assert(!std::is_invocable_v); + static_assert(!std::is_invocable_v); + static_assert(std::is_invocable_v); + static_assert(!std::is_invocable_v); + + static_assert(!std::is_invocable_v); + static_assert(!std::is_invocable_v); + static_assert(std::is_invocable_v); + static_assert(!std::is_invocable_v); } SUBCASE("non_const_method_noexcept_rref") { @@ -682,6 +869,16 @@ TEST_CASE("meta/meta_states/method") { CHECK_FALSE(mi2.is_invocable_with()); CHECK(mi2.is_invocable_with()); CHECK_FALSE(mi2.is_invocable_with()); + + CHECK_FALSE(mi.is_invocable_with()); + CHECK_FALSE(mi.is_invocable_with()); + CHECK(mi.is_invocable_with()); + CHECK_FALSE(mi.is_invocable_with()); + + CHECK_FALSE(mi2.is_invocable_with()); + CHECK_FALSE(mi2.is_invocable_with()); + CHECK(mi2.is_invocable_with()); + CHECK_FALSE(mi2.is_invocable_with()); } { @@ -707,6 +904,16 @@ TEST_CASE("meta/meta_states/method") { static_assert(!std::is_invocable_v); static_assert(std::is_invocable_v); static_assert(!std::is_invocable_v); + + static_assert(!std::is_invocable_v); + static_assert(!std::is_invocable_v); + static_assert(std::is_invocable_v); + static_assert(!std::is_invocable_v); + + static_assert(!std::is_invocable_v); + static_assert(!std::is_invocable_v); + static_assert(std::is_invocable_v); + static_assert(!std::is_invocable_v); } SUBCASE("const_method_rref") { @@ -741,6 +948,16 @@ TEST_CASE("meta/meta_states/method") { CHECK_FALSE(mi2.is_invocable_with()); CHECK(mi2.is_invocable_with()); CHECK(mi2.is_invocable_with()); + + CHECK_FALSE(mi.is_invocable_with()); + CHECK_FALSE(mi.is_invocable_with()); + CHECK(mi.is_invocable_with()); + CHECK(mi.is_invocable_with()); + + CHECK_FALSE(mi2.is_invocable_with()); + CHECK_FALSE(mi2.is_invocable_with()); + CHECK(mi2.is_invocable_with()); + CHECK(mi2.is_invocable_with()); } { @@ -766,6 +983,16 @@ TEST_CASE("meta/meta_states/method") { static_assert(!std::is_invocable_v); static_assert(std::is_invocable_v); static_assert(std::is_invocable_v); + + static_assert(!std::is_invocable_v); + static_assert(!std::is_invocable_v); + static_assert(std::is_invocable_v); + static_assert(std::is_invocable_v); + + static_assert(!std::is_invocable_v); + static_assert(!std::is_invocable_v); + static_assert(std::is_invocable_v); + static_assert(std::is_invocable_v); } SUBCASE("const_method_noexcept_rref") { @@ -800,6 +1027,16 @@ TEST_CASE("meta/meta_states/method") { CHECK_FALSE(mi2.is_invocable_with()); CHECK(mi2.is_invocable_with()); CHECK(mi2.is_invocable_with()); + + CHECK_FALSE(mi.is_invocable_with()); + CHECK_FALSE(mi.is_invocable_with()); + CHECK(mi.is_invocable_with()); + CHECK(mi.is_invocable_with()); + + CHECK_FALSE(mi2.is_invocable_with()); + CHECK_FALSE(mi2.is_invocable_with()); + CHECK(mi2.is_invocable_with()); + CHECK(mi2.is_invocable_with()); } { @@ -825,5 +1062,15 @@ TEST_CASE("meta/meta_states/method") { static_assert(!std::is_invocable_v); static_assert(std::is_invocable_v); static_assert(std::is_invocable_v); + + static_assert(!std::is_invocable_v); + static_assert(!std::is_invocable_v); + static_assert(std::is_invocable_v); + static_assert(std::is_invocable_v); + + static_assert(!std::is_invocable_v); + static_assert(!std::is_invocable_v); + static_assert(std::is_invocable_v); + static_assert(std::is_invocable_v); } } diff --git a/untests/meta_utilities/arg_tests.cpp b/untests/meta_utilities/arg_tests.cpp index f895c7c..af794ee 100644 --- a/untests/meta_utilities/arg_tests.cpp +++ b/untests/meta_utilities/arg_tests.cpp @@ -69,6 +69,128 @@ namespace } } +TEST_CASE("features/meta_utilities/arg/from_value") { + namespace meta = meta_hpp; + + SUBCASE("ptr") { + ivec2 v{1,2}; + ivec2* vp = &v; + meta::value vvp{vp}; + meta::detail::arg a{vvp}; + + CHECK(a.get_raw_type() == meta::resolve_type()); + CHECK(a.get_ref_type() == meta::detail::arg::ref_types::ref); + } + + SUBCASE("rptr") { + ivec2 v{1,2}; + ivec2* vp = &v; + meta::value vvp{vp}; + meta::detail::arg a{std::move(vvp)}; + + CHECK(a.get_raw_type() == meta::resolve_type()); + CHECK(a.get_ref_type() == meta::detail::arg::ref_types::rref); + } + + SUBCASE("ptr_c") { + ivec2 v{1,2}; + ivec2* const vp = &v; + const meta::value vvp{vp}; + meta::detail::arg a{vvp}; + + CHECK(a.get_raw_type() == meta::resolve_type()); + CHECK(a.get_ref_type() == meta::detail::arg::ref_types::cref); + } + + SUBCASE("rptr_c") { + ivec2 v{1,2}; + ivec2* const vp = &v; + const meta::value vvp{vp}; + meta::detail::arg a{std::move(vvp)}; + + CHECK(a.get_raw_type() == meta::resolve_type()); + CHECK(a.get_ref_type() == meta::detail::arg::ref_types::crref); + } + + SUBCASE("cptr") { + const ivec2 v{1,2}; + const ivec2* vp = &v; + meta::value vvp{vp}; + meta::detail::arg a{vvp}; + + CHECK(a.get_raw_type() == meta::resolve_type()); + CHECK(a.get_ref_type() == meta::detail::arg::ref_types::ref); + } + + SUBCASE("crptr") { + const ivec2 v{1,2}; + const ivec2* vp = &v; + meta::value vvp{vp}; + meta::detail::arg a{std::move(vvp)}; + + CHECK(a.get_raw_type() == meta::resolve_type()); + CHECK(a.get_ref_type() == meta::detail::arg::ref_types::rref); + } + + SUBCASE("cptr_c") { + const ivec2 v{1,2}; + const ivec2* const vp = &v; + const meta::value vvp{vp}; + meta::detail::arg a{vvp}; + + CHECK(a.get_raw_type() == meta::resolve_type()); + CHECK(a.get_ref_type() == meta::detail::arg::ref_types::cref); + } + + SUBCASE("crptr_c") { + const ivec2 v{1,2}; + const ivec2* const vp = &v; + const meta::value vvp{vp}; + meta::detail::arg a{std::move(vvp)}; + + CHECK(a.get_raw_type() == meta::resolve_type()); + CHECK(a.get_ref_type() == meta::detail::arg::ref_types::crref); + } + + SUBCASE("ref") { + ivec2 v{1,2}; + ivec2& vr = v; + meta::value vvr{vr}; + meta::detail::arg a{vvr}; + + CHECK(a.get_raw_type() == meta::resolve_type()); + CHECK(a.get_ref_type() == meta::detail::arg::ref_types::ref); + } + + SUBCASE("cref") { + const ivec2 v{1,2}; + const ivec2& vr = v; + const meta::value vvr{vr}; + meta::detail::arg a{vvr}; + + CHECK(a.get_raw_type() == meta::resolve_type()); + CHECK(a.get_ref_type() == meta::detail::arg::ref_types::cref); + } + + SUBCASE("rref") { + ivec2 v{1,2}; + meta::value vv{v}; + meta::detail::arg a{std::move(vv)}; + + CHECK(a.get_raw_type() == meta::resolve_type()); + CHECK(a.get_ref_type() == meta::detail::arg::ref_types::rref); + } + + SUBCASE("crref") { + const ivec2 v{1,2}; + const meta::value vv{v}; + meta::detail::arg a{std::move(vv)}; + + CHECK(a.get_raw_type() == meta::resolve_type()); + CHECK(a.get_ref_type() == meta::detail::arg::ref_types::crref); + } +} + TEST_CASE("features/meta_utilities/arg/type") { namespace meta = meta_hpp; diff --git a/untests/meta_utilities/inst_tests.cpp b/untests/meta_utilities/inst_tests.cpp index 5f29099..9048994 100644 --- a/untests/meta_utilities/inst_tests.cpp +++ b/untests/meta_utilities/inst_tests.cpp @@ -31,42 +31,110 @@ namespace ivec2& operator=(ivec2&&) = delete; ivec2& operator=(const ivec2&) = delete; }; + + struct derived_ivec2 : ivec2 { + [[maybe_unused]] derived_ivec2() = default; + [[maybe_unused]] explicit derived_ivec2(int v): ivec2{v, v} {} + [[maybe_unused]] derived_ivec2(int x, int y): ivec2{x, y} {} + }; } TEST_CASE("features/meta_utilities/inst") { namespace meta = meta_hpp; SUBCASE("ref") { - ivec2 v{1,2}; - ivec2& vr = v; - meta::detail::inst a{vr}; + { + derived_ivec2 v{1,2}; + derived_ivec2& vr = v; + meta::detail::inst a{vr}; - CHECK(a.get_raw_type() == meta::resolve_type()); - CHECK(a.get_ref_type() == meta::detail::inst::ref_types::ref); + CHECK(a.get_raw_type() == meta::resolve_type()); + CHECK(a.get_ref_type() == meta::detail::inst::ref_types::ref); + } + { + meta::value v{derived_ivec2{1,2}}; + meta::value& vr = v; + meta::detail::inst a{vr}; + + CHECK(a.get_raw_type() == meta::resolve_type()); + CHECK(a.get_ref_type() == meta::detail::inst::ref_types::ref); + + CHECK(a.can_cast_to()); + CHECK(a.can_cast_to()); + CHECK(a.can_cast_to()); + CHECK_FALSE(a.can_cast_to()); + CHECK_FALSE(a.can_cast_to()); + } } SUBCASE("cref") { - const ivec2 v{1,2}; - const ivec2& vr = v; - meta::detail::inst a{vr}; + { + const derived_ivec2 v{1,2}; + const derived_ivec2& vr = v; + meta::detail::inst a{vr}; - CHECK(a.get_raw_type() == meta::resolve_type()); - CHECK(a.get_ref_type() == meta::detail::inst::ref_types::cref); + CHECK(a.get_raw_type() == meta::resolve_type()); + CHECK(a.get_ref_type() == meta::detail::inst::ref_types::cref); + } + { + const meta::value v{derived_ivec2{1,2}}; + const meta::value& vr = v; + meta::detail::inst a{vr}; + + CHECK(a.get_raw_type() == meta::resolve_type()); + CHECK(a.get_ref_type() == meta::detail::inst::ref_types::cref); + + CHECK_FALSE(a.can_cast_to()); + CHECK_FALSE(a.can_cast_to()); + CHECK(a.can_cast_to()); + CHECK_FALSE(a.can_cast_to()); + CHECK_FALSE(a.can_cast_to()); + } } SUBCASE("rref") { - ivec2 v{1,2}; - meta::detail::inst a{std::move(v)}; + { + derived_ivec2 v{1,2}; + meta::detail::inst a{std::move(v)}; - CHECK(a.get_raw_type() == meta::resolve_type()); - CHECK(a.get_ref_type() == meta::detail::inst::ref_types::rref); + CHECK(a.get_raw_type() == meta::resolve_type()); + CHECK(a.get_ref_type() == meta::detail::inst::ref_types::rref); + } + { + meta::value v{derived_ivec2{1,2}}; + meta::detail::inst a{std::move(v)}; + + CHECK(a.get_raw_type() == meta::resolve_type()); + CHECK(a.get_ref_type() == meta::detail::inst::ref_types::rref); + + CHECK(a.can_cast_to()); + CHECK_FALSE(a.can_cast_to()); + CHECK_FALSE(a.can_cast_to()); + CHECK(a.can_cast_to()); + CHECK(a.can_cast_to()); + } } SUBCASE("crref") { - const ivec2 v{1,2}; - meta::detail::inst a{std::move(v)}; + { + const derived_ivec2 v{1,2}; + meta::detail::inst a{std::move(v)}; - CHECK(a.get_raw_type() == meta::resolve_type()); - CHECK(a.get_ref_type() == meta::detail::inst::ref_types::crref); + CHECK(a.get_raw_type() == meta::resolve_type()); + CHECK(a.get_ref_type() == meta::detail::inst::ref_types::crref); + } + { + const meta::value v{derived_ivec2{1,2}}; + meta::detail::inst a{std::move(v)}; + + CHECK(a.get_raw_type() == meta::resolve_type()); + CHECK(a.get_ref_type() == meta::detail::inst::ref_types::crref); + + CHECK_FALSE(a.can_cast_to()); + CHECK_FALSE(a.can_cast_to()); + CHECK_FALSE(a.can_cast_to()); + CHECK_FALSE(a.can_cast_to()); + CHECK(a.can_cast_to()); + } } }