diff --git a/include/proxy/v4/detail/skills.h b/include/proxy/v4/detail/skills.h index adee855..c927bf3 100644 --- a/include/proxy/v4/detail/skills.h +++ b/include/proxy/v4/detail/skills.h @@ -163,7 +163,7 @@ struct proxy_cast_accessor_impl { .is_ref = true, .is_const = std::is_const_v, .result_ptr = &result}; - invoke(static_cast(self), ctx); + invoke_cast(static_cast(self), ctx); if (result == nullptr) [[unlikely]] { PRO4D_THROW(bad_proxy_cast{}); } @@ -174,7 +174,7 @@ struct proxy_cast_accessor_impl { .is_ref = false, .is_const = false, .result_ptr = &result}; - invoke(static_cast(self), ctx); + invoke_cast(static_cast(self), ctx); if (!result.has_value()) [[unlikely]] { PRO4D_THROW(bad_proxy_cast{}); } @@ -190,9 +190,32 @@ struct proxy_cast_accessor_impl { .is_ref = true, .is_const = std::is_const_v, .result_ptr = &result}; - invoke(*self, ctx); + invoke_cast(*self, ctx); return static_cast(result); } + +private: + template + static void invoke_cast(Self self, const proxy_cast_context& cast_ctx) { + if constexpr (specialization_of, proxy>) { + using F = std::remove_cvref_t::facade_type; + constexpr bool is_rv = + overload_traits::this_qualifier == qualifier_type::rv; + if (proxy_typeid(self) == *cast_ctx.type_ptr) [[likely]] { + erased_context ctx{proxy_helper::get_ptr(self)}; + if constexpr (is_rv) { + proxy_helper::meta_resetting_guard guard{self}; + invoke>(ctx, cast_ctx); + } else { + invoke>(ctx, cast_ctx); + } + } else if constexpr (is_rv) { + self.reset(); + } + } else { + invoke(static_cast(self), cast_ctx); + } + } }; #define PRO4D_DEF_PROXY_CAST_ACCESSOR(oq, pq, ne, ...) \ @@ -242,6 +265,17 @@ struct proxy_typeid_reflector { const std::type_info* info; }; + +struct direct_rtti_reflector : proxy_typeid_reflector { + using proxy_typeid_reflector::proxy_typeid_reflector; + + template + struct PRO4D_ENFORCE_EBO accessor + : proxy_typeid_reflector::accessor, + proxy_cast_dispatch::accessor< + Self, proxy_cast_dispatch, void(proxy_cast_context) &, + void(proxy_cast_context) const&, void(proxy_cast_context) &&> {}; +}; #endif // __cpp_rtti >= 199711L } // namespace detail @@ -270,11 +304,7 @@ using indirect_rtti = FB::template add_indirect_convention< template using direct_rtti = - FB::template add_direct_convention:: - template add_direct_reflection; + FB::template add_direct_reflection; template using rtti = indirect_rtti;