From 19247ddcccce239a96bae2770448d877ea1d52cc Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Mon, 17 Jun 2024 23:18:01 +0700 Subject: [PATCH] new meta_poly_ptr method in META_HPP_ENABLE_POLY_INFO macro --- ROADMAP.md | 1 + .../manuals/meta_examples/ucast_example.cpp | 4 + develop/singles/headers/meta.hpp/meta_all.hpp | 6 ++ .../meta_issues/github_discussion_88.cpp | 74 +++++++++++++++++++ .../meta_types/poly_resolving2_tests.cpp | 2 + .../meta_types/poly_resolving_tests.cpp | 2 + headers/meta.hpp/meta_detail/base_info.hpp | 7 ++ 7 files changed, 96 insertions(+) create mode 100644 develop/untests/meta_issues/github_discussion_88.cpp diff --git a/ROADMAP.md b/ROADMAP.md index 8a5e91b..3777bcf 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -3,6 +3,7 @@ ## Backlog - add coverage information +- add an ucast function with a dynamic `to` argument ## Version 1.0 diff --git a/develop/manuals/meta_examples/ucast_example.cpp b/develop/manuals/meta_examples/ucast_example.cpp index 4fd482c..52aec9c 100644 --- a/develop/manuals/meta_examples/ucast_example.cpp +++ b/develop/manuals/meta_examples/ucast_example.cpp @@ -18,11 +18,15 @@ namespace // like `ucast` or `resolve_type(T&&)` struct A { + A() = default; + A(const A&) = default; virtual ~A() = default; META_HPP_ENABLE_POLY_INFO() }; struct B { + B() = default; + B(const B&) = default; virtual ~B() = default; META_HPP_ENABLE_POLY_INFO() }; diff --git a/develop/singles/headers/meta.hpp/meta_all.hpp b/develop/singles/headers/meta.hpp/meta_all.hpp index 8772f07..12f7971 100644 --- a/develop/singles/headers/meta.hpp/meta_all.hpp +++ b/develop/singles/headers/meta.hpp/meta_all.hpp @@ -4679,6 +4679,12 @@ public: \ META_HPP_ENABLE_BASE_INFO(__VA_ARGS__) \ public: \ META_HPP_DETAIL_IGNORE_OVERRIDE_WARNINGS_PUSH() \ + virtual ::meta_hpp::uvalue meta_poly_ptr() { \ + return ::meta_hpp::uvalue{this}; \ + } \ + virtual ::meta_hpp::uvalue meta_poly_ptr() const { \ + return ::meta_hpp::uvalue{this}; \ + } \ 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_by_type()}; \ diff --git a/develop/untests/meta_issues/github_discussion_88.cpp b/develop/untests/meta_issues/github_discussion_88.cpp new file mode 100644 index 0000000..fc1c9c7 --- /dev/null +++ b/develop/untests/meta_issues/github_discussion_88.cpp @@ -0,0 +1,74 @@ +/******************************************************************************* + * 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-2024, by Matvey Cherevko (blackmatov@gmail.com) + ******************************************************************************/ + +#include +#include + +namespace +{ + struct component { + component() = default; + component(const component&) = default; + virtual ~component() = default; + META_HPP_ENABLE_POLY_INFO() + }; + + struct position_component : component { + META_HPP_ENABLE_POLY_INFO() + public: + explicit position_component(int nx, int ny) : x{nx}, y{ny} {} + + int x{}; + int y{}; + }; +} + +TEST_CASE("meta/meta_discussion/88") { + namespace meta = meta_hpp; + + meta::class_() + .member_("x", &position_component::x, meta::member_policy::as_pointer) + .member_("y", &position_component::y, meta::member_policy::as_pointer); + + position_component position{21, 42}; + + std::vector components{&position}; + + for (component* c : components) { + // meta_poly_ptr returns a pointer of the most derived type (position_component* in this case) + meta::uvalue derived_instance_ptr = c->meta_poly_ptr(); + meta::any_type derived_instance_ptr_type = derived_instance_ptr.get_type(); + CHECK(derived_instance_ptr_type == meta::resolve_type()); + + // to get all members of the component we should extract a class type from the pointer (position_component) + meta::any_type derived_instance_type = derived_instance_ptr_type.as_pointer().get_data_type(); + CHECK(derived_instance_type == meta::resolve_type()); + + // for each member we can show our debug inspector (imgui input for example) + for (const meta::member& m : derived_instance_type.as_class().get_members()) { + // we registered members as pointers (member_policy::as_pointer), so the type of the member is a pointer + CHECK(m.get_type() == meta::resolve_type()); + CHECK(m.get_type().get_value_type() == meta::resolve_type()); + + // Note: + // We can register members without any policy then member::get will return copy of this member value, + // and to change this member we will have to call member::set function. + // But in this case we will change values in-place by a pointer + + meta::uvalue value = m.get(derived_instance_ptr); + CHECK(value.get_type() == meta::resolve_type()); + + int* raw_value = value.as(); + + // here we can show the value on the screen or change it + CHECK((*raw_value == 21 || *raw_value == 42)); + *raw_value = 84; + } + + CHECK(position.x == 84); + CHECK(position.y == 84); + } +} diff --git a/develop/untests/meta_types/poly_resolving2_tests.cpp b/develop/untests/meta_types/poly_resolving2_tests.cpp index a47c223..457b1e9 100644 --- a/develop/untests/meta_types/poly_resolving2_tests.cpp +++ b/develop/untests/meta_types/poly_resolving2_tests.cpp @@ -13,6 +13,8 @@ namespace struct derived : base {}; struct poly_base { + poly_base() = default; + poly_base(const poly_base&) = default; virtual ~poly_base() = default; META_HPP_ENABLE_POLY_INFO() }; diff --git a/develop/untests/meta_types/poly_resolving_tests.cpp b/develop/untests/meta_types/poly_resolving_tests.cpp index b36284b..46d969c 100644 --- a/develop/untests/meta_types/poly_resolving_tests.cpp +++ b/develop/untests/meta_types/poly_resolving_tests.cpp @@ -9,6 +9,8 @@ namespace { struct A { + A() = default; + A(const A&) = default; virtual ~A() = default; META_HPP_ENABLE_POLY_INFO() }; diff --git a/headers/meta.hpp/meta_detail/base_info.hpp b/headers/meta.hpp/meta_detail/base_info.hpp index e2a5c44..e6b2e6c 100644 --- a/headers/meta.hpp/meta_detail/base_info.hpp +++ b/headers/meta.hpp/meta_detail/base_info.hpp @@ -8,6 +8,7 @@ #include "../meta_base.hpp" #include "../meta_types.hpp" +#include "../meta_uvalue.hpp" #include "type_registry.hpp" @@ -45,6 +46,12 @@ public: \ META_HPP_ENABLE_BASE_INFO(__VA_ARGS__) \ public: \ META_HPP_DETAIL_IGNORE_OVERRIDE_WARNINGS_PUSH() \ + virtual ::meta_hpp::uvalue meta_poly_ptr() { \ + return ::meta_hpp::uvalue{this}; \ + } \ + virtual ::meta_hpp::uvalue meta_poly_ptr() const { \ + return ::meta_hpp::uvalue{this}; \ + } \ 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_by_type()}; \