diff --git a/ROADMAP.md b/ROADMAP.md index a4419f1..54b08e0 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -6,7 +6,6 @@ - non-linear search of methods/functions/... - 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 ucast manual ## Version 1.0 diff --git a/develop/singles/headers/meta.hpp/meta_all.hpp b/develop/singles/headers/meta.hpp/meta_all.hpp index 44b4ad4..c836cef 100644 --- a/develop/singles/headers/meta.hpp/meta_all.hpp +++ b/develop/singles/headers/meta.hpp/meta_all.hpp @@ -4245,11 +4245,19 @@ namespace meta_hpp::detail concept check_base_info_enabled // = requires { typename T::meta_base_info; }; + template < check_base_info_enabled T > + using get_meta_base_info = typename T::meta_base_info; + template < typename T > - concept check_poly_info_enabled // + concept poly_info_enabled // = requires(type_registry& r, const T& v) { - { v.get_most_derived_meta_poly_info(r) } -> std::convertible_to; + { v.meta_poly_info(r) } -> std::convertible_to; }; + + template < poly_info_enabled T > + poly_info get_meta_poly_info(type_registry& r, const T& v) { + return v.meta_poly_info(r); + } } #define META_HPP_ENABLE_BASE_INFO(...) \ @@ -4262,7 +4270,7 @@ private: META_HPP_ENABLE_BASE_INFO(__VA_ARGS__) \ public: \ META_HPP_DETAIL_IGNORE_OVERRIDE_WARNINGS_PUSH() \ - virtual ::meta_hpp::detail::poly_info get_most_derived_meta_poly_info(::meta_hpp::detail::type_registry& registry) const { \ + virtual ::meta_hpp::detail::poly_info meta_poly_info(::meta_hpp::detail::type_registry& registry) const { \ using self_type = std::remove_cvref_t; \ return ::meta_hpp::detail::poly_info{.ptr = this, .type = registry.resolve_class_type()}; \ } \ @@ -4363,10 +4371,23 @@ namespace meta_hpp template < typename T > // NOLINTNEXTLINE(*-missing-std-forward) - [[nodiscard]] auto resolve_type(T&&) { + [[nodiscard]] auto resolve_type(T&& from) { using namespace detail; + + using raw_type = std::remove_cvref_t; type_registry& registry = type_registry::instance(); - return registry.resolve_type>(); + + if constexpr ( std::is_class_v && std::is_polymorphic_v ) { + static_assert( + detail::poly_info_enabled, + "The class doesn't support polymorphic type resolving. " + "Use the META_HPP_ENABLE_POLY_INFO macro to fix it." + ); + return detail::get_meta_poly_info(registry, from).type; + } else { + (void)from; + return registry.resolve_type(); + } } template < typename... Ts > @@ -4384,29 +4405,6 @@ namespace meta_hpp } } -namespace meta_hpp -{ - template < typename T > - // NOLINTNEXTLINE(*-missing-std-forward) - [[nodiscard]] auto resolve_poly_type(T&& from) { - using namespace detail; - - using raw_type = std::remove_cvref_t; - type_registry& registry = type_registry::instance(); - - if constexpr ( std::is_class_v ) { - static_assert( - detail::check_poly_info_enabled, - "The class doesn't support polymorphic type resolving. Use the META_HPP_ENABLE_POLY_INFO macro to fix it." - ); - return from.get_most_derived_meta_poly_info(registry).type; - } else { - (void)from; - return registry.resolve_type(); - } - } -} - namespace meta_hpp { template < detail::class_kind Class, typename... Args > @@ -8309,7 +8307,7 @@ namespace meta_hpp::detail::class_type_data_impl }); if constexpr ( check_base_info_enabled ) { - using target_base_info = typename Target::meta_base_info; + using target_base_info = get_meta_base_info; target_base_info::for_each([&info]() { // add_upcast_info(info); }); @@ -8319,7 +8317,7 @@ namespace meta_hpp::detail::class_type_data_impl template < class_kind Class > void fill_upcast_info(new_base_info_t& info) { if constexpr ( check_base_info_enabled ) { - using class_base_info = typename Class::meta_base_info; + using class_base_info = get_meta_base_info; class_base_info::for_each([&info]() { info.base_classes.push_back(resolve_type()); add_upcast_info(info); @@ -9175,8 +9173,9 @@ namespace meta_hpp using to_data_type = std::remove_pointer_t; static_assert( - detail::check_poly_info_enabled, - "The type doesn't support ucasts. Use the META_HPP_ENABLE_POLY_INFO macro to fix it." + detail::poly_info_enabled, + "The type doesn't support ucasts. " + "Use the META_HPP_ENABLE_POLY_INFO macro to fix it." ); if ( from == nullptr ) { @@ -9187,7 +9186,7 @@ namespace meta_hpp return from; } else { detail::type_registry& registry{detail::type_registry::instance()}; - const detail::poly_info& meta_info{from->get_most_derived_meta_poly_info(registry)}; + const detail::poly_info& meta_info{detail::get_meta_poly_info(registry, *from)}; // NOLINTNEXTLINE(*-const-cast) void* most_derived_object_ptr = const_cast(meta_info.ptr); @@ -9209,8 +9208,9 @@ namespace meta_hpp using to_data_type = std::remove_reference_t; static_assert( - detail::check_poly_info_enabled, - "The type doesn't support ucasts. Use the META_HPP_ENABLE_POLY_INFO macro to fix it." + detail::poly_info_enabled, + "The type doesn't support ucasts. " + "Use the META_HPP_ENABLE_POLY_INFO macro to fix it." ); if ( to_data_type* ptr = ucast(std::addressof(from)) ) { diff --git a/develop/untests/meta_features/diamond_tests.cpp b/develop/untests/meta_features/diamond_tests.cpp index 44e63f1..08573e3 100644 --- a/develop/untests/meta_features/diamond_tests.cpp +++ b/develop/untests/meta_features/diamond_tests.cpp @@ -317,7 +317,7 @@ TEST_CASE("meta/meta_features/diamond") { } } - SUBCASE("resolve_poly_type") { + SUBCASE("resolve_type") { D d; A& ad = d; @@ -325,34 +325,24 @@ TEST_CASE("meta/meta_features/diamond") { C& cd = d; D& dd = d; - CHECK(meta::resolve_type(ad) == meta::resolve_type()); - CHECK(meta::resolve_type(bd) == meta::resolve_type()); - CHECK(meta::resolve_type(cd) == meta::resolve_type()); + CHECK(meta::resolve_type(A{}) == meta::resolve_type()); + CHECK(meta::resolve_type(B{}) == meta::resolve_type()); + CHECK(meta::resolve_type(C{}) == meta::resolve_type()); + CHECK(meta::resolve_type(D{}) == meta::resolve_type()); + + CHECK(meta::resolve_type(ad) == meta::resolve_type()); + CHECK(meta::resolve_type(bd) == meta::resolve_type()); + CHECK(meta::resolve_type(cd) == meta::resolve_type()); CHECK(meta::resolve_type(dd) == meta::resolve_type()); - CHECK(meta::resolve_type(std::as_const(ad)) == meta::resolve_type()); - CHECK(meta::resolve_type(std::as_const(bd)) == meta::resolve_type()); - CHECK(meta::resolve_type(std::as_const(cd)) == meta::resolve_type()); + CHECK(meta::resolve_type(std::move(ad)) == meta::resolve_type()); + CHECK(meta::resolve_type(std::move(bd)) == meta::resolve_type()); + CHECK(meta::resolve_type(std::move(cd)) == meta::resolve_type()); + CHECK(meta::resolve_type(std::move(dd)) == meta::resolve_type()); + + CHECK(meta::resolve_type(std::as_const(ad)) == meta::resolve_type()); + CHECK(meta::resolve_type(std::as_const(bd)) == meta::resolve_type()); + CHECK(meta::resolve_type(std::as_const(cd)) == meta::resolve_type()); CHECK(meta::resolve_type(std::as_const(dd)) == meta::resolve_type()); - - CHECK(meta::resolve_poly_type(A{}) == meta::resolve_type()); - CHECK(meta::resolve_poly_type(B{}) == meta::resolve_type()); - CHECK(meta::resolve_poly_type(C{}) == meta::resolve_type()); - CHECK(meta::resolve_poly_type(D{}) == meta::resolve_type()); - - CHECK(meta::resolve_poly_type(ad) == meta::resolve_type()); - CHECK(meta::resolve_poly_type(bd) == meta::resolve_type()); - CHECK(meta::resolve_poly_type(cd) == meta::resolve_type()); - CHECK(meta::resolve_poly_type(dd) == meta::resolve_type()); - - CHECK(meta::resolve_poly_type(std::move(ad)) == meta::resolve_type()); - CHECK(meta::resolve_poly_type(std::move(bd)) == meta::resolve_type()); - CHECK(meta::resolve_poly_type(std::move(cd)) == meta::resolve_type()); - CHECK(meta::resolve_poly_type(std::move(dd)) == meta::resolve_type()); - - CHECK(meta::resolve_poly_type(std::as_const(ad)) == meta::resolve_type()); - CHECK(meta::resolve_poly_type(std::as_const(bd)) == meta::resolve_type()); - CHECK(meta::resolve_poly_type(std::as_const(cd)) == meta::resolve_type()); - CHECK(meta::resolve_poly_type(std::as_const(dd)) == meta::resolve_type()); } } diff --git a/develop/untests/meta_types/poly_resolving2_tests.cpp b/develop/untests/meta_types/poly_resolving2_tests.cpp new file mode 100644 index 0000000..798b968 --- /dev/null +++ b/develop/untests/meta_types/poly_resolving2_tests.cpp @@ -0,0 +1,46 @@ +/******************************************************************************* + * This file is part of the "https://github.com/blackmatov/meta.hpp" + * For conditions of distribution and use, see copyright notice in LICENSE.md + * Copyright (C) 2021-2023, by Matvey Cherevko (blackmatov@gmail.com) + ******************************************************************************/ + +#include +#include + +namespace +{ + struct base {}; + struct derived : base {}; + + struct poly_base { + virtual ~poly_base() = default; + META_HPP_ENABLE_POLY_INFO() + }; + + struct poly_derived : poly_base { + META_HPP_ENABLE_POLY_INFO(poly_base) + }; +} + +TEST_CASE("meta/meta_types/poly_resolving2") { + namespace meta = meta_hpp; + + SUBCASE("simple-type") { + int v{}; + CHECK(meta::resolve_type(v) == meta::resolve_type()); + } + + SUBCASE("not-polymorphic-class") { + derived d; + base& b = d; + CHECK(meta::resolve_type(b) == meta::resolve_type()); + CHECK(meta::resolve_type(d) == meta::resolve_type()); + } + + SUBCASE("polymorphic-class") { + poly_derived d; + poly_base& b = d; + CHECK(meta::resolve_type(b) == meta::resolve_type()); + CHECK(meta::resolve_type(d) == meta::resolve_type()); + } +} diff --git a/develop/untests/meta_types/poly_resolving_tests.cpp b/develop/untests/meta_types/poly_resolving_tests.cpp index 3a4f93e..fa26792 100644 --- a/develop/untests/meta_types/poly_resolving_tests.cpp +++ b/develop/untests/meta_types/poly_resolving_tests.cpp @@ -14,61 +14,61 @@ namespace { }; struct B : A { - META_HPP_ENABLE_POLY_INFO() + META_HPP_ENABLE_POLY_INFO(A) }; } TEST_CASE("meta/meta_types/poly_resolving") { namespace meta = meta_hpp; - static_assert(std::is_same_v()))>); - static_assert(std::is_same_v()))>); + static_assert(std::is_same_v()))>); + static_assert(std::is_same_v()))>); - static_assert(std::is_same_v()))>); - static_assert(std::is_same_v()))>); + static_assert(std::is_same_v()))>); + static_assert(std::is_same_v()))>); - static_assert(std::is_same_v()))>); - static_assert(std::is_same_v()))>); - static_assert(std::is_same_v()))>); - static_assert(std::is_same_v()))>); - static_assert(std::is_same_v()))>); + static_assert(std::is_same_v()))>); + static_assert(std::is_same_v()))>); + static_assert(std::is_same_v()))>); + static_assert(std::is_same_v()))>); + static_assert(std::is_same_v()))>); - static_assert(std::is_same_v()))>); - static_assert(std::is_same_v()))>); - static_assert(std::is_same_v()))>); - static_assert(std::is_same_v()))>); - static_assert(std::is_same_v()))>); + static_assert(std::is_same_v()))>); + static_assert(std::is_same_v()))>); + static_assert(std::is_same_v()))>); + static_assert(std::is_same_v()))>); + static_assert(std::is_same_v()))>); { int i{42}; - CHECK(meta::resolve_poly_type(i) == meta::resolve_type()); - CHECK(meta::resolve_poly_type(std::move(i)) == meta::resolve_type()); - CHECK(meta::resolve_poly_type(std::as_const(i)) == meta::resolve_type()); - CHECK(meta::resolve_poly_type(std::move(std::as_const(i))) == meta::resolve_type()); + CHECK(meta::resolve_type(i) == meta::resolve_type()); + CHECK(meta::resolve_type(std::move(i)) == meta::resolve_type()); + CHECK(meta::resolve_type(std::as_const(i)) == meta::resolve_type()); + CHECK(meta::resolve_type(std::move(std::as_const(i))) == meta::resolve_type()); } { A a{}; - CHECK(meta::resolve_poly_type(a) == meta::resolve_type()); - CHECK(meta::resolve_poly_type(std::move(a)) == meta::resolve_type()); - CHECK(meta::resolve_poly_type(std::as_const(a)) == meta::resolve_type()); - CHECK(meta::resolve_poly_type(std::move(std::as_const(a))) == meta::resolve_type()); + CHECK(meta::resolve_type(a) == meta::resolve_type()); + CHECK(meta::resolve_type(std::move(a)) == meta::resolve_type()); + CHECK(meta::resolve_type(std::as_const(a)) == meta::resolve_type()); + CHECK(meta::resolve_type(std::move(std::as_const(a))) == meta::resolve_type()); } { B b{}; A& a{b}; - CHECK(meta::resolve_poly_type(a) == meta::resolve_type()); - CHECK(meta::resolve_poly_type(std::move(a)) == meta::resolve_type()); - CHECK(meta::resolve_poly_type(std::as_const(a)) == meta::resolve_type()); - CHECK(meta::resolve_poly_type(std::move(std::as_const(a))) == meta::resolve_type()); + CHECK(meta::resolve_type(a) == meta::resolve_type()); + CHECK(meta::resolve_type(std::move(a)) == meta::resolve_type()); + CHECK(meta::resolve_type(std::as_const(a)) == meta::resolve_type()); + CHECK(meta::resolve_type(std::move(std::as_const(a))) == meta::resolve_type()); - CHECK(meta::resolve_poly_type(b) == meta::resolve_type()); - CHECK(meta::resolve_poly_type(std::move(b)) == meta::resolve_type()); - CHECK(meta::resolve_poly_type(std::as_const(b)) == meta::resolve_type()); - CHECK(meta::resolve_poly_type(std::move(std::as_const(b))) == meta::resolve_type()); + CHECK(meta::resolve_type(b) == meta::resolve_type()); + CHECK(meta::resolve_type(std::move(b)) == meta::resolve_type()); + CHECK(meta::resolve_type(std::as_const(b)) == meta::resolve_type()); + CHECK(meta::resolve_type(std::move(std::as_const(b))) == meta::resolve_type()); } } diff --git a/headers/meta.hpp/meta_detail/base_info.hpp b/headers/meta.hpp/meta_detail/base_info.hpp index 6f19618..0d98fa7 100644 --- a/headers/meta.hpp/meta_detail/base_info.hpp +++ b/headers/meta.hpp/meta_detail/base_info.hpp @@ -22,11 +22,19 @@ namespace meta_hpp::detail concept check_base_info_enabled // = requires { typename T::meta_base_info; }; + template < check_base_info_enabled T > + using get_meta_base_info = typename T::meta_base_info; + template < typename T > - concept check_poly_info_enabled // + concept poly_info_enabled // = requires(type_registry& r, const T& v) { - { v.get_most_derived_meta_poly_info(r) } -> std::convertible_to; + { v.meta_poly_info(r) } -> std::convertible_to; }; + + template < poly_info_enabled T > + poly_info get_meta_poly_info(type_registry& r, const T& v) { + return v.meta_poly_info(r); + } } #define META_HPP_ENABLE_BASE_INFO(...) \ @@ -39,7 +47,7 @@ private: META_HPP_ENABLE_BASE_INFO(__VA_ARGS__) \ public: \ META_HPP_DETAIL_IGNORE_OVERRIDE_WARNINGS_PUSH() \ - virtual ::meta_hpp::detail::poly_info get_most_derived_meta_poly_info(::meta_hpp::detail::type_registry& registry) const { \ + virtual ::meta_hpp::detail::poly_info meta_poly_info(::meta_hpp::detail::type_registry& registry) const { \ using self_type = std::remove_cvref_t; \ return ::meta_hpp::detail::poly_info{.ptr = this, .type = registry.resolve_class_type()}; \ } \ diff --git a/headers/meta.hpp/meta_registry.hpp b/headers/meta.hpp/meta_registry.hpp index 533e3c6..66d1ca6 100644 --- a/headers/meta.hpp/meta_registry.hpp +++ b/headers/meta.hpp/meta_registry.hpp @@ -37,10 +37,23 @@ namespace meta_hpp template < typename T > // NOLINTNEXTLINE(*-missing-std-forward) - [[nodiscard]] auto resolve_type(T&&) { + [[nodiscard]] auto resolve_type(T&& from) { using namespace detail; + + using raw_type = std::remove_cvref_t; type_registry& registry = type_registry::instance(); - return registry.resolve_type>(); + + if constexpr ( std::is_class_v && std::is_polymorphic_v ) { + static_assert( + detail::poly_info_enabled, + "The class doesn't support polymorphic type resolving. " + "Use the META_HPP_ENABLE_POLY_INFO macro to fix it." + ); + return detail::get_meta_poly_info(registry, from).type; + } else { + (void)from; + return registry.resolve_type(); + } } template < typename... Ts > @@ -58,29 +71,6 @@ namespace meta_hpp } } -namespace meta_hpp -{ - template < typename T > - // NOLINTNEXTLINE(*-missing-std-forward) - [[nodiscard]] auto resolve_poly_type(T&& from) { - using namespace detail; - - using raw_type = std::remove_cvref_t; - type_registry& registry = type_registry::instance(); - - if constexpr ( std::is_class_v ) { - static_assert( - detail::check_poly_info_enabled, - "The class doesn't support polymorphic type resolving. Use the META_HPP_ENABLE_POLY_INFO macro to fix it." - ); - return from.get_most_derived_meta_poly_info(registry).type; - } else { - (void)from; - return registry.resolve_type(); - } - } -} - namespace meta_hpp { template < detail::class_kind Class, typename... Args > diff --git a/headers/meta.hpp/meta_types/class_type.hpp b/headers/meta.hpp/meta_types/class_type.hpp index 7d42506..2d3a77c 100644 --- a/headers/meta.hpp/meta_types/class_type.hpp +++ b/headers/meta.hpp/meta_types/class_type.hpp @@ -43,7 +43,7 @@ namespace meta_hpp::detail::class_type_data_impl }); if constexpr ( check_base_info_enabled ) { - using target_base_info = typename Target::meta_base_info; + using target_base_info = get_meta_base_info; target_base_info::for_each([&info]() { // add_upcast_info(info); }); @@ -53,7 +53,7 @@ namespace meta_hpp::detail::class_type_data_impl template < class_kind Class > void fill_upcast_info(new_base_info_t& info) { if constexpr ( check_base_info_enabled ) { - using class_base_info = typename Class::meta_base_info; + using class_base_info = get_meta_base_info; class_base_info::for_each([&info]() { info.base_classes.push_back(resolve_type()); add_upcast_info(info); diff --git a/headers/meta.hpp/meta_ucast/ucast.hpp b/headers/meta.hpp/meta_ucast/ucast.hpp index 813a71c..bd307ba 100644 --- a/headers/meta.hpp/meta_ucast/ucast.hpp +++ b/headers/meta.hpp/meta_ucast/ucast.hpp @@ -22,8 +22,9 @@ namespace meta_hpp using to_data_type = std::remove_pointer_t; static_assert( - detail::check_poly_info_enabled, - "The type doesn't support ucasts. Use the META_HPP_ENABLE_POLY_INFO macro to fix it." + detail::poly_info_enabled, + "The type doesn't support ucasts. " + "Use the META_HPP_ENABLE_POLY_INFO macro to fix it." ); if ( from == nullptr ) { @@ -34,7 +35,7 @@ namespace meta_hpp return from; } else { detail::type_registry& registry{detail::type_registry::instance()}; - const detail::poly_info& meta_info{from->get_most_derived_meta_poly_info(registry)}; + const detail::poly_info& meta_info{detail::get_meta_poly_info(registry, *from)}; // NOLINTNEXTLINE(*-const-cast) void* most_derived_object_ptr = const_cast(meta_info.ptr); @@ -56,8 +57,9 @@ namespace meta_hpp using to_data_type = std::remove_reference_t; static_assert( - detail::check_poly_info_enabled, - "The type doesn't support ucasts. Use the META_HPP_ENABLE_POLY_INFO macro to fix it." + detail::poly_info_enabled, + "The type doesn't support ucasts. " + "Use the META_HPP_ENABLE_POLY_INFO macro to fix it." ); if ( to_data_type* ptr = ucast(std::addressof(from)) ) {