From 41855b3ed75d52fcfeaaa6c017a1155ce58c30fe Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Thu, 5 Sep 2024 07:18:15 +0700 Subject: [PATCH] fix uvalue deref traits ref: https://github.com/BlackMATov/meta.hpp/issues/100 --- .../untests/meta_utilities/value_tests.cpp | 18 +++++++++++++ .../meta_detail/value_traits/deref_traits.hpp | 27 +++++++++++++++---- 2 files changed, 40 insertions(+), 5 deletions(-) diff --git a/develop/untests/meta_utilities/value_tests.cpp b/develop/untests/meta_utilities/value_tests.cpp index 49adcc4..673db51 100644 --- a/develop/untests/meta_utilities/value_tests.cpp +++ b/develop/untests/meta_utilities/value_tests.cpp @@ -107,11 +107,17 @@ namespace bool operator==(const ivec2_big& l, const ivec2_big& r) noexcept { return l.x == r.x && l.y == r.y; } + + struct deref_custom_class { + int operator*() const { return 42; } + }; } META_HPP_DECLARE_COPY_TRAITS_FOR(ivec2) META_HPP_DECLARE_COPY_TRAITS_FOR(ivec2_big) +META_HPP_DECLARE_DEREF_TRAITS_FOR(deref_custom_class) + TEST_CASE("meta/meta_utilities/value/_") { namespace meta = meta_hpp; @@ -645,6 +651,18 @@ TEST_CASE("meta/meta_utilities/value") { meta::uvalue v{std::make_unique(42)}; CHECK((*v).as() == 42); } + { + CHECK(meta::uvalue{std::make_shared>>()}.has_deref_op()); + CHECK_FALSE(meta::uvalue{std::make_shared>>()}.has_deref_op()); + } + { + const meta::uvalue v{deref_custom_class{}}; + CHECK(v.has_deref_op()); + + const meta::uvalue u = *v; + CHECK(u.get_type() == meta::resolve_type()); + CHECK(u.as() == 42); + } } SUBCASE("less/equal") { diff --git a/headers/meta.hpp/meta_detail/value_traits/deref_traits.hpp b/headers/meta.hpp/meta_detail/value_traits/deref_traits.hpp index a0aef7c..19a0d71 100644 --- a/headers/meta.hpp/meta_detail/value_traits/deref_traits.hpp +++ b/headers/meta.hpp/meta_detail/value_traits/deref_traits.hpp @@ -9,6 +9,8 @@ #include "../../meta_base.hpp" #include "../../meta_uvalue.hpp" +#include "copy_traits.hpp" + namespace meta_hpp::detail { template < typename T > @@ -22,7 +24,7 @@ namespace meta_hpp::detail namespace meta_hpp::detail { template < typename T > - requires std::is_copy_constructible_v + requires has_copy_traits struct deref_traits { uvalue operator()(T* v) const { return v != nullptr ? uvalue{*v} : uvalue{}; @@ -30,18 +32,33 @@ namespace meta_hpp::detail }; template < typename T > - requires std::is_copy_constructible_v + requires has_copy_traits struct deref_traits> { - uvalue operator()(const std::shared_ptr& v) const { + using value_t = std::shared_ptr; + + uvalue operator()(const value_t& v) const { return v != nullptr ? uvalue{*v} : uvalue{}; } }; template < typename T, typename Deleter > - requires std::is_copy_constructible_v + requires has_copy_traits struct deref_traits> { - uvalue operator()(const std::unique_ptr& v) const { + using value_t = std::unique_ptr; + + uvalue operator()(const value_t& v) const { return v != nullptr ? uvalue{*v} : uvalue{}; } }; } + +#define META_HPP_DECLARE_DEREF_TRAITS_FOR(T) \ + namespace meta_hpp::detail \ + { \ + template <> \ + struct deref_traits { \ + uvalue operator()(const T& v) const { \ + return uvalue{*v}; \ + } \ + }; \ + }