diff --git a/ROADMAP.md b/ROADMAP.md index 78c1df0..7cf32af 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -8,7 +8,6 @@ - fix all includes to work with the library more flexible - test and support shared libraries - remove `resolve_poly_type`, use `resolve_type(T&&)` instead -- add `match` function to `any_type` class ## Thoughts diff --git a/develop/singles/headers/meta.hpp/meta_all.hpp b/develop/singles/headers/meta.hpp/meta_all.hpp index 86bc569..e3a50cf 100644 --- a/develop/singles/headers/meta.hpp/meta_all.hpp +++ b/develop/singles/headers/meta.hpp/meta_all.hpp @@ -1534,6 +1534,8 @@ namespace meta_hpp using detail::hashed_string; using detail::memory_buffer; + using detail::overloaded; + using detail::select_const; using detail::select_non_const; using detail::select_overload; @@ -2615,6 +2617,9 @@ namespace meta_hpp template < type_family Type > [[nodiscard]] Type as() const noexcept; + template < typename F > + bool match(F&& f) const; + [[nodiscard]] bool is_array() const noexcept; [[nodiscard]] bool is_class() const noexcept; [[nodiscard]] bool is_constructor() const noexcept; @@ -9275,6 +9280,58 @@ namespace meta_hpp } } + template < typename F > + bool any_type::match(F&& f) const { + if ( !is_valid() ) { + return false; + } + + switch ( get_kind() ) { + case type_kind::array_: + std::invoke(std::forward(f), as_array()); + return true; + case type_kind::class_: + std::invoke(std::forward(f), as_class()); + return true; + case type_kind::constructor_: + std::invoke(std::forward(f), as_constructor()); + return true; + case type_kind::destructor_: + std::invoke(std::forward(f), as_destructor()); + return true; + case type_kind::enum_: + std::invoke(std::forward(f), as_enum()); + return true; + case type_kind::function_: + std::invoke(std::forward(f), as_function()); + return true; + case type_kind::member_: + std::invoke(std::forward(f), as_member()); + return true; + case type_kind::method_: + std::invoke(std::forward(f), as_method()); + return true; + case type_kind::nullptr_: + std::invoke(std::forward(f), as_nullptr()); + return true; + case type_kind::number_: + std::invoke(std::forward(f), as_number()); + return true; + case type_kind::pointer_: + std::invoke(std::forward(f), as_pointer()); + return true; + case type_kind::reference_: + std::invoke(std::forward(f), as_reference()); + return true; + case type_kind::void_: + std::invoke(std::forward(f), as_void()); + return true; + } + + META_HPP_ASSERT(false); + return false; + } + inline bool any_type::is_array() const noexcept { return is(); } diff --git a/develop/untests/meta_types/any_type_tests.cpp b/develop/untests/meta_types/any_type_tests.cpp index 6307d8e..5282a06 100644 --- a/develop/untests/meta_types/any_type_tests.cpp +++ b/develop/untests/meta_types/any_type_tests.cpp @@ -43,6 +43,10 @@ TEST_CASE("meta/meta_types/any_type") { CHECK_FALSE(type.is_array()); CHECK_FALSE(type.as_array()); + + CHECK_FALSE(type.match(meta::overloaded{ + [](auto&&){} + })); } SUBCASE("array") { @@ -61,6 +65,15 @@ TEST_CASE("meta/meta_types/any_type") { const meta::array_type& specific_type = type.as_array(); REQUIRE(specific_type); CHECK(specific_type.get_id() == type.get_id()); + + { + bool match_called = false; + CHECK(type.match(meta::overloaded{ + [&type, &match_called](meta::array_type t){ CHECK(t == type); match_called = true; }, + [](auto&&){} + })); + CHECK(match_called); + } } SUBCASE("class") { @@ -79,6 +92,15 @@ TEST_CASE("meta/meta_types/any_type") { const meta::class_type& specific_type = type.as_class(); REQUIRE(specific_type); CHECK(specific_type.get_id() == type.get_id()); + + { + bool match_called = false; + CHECK(type.match(meta::overloaded{ + [&type, &match_called](meta::class_type t){ CHECK(t == type); match_called = true; }, + [](auto&&){} + })); + CHECK(match_called); + } } SUBCASE("ctor") { @@ -97,6 +119,15 @@ TEST_CASE("meta/meta_types/any_type") { const meta::constructor_type& specific_type = type.as_constructor(); REQUIRE(specific_type); CHECK(specific_type.get_id() == type.get_id()); + + { + bool match_called = false; + CHECK(type.match(meta::overloaded{ + [&type, &match_called](meta::constructor_type t){ CHECK(t == type); match_called = true; }, + [](auto&&){} + })); + CHECK(match_called); + } } SUBCASE("enum") { @@ -115,6 +146,15 @@ TEST_CASE("meta/meta_types/any_type") { const meta::enum_type& specific_type = type.as_enum(); REQUIRE(specific_type); CHECK(specific_type.get_id() == type.get_id()); + + { + bool match_called = false; + CHECK(type.match(meta::overloaded{ + [&type, &match_called](meta::enum_type t){ CHECK(t == type); match_called = true; }, + [](auto&&){} + })); + CHECK(match_called); + } } SUBCASE("function") { @@ -133,6 +173,15 @@ TEST_CASE("meta/meta_types/any_type") { const meta::function_type& specific_type = type.as_function(); REQUIRE(specific_type); CHECK(specific_type.get_id() == type.get_id()); + + { + bool match_called = false; + CHECK(type.match(meta::overloaded{ + [&type, &match_called](meta::function_type t){ CHECK(t == type); match_called = true; }, + [](auto&&){} + })); + CHECK(match_called); + } } SUBCASE("member") { @@ -151,6 +200,15 @@ TEST_CASE("meta/meta_types/any_type") { const meta::member_type& specific_type = type.as_member(); REQUIRE(specific_type); CHECK(specific_type.get_id() == type.get_id()); + + { + bool match_called = false; + CHECK(type.match(meta::overloaded{ + [&type, &match_called](meta::member_type t){ CHECK(t == type); match_called = true; }, + [](auto&&){} + })); + CHECK(match_called); + } } SUBCASE("method") { @@ -169,6 +227,15 @@ TEST_CASE("meta/meta_types/any_type") { const meta::method_type& specific_type = type.as_method(); REQUIRE(specific_type); CHECK(specific_type.get_id() == type.get_id()); + + { + bool match_called = false; + CHECK(type.match(meta::overloaded{ + [&type, &match_called](meta::method_type t){ CHECK(t == type); match_called = true; }, + [](auto&&){} + })); + CHECK(match_called); + } } SUBCASE("nullptr") { @@ -187,6 +254,15 @@ TEST_CASE("meta/meta_types/any_type") { const meta::nullptr_type& specific_type = type.as_nullptr(); REQUIRE(specific_type); CHECK(specific_type.get_id() == type.get_id()); + + { + bool match_called = false; + CHECK(type.match(meta::overloaded{ + [&type, &match_called](meta::nullptr_type t){ CHECK(t == type); match_called = true; }, + [](auto&&){} + })); + CHECK(match_called); + } } SUBCASE("number") { @@ -205,6 +281,15 @@ TEST_CASE("meta/meta_types/any_type") { const meta::number_type& specific_type = type.as_number(); REQUIRE(specific_type); CHECK(specific_type.get_id() == type.get_id()); + + { + bool match_called = false; + CHECK(type.match(meta::overloaded{ + [&type, &match_called](meta::number_type t){ CHECK(t == type); match_called = true; }, + [](auto&&){} + })); + CHECK(match_called); + } } SUBCASE("pointer") { @@ -223,6 +308,15 @@ TEST_CASE("meta/meta_types/any_type") { const meta::pointer_type& specific_type = type.as_pointer(); REQUIRE(specific_type); CHECK(specific_type.get_id() == type.get_id()); + + { + bool match_called = false; + CHECK(type.match(meta::overloaded{ + [&type, &match_called](meta::pointer_type t){ CHECK(t == type); match_called = true; }, + [](auto&&){} + })); + CHECK(match_called); + } } SUBCASE("reference") { @@ -239,6 +333,15 @@ TEST_CASE("meta/meta_types/any_type") { const meta::reference_type& specific_type = type.as_reference(); REQUIRE(specific_type); CHECK(specific_type.get_id() == type.get_id()); + + { + bool match_called = false; + CHECK(type.match(meta::overloaded{ + [&type, &match_called](meta::reference_type t){ CHECK(t == type); match_called = true; }, + [](auto&&){} + })); + CHECK(match_called); + } } SUBCASE("void") { @@ -255,6 +358,15 @@ TEST_CASE("meta/meta_types/any_type") { const meta::void_type& specific_type = type.as_void(); REQUIRE(specific_type); CHECK(specific_type.get_id() == type.get_id()); + + { + bool match_called = false; + CHECK(type.match(meta::overloaded{ + [&type, &match_called](meta::void_type t){ CHECK(t == type); match_called = true; }, + [](auto&&){} + })); + CHECK(match_called); + } } SUBCASE("is/as") { diff --git a/headers/meta.hpp/meta_base.hpp b/headers/meta.hpp/meta_base.hpp index 593f5d0..628f5b5 100644 --- a/headers/meta.hpp/meta_base.hpp +++ b/headers/meta.hpp/meta_base.hpp @@ -38,6 +38,8 @@ namespace meta_hpp using detail::hashed_string; using detail::memory_buffer; + using detail::overloaded; + using detail::select_const; using detail::select_non_const; using detail::select_overload; diff --git a/headers/meta.hpp/meta_types.hpp b/headers/meta.hpp/meta_types.hpp index bc12442..e5e2601 100644 --- a/headers/meta.hpp/meta_types.hpp +++ b/headers/meta.hpp/meta_types.hpp @@ -157,6 +157,9 @@ namespace meta_hpp template < type_family Type > [[nodiscard]] Type as() const noexcept; + template < typename F > + bool match(F&& f) const; + [[nodiscard]] bool is_array() const noexcept; [[nodiscard]] bool is_class() const noexcept; [[nodiscard]] bool is_constructor() const noexcept; diff --git a/headers/meta.hpp/meta_types/any_type.hpp b/headers/meta.hpp/meta_types/any_type.hpp index ee61fad..e6dfd65 100644 --- a/headers/meta.hpp/meta_types/any_type.hpp +++ b/headers/meta.hpp/meta_types/any_type.hpp @@ -38,6 +38,58 @@ namespace meta_hpp } } + template < typename F > + bool any_type::match(F&& f) const { + if ( !is_valid() ) { + return false; + } + + switch ( get_kind() ) { + case type_kind::array_: + std::invoke(std::forward(f), as_array()); + return true; + case type_kind::class_: + std::invoke(std::forward(f), as_class()); + return true; + case type_kind::constructor_: + std::invoke(std::forward(f), as_constructor()); + return true; + case type_kind::destructor_: + std::invoke(std::forward(f), as_destructor()); + return true; + case type_kind::enum_: + std::invoke(std::forward(f), as_enum()); + return true; + case type_kind::function_: + std::invoke(std::forward(f), as_function()); + return true; + case type_kind::member_: + std::invoke(std::forward(f), as_member()); + return true; + case type_kind::method_: + std::invoke(std::forward(f), as_method()); + return true; + case type_kind::nullptr_: + std::invoke(std::forward(f), as_nullptr()); + return true; + case type_kind::number_: + std::invoke(std::forward(f), as_number()); + return true; + case type_kind::pointer_: + std::invoke(std::forward(f), as_pointer()); + return true; + case type_kind::reference_: + std::invoke(std::forward(f), as_reference()); + return true; + case type_kind::void_: + std::invoke(std::forward(f), as_void()); + return true; + } + + META_HPP_ASSERT(false); + return false; + } + inline bool any_type::is_array() const noexcept { return is(); }