diff --git a/develop/manuals/meta_manuals/class_manual.cpp b/develop/manuals/meta_manuals/class_manual.cpp index b46e605..897ab77 100644 --- a/develop/manuals/meta_manuals/class_manual.cpp +++ b/develop/manuals/meta_manuals/class_manual.cpp @@ -21,7 +21,7 @@ namespace }; class rectangle : public shape { - META_HPP_ENABLE_BASE_INFO(shape) + META_HPP_ENABLE_POLY_INFO(shape) public: explicit rectangle(int width, int height) : width_{width} diff --git a/develop/manuals/meta_manuals/uvalue_manual.cpp b/develop/manuals/meta_manuals/uvalue_manual.cpp index 0a6045f..0abf6c4 100644 --- a/develop/manuals/meta_manuals/uvalue_manual.cpp +++ b/develop/manuals/meta_manuals/uvalue_manual.cpp @@ -21,7 +21,7 @@ namespace }; class rectangle : public shape { - META_HPP_ENABLE_BASE_INFO(shape) + META_HPP_ENABLE_POLY_INFO(shape) public: explicit rectangle(int width, int height) : width_{width} diff --git a/develop/singles/headers/meta.hpp/meta_all.hpp b/develop/singles/headers/meta.hpp/meta_all.hpp index 71a18d7..4b8c188 100644 --- a/develop/singles/headers/meta.hpp/meta_all.hpp +++ b/develop/singles/headers/meta.hpp/meta_all.hpp @@ -2995,7 +2995,7 @@ namespace meta_hpp::detail vbases_t vbases{}; bool is_ambiguous{}; - upcast_func_list_t(const upcast_func_t& in_upcast); + explicit upcast_func_list_t(const upcast_func_t& in_upcast); upcast_func_list_t(upcasts_t in_upcasts, vbases_t in_vbases); [[nodiscard]] void* apply(void* ptr) const noexcept; @@ -8368,17 +8368,18 @@ namespace meta_hpp::detail deep_upcasts_t deep_upcasts; } new_base_data; - [[maybe_unused]] const auto add_base_class = [&new_base_data](std::in_place_type_t) { + [[maybe_unused]] const auto add_base_class = [&new_base_data]() { const class_type& base_class = resolve_type(); - const class_type_data& base_class_data = *type_access(base_class); + const class_type_data& base_data = *type_access(base_class); upcast_func_t self_to_base{std::in_place_type, std::in_place_type}; + upcast_func_list_t self_to_base_list{self_to_base}; new_base_data.base_classes.emplace_back(base_class); new_base_data.base_upcasts.emplace(base_class, self_to_base); - for ( const auto& [deep_class, base_to_deep] : base_class_data.deep_upcasts ) { - upcast_func_list_t self_to_deep = self_to_base + base_to_deep; + for ( const auto& [deep_class, base_to_deep] : base_data.deep_upcasts ) { + upcast_func_list_t self_to_deep = self_to_base_list + base_to_deep; const auto& [position, emplaced] = new_base_data.deep_upcasts.try_emplace( deep_class, std::move(self_to_deep) @@ -8389,9 +8390,9 @@ namespace meta_hpp::detail } } - new_base_data.deep_upcasts.emplace(base_class, upcast_func_list_t{self_to_base}); + new_base_data.deep_upcasts.emplace(base_class, std::move(self_to_base_list)); }; - (add_base_class(std::in_place_type>), ...); + (add_base_class.template operator()>(), ...); base_classes.swap(new_base_data.base_classes); base_upcasts.swap(new_base_data.base_upcasts); diff --git a/develop/untests/meta_issues/random_issue_5.cpp b/develop/untests/meta_issues/random_issue_5.cpp new file mode 100644 index 0000000..1cf8154 --- /dev/null +++ b/develop/untests/meta_issues/random_issue_5.cpp @@ -0,0 +1,61 @@ +/******************************************************************************* + * 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 A1 {}; + struct B1 : A1 { META_HPP_ENABLE_BASE_INFO(A1) }; + struct C1 : A1 { META_HPP_ENABLE_BASE_INFO(A1) }; + struct D1 : B1, C1 { META_HPP_ENABLE_BASE_INFO(B1, C1) }; + struct E1 : D1 { META_HPP_ENABLE_BASE_INFO(D1) }; + + // A1 < B1 + // < D1 < E1 + // A1 < C1 + + struct A2 {}; + struct B2 : virtual A2 { META_HPP_ENABLE_BASE_INFO(A2) }; + struct C2 : virtual A2 { META_HPP_ENABLE_BASE_INFO(A2) }; + struct D2 : B2, C2 { META_HPP_ENABLE_BASE_INFO(B2, C2) }; + struct E2 : D2 { META_HPP_ENABLE_BASE_INFO(D2) }; + + // A2 <= B2 + // < D2 < E2 + // A2 <= C2 +} + +TEST_CASE("meta/meta_issues/random/5") { + namespace meta = meta_hpp; + + { + CHECK(meta::is_invocable_with(+[](const A1&){}, B1{})); + CHECK(meta::is_invocable_with(+[](const A1&){}, C1{})); + CHECK(meta::is_invocable_with(+[](const B1&){}, D1{})); + CHECK(meta::is_invocable_with(+[](const C1&){}, D1{})); + CHECK(meta::is_invocable_with(+[](const B1&){}, E1{})); + CHECK(meta::is_invocable_with(+[](const C1&){}, E1{})); + CHECK(meta::is_invocable_with(+[](const D1&){}, E1{})); + + CHECK_FALSE(meta::is_invocable_with(+[](const A1&){}, D1{})); + CHECK_FALSE(meta::is_invocable_with(+[](const A1&){}, E1{})); + } + + { + CHECK(meta::is_invocable_with(+[](const A2&){}, B2{})); + CHECK(meta::is_invocable_with(+[](const A2&){}, C2{})); + CHECK(meta::is_invocable_with(+[](const B2&){}, D2{})); + CHECK(meta::is_invocable_with(+[](const C2&){}, D2{})); + CHECK(meta::is_invocable_with(+[](const B2&){}, E2{})); + CHECK(meta::is_invocable_with(+[](const C2&){}, E2{})); + CHECK(meta::is_invocable_with(+[](const D2&){}, E2{})); + + CHECK(meta::is_invocable_with(+[](const A2&){}, D2{})); + CHECK(meta::is_invocable_with(+[](const A2&){}, E2{})); + } +} diff --git a/headers/meta.hpp/meta_types.hpp b/headers/meta.hpp/meta_types.hpp index fa10ef7..49523cf 100644 --- a/headers/meta.hpp/meta_types.hpp +++ b/headers/meta.hpp/meta_types.hpp @@ -534,7 +534,7 @@ namespace meta_hpp::detail vbases_t vbases{}; bool is_ambiguous{}; - upcast_func_list_t(const upcast_func_t& in_upcast); + explicit upcast_func_list_t(const upcast_func_t& in_upcast); upcast_func_list_t(upcasts_t in_upcasts, vbases_t in_vbases); [[nodiscard]] void* apply(void* ptr) const noexcept; diff --git a/headers/meta.hpp/meta_types/class_type.hpp b/headers/meta.hpp/meta_types/class_type.hpp index 891d390..e141435 100644 --- a/headers/meta.hpp/meta_types/class_type.hpp +++ b/headers/meta.hpp/meta_types/class_type.hpp @@ -37,17 +37,18 @@ namespace meta_hpp::detail deep_upcasts_t deep_upcasts; } new_base_data; - [[maybe_unused]] const auto add_base_class = [&new_base_data](std::in_place_type_t) { + [[maybe_unused]] const auto add_base_class = [&new_base_data]() { const class_type& base_class = resolve_type(); - const class_type_data& base_class_data = *type_access(base_class); + const class_type_data& base_data = *type_access(base_class); upcast_func_t self_to_base{std::in_place_type, std::in_place_type}; + upcast_func_list_t self_to_base_list{self_to_base}; new_base_data.base_classes.emplace_back(base_class); new_base_data.base_upcasts.emplace(base_class, self_to_base); - for ( const auto& [deep_class, base_to_deep] : base_class_data.deep_upcasts ) { - upcast_func_list_t self_to_deep = self_to_base + base_to_deep; + for ( const auto& [deep_class, base_to_deep] : base_data.deep_upcasts ) { + upcast_func_list_t self_to_deep = self_to_base_list + base_to_deep; const auto& [position, emplaced] = new_base_data.deep_upcasts.try_emplace( deep_class, std::move(self_to_deep) @@ -58,9 +59,9 @@ namespace meta_hpp::detail } } - new_base_data.deep_upcasts.emplace(base_class, upcast_func_list_t{self_to_base}); + new_base_data.deep_upcasts.emplace(base_class, std::move(self_to_base_list)); }; - (add_base_class(std::in_place_type>), ...); + (add_base_class.template operator()>(), ...); base_classes.swap(new_base_data.base_classes); base_upcasts.swap(new_base_data.base_upcasts);