diff --git a/include/proxy/v4/proxy.h b/include/proxy/v4/proxy.h index 2b26da3..80f4819 100644 --- a/include/proxy/v4/proxy.h +++ b/include/proxy/v4/proxy.h @@ -232,10 +232,19 @@ template struct destructibility_traits : applicable_traits {}; +template +using proxy_accessor = add_qualifier_t< + std::conditional_t, proxy_indirect_accessor>, Q>; +template +add_qualifier_t, Q> + as_proxy(add_qualifier_t, Q> p); + struct proxy_helper { template struct resetting_guard { explicit resetting_guard(proxy& p) noexcept : p_(p) {} + explicit resetting_guard(proxy_indirect_accessor& p) noexcept + : p_(as_proxy(p)) {} ~resetting_guard() noexcept(std::is_nothrow_destructible_v

) { std::destroy_at(std::addressof(get_ptr(p_))); p_.meta_.reset(); @@ -245,10 +254,14 @@ struct proxy_helper { proxy& p_; }; - template - static const auto& get_meta(const proxy& p) noexcept { + template + static const M& get_meta(const proxy& p) noexcept { assert(p.has_value()); - return *p.meta_.operator->(); + return static_cast(*p.meta_.operator->()); + } + template + static const M& get_meta(const proxy_indirect_accessor& p) noexcept { + return get_meta(as_proxy(p)); } template static add_qualifier_t get_ptr(add_qualifier_t, Q> p) { @@ -282,64 +295,13 @@ concept invocable_dispatch = (Q != qualifier_type::rv || (NE && std::is_nothrow_destructible_v

) || (!NE && std::is_destructible_v

)); -template -R invoke_dispatch_impl(Args&&... args) { - if constexpr (std::is_void_v) { - D()(std::forward(args)...); - } else { - return D()(std::forward(args)...); - } -} -template -decltype(auto) get_operand(P&& ptr) { - if constexpr (IsDirect) { - return std::forward

(ptr); - } else { - if constexpr (std::is_constructible_v) { - assert(ptr); - } - return *std::forward

(ptr); - } -} struct internal_dispatch {}; -template -R invoke_dispatch(add_qualifier_t, Q> self, - Args... args) noexcept(NE) { - if constexpr (Q == qualifier_type::rv) { - if constexpr (std::is_base_of_v && - is_bitwise_trivially_relocatable_v

) { - static_assert(IsDirect); - return D{}(std::in_place_type

, - std::forward, Q>>(self), - std::forward(args)...); - } else { - proxy_helper::resetting_guard guard{self}; - return invoke_dispatch_impl( - get_operand( - proxy_helper::get_ptr(std::move(self))), - std::forward(args)...); - } - } else { - return invoke_dispatch_impl( - get_operand(proxy_helper::get_ptr( - std::forward, Q>>(self))), - std::forward(args)...); - } -} template struct overload_traits : inapplicable_traits {}; template struct overload_traits_impl : applicable_traits { using return_type = R; - template - using dispatcher_type = R (*)(add_qualifier_t, Q>, - Args...) noexcept(NE); - - template - static constexpr auto dispatcher = - &invoke_dispatch; template static constexpr bool applicable_ptr = @@ -381,6 +343,8 @@ struct overload_traits template struct overload_traits : overload_traits_impl {}; +template +using ret_t = typename overload_traits::return_type; template struct overload_substitution_traits : inapplicable_traits { @@ -406,16 +370,23 @@ consteval void diagnose_proxiable_required_convention_not_implemented() { "not proxiable due to a required convention not implemented"); } -template -struct invocation_meta { - invocation_meta() = default; - template - constexpr explicit invocation_meta(std::in_place_type_t

) - : dispatcher(overload_traits::template dispatcher) { +template +struct conv_meta; +#define PROD_DEF_CONV_META(oq, pq, ne, ...) \ + template \ + struct conv_meta { \ + conv_meta() = default; \ + template \ + constexpr explicit conv_meta(std::in_place_type_t

) \ + : invoke([](ProP pq self, Args... args) ne -> R { \ + return reinterpret_invoke(static_cast(self), \ + std::forward(args)...); \ + }) {} \ + \ + R (*invoke)(ProP pq, Args...) ne; \ } - - typename overload_traits::template dispatcher_type dispatcher; -}; +PRO4D_DEF_OVERLOAD_SPECIALIZATIONS(PROD_DEF_CONV_META) +#undef PROD_DEF_CONV_META template struct PRO4D_ENFORCE_EBO composite_meta : Ms... { @@ -472,9 +443,9 @@ template struct conv_traits_impl { static_assert((overload_traits>::applicable && ...)); - using meta = - composite_meta>...>; + using meta = composite_meta, proxy_indirect_accessor>, + typename C::dispatch_type, substituted_overload_t>...>; template using accessor = accessor_t struct lifetime_meta_traits : std::type_identity {}; template struct lifetime_meta_traits - : std::type_identity> {}; + : std::type_identity, D, ONE>> {}; template struct lifetime_meta_traits - : std::type_identity> {}; + : std::type_identity, D, OE>> {}; template using lifetime_meta_t = typename lifetime_meta_traits::type; @@ -799,18 +770,17 @@ struct meta_ptr_indirect_impl { template struct meta_ptr_direct_impl : private M { using M::M; - bool has_value() const noexcept { return this->DM::dispatcher != nullptr; } - void reset() noexcept { this->DM::dispatcher = nullptr; } + bool has_value() const noexcept { return this->DM::invoke != nullptr; } + void reset() noexcept { this->DM::invoke = nullptr; } const M* operator->() const noexcept { return this; } }; template struct meta_ptr_traits_impl : std::type_identity> {}; -template -struct meta_ptr_traits_impl< - composite_meta, Ms...>> - : std::type_identity, Ms...>, - invocation_meta>> {}; +template +struct meta_ptr_traits_impl, Ms...>> + : std::type_identity< + meta_ptr_direct_impl, Ms...>, + conv_meta>> {}; template struct meta_ptr_traits : std::type_identity> {}; template @@ -846,12 +816,10 @@ class inplace_ptr { T value_; }; -template -decltype(auto) invoke_impl(P&& p, Args&&... args) { - auto dispatcher = - proxy_helper::get_meta(p) - .template invocation_meta::dispatcher; - return dispatcher(std::forward

(p), std::forward(args)...); +template +ret_t invoke_impl(P&& p, Args&&... args) { + return proxy_helper::get_meta, D, O>>(p) + .invoke(std::forward

(p), std::forward(args)...); } template add_qualifier_t, Q> @@ -861,6 +829,49 @@ add_qualifier_t, Q> add_qualifier_ptr_t>, Q>>( std::addressof(p))); } +template +operand_t get_operand(proxy_accessor p) { + if constexpr (IsDirect) { + return proxy_helper::get_ptr( + std::forward>(p)); + } else { + add_qualifier_t ptr = proxy_helper::get_ptr( + as_proxy(std::forward>(p))); + if constexpr (std::is_constructible_v) { + assert(ptr); + } + return *std::forward>(ptr); + } +} +template +R invoke_dispatch(Args&&... args) { + if constexpr (std::is_void_v) { + D()(std::forward(args)...); + } else { + return D()(std::forward(args)...); + } +} +template +R reinterpret_invoke(proxy_accessor self, Args&&... args) { + if constexpr (Q == qualifier_type::rv) { + if constexpr (std::is_base_of_v && + is_bitwise_trivially_relocatable_v

) { + return D()(std::in_place_type

, std::move(self), + std::forward(args)...); + } else { + proxy_helper::resetting_guard guard{self}; + return invoke_dispatch( + get_operand(std::move(self)), + std::forward(args)...); + } + } else { + return invoke_dispatch( + get_operand( + std::forward>(self)), + std::forward(args)...); + } +} } // namespace details @@ -878,38 +889,54 @@ class proxy_indirect_accessor public: template - friend auto invoke(proxy_indirect_accessor& p, Args&&... args) -> - typename details::overload_traits::return_type { - return details::invoke_impl( - details::as_proxy(p), - std::forward(args)...); + friend details::ret_t invoke(proxy_indirect_accessor& p, Args&&... args) { + return details::invoke_impl(p, std::forward(args)...); } template - friend auto invoke(const proxy_indirect_accessor& p, Args&&... args) -> - typename details::overload_traits::return_type { - return details::invoke_impl( - details::as_proxy(p), - std::forward(args)...); + friend details::ret_t invoke(const proxy_indirect_accessor& p, + Args&&... args) { + return details::invoke_impl(p, std::forward(args)...); } template - friend auto invoke(proxy_indirect_accessor&& p, Args&&... args) -> - typename details::overload_traits::return_type { - return details::invoke_impl( - details::as_proxy(std::move(p)), - std::forward(args)...); + friend details::ret_t invoke(proxy_indirect_accessor&& p, Args&&... args) { + return details::invoke_impl(std::move(p), + std::forward(args)...); } template - friend auto invoke(const proxy_indirect_accessor&& p, Args&&... args) -> - typename details::overload_traits::return_type { - return details::invoke_impl( - details::as_proxy(std::move(p)), - std::forward(args)...); + friend details::ret_t invoke(const proxy_indirect_accessor&& p, + Args&&... args) { + return details::invoke_impl(std::move(p), + std::forward(args)...); + } + template + friend R reinterpret_invoke(proxy_indirect_accessor& p, Args&&... args) { + return details::reinterpret_invoke(p, std::forward(args)...); + } + template + friend R reinterpret_invoke(const proxy_indirect_accessor& p, + Args&&... args) { + return details::reinterpret_invoke( + p, std::forward(args)...); + } + template + friend R reinterpret_invoke(proxy_indirect_accessor&& p, Args&&... args) { + return details::reinterpret_invoke(std::move(p), + std::forward(args)...); + } + template + friend R reinterpret_invoke(const proxy_indirect_accessor&& p, + Args&&... args) { + return details::reinterpret_invoke( + std::move(p), std::forward(args)...); } template friend const R& reflect(const proxy_indirect_accessor& p) noexcept { - return static_cast&>( - details::proxy_helper::get_meta( - details::as_proxy(p))) + return details::proxy_helper::get_meta>( + p) .reflector; } }; @@ -1108,31 +1135,49 @@ class proxy : public details::facade_traits::direct_accessor, return !lhs.has_value(); } template - friend auto invoke(proxy& p, Args&&... args) -> - typename details::overload_traits::return_type { - return details::invoke_impl(p, std::forward(args)...); + friend details::ret_t invoke(proxy& p, Args&&... args) { + return details::invoke_impl(p, std::forward(args)...); } template - friend auto invoke(const proxy& p, Args&&... args) -> - typename details::overload_traits::return_type { - return details::invoke_impl(p, std::forward(args)...); + friend details::ret_t invoke(const proxy& p, Args&&... args) { + return details::invoke_impl(p, std::forward(args)...); } template - friend auto invoke(proxy&& p, Args&&... args) -> - typename details::overload_traits::return_type { - return details::invoke_impl(std::move(p), - std::forward(args)...); + friend details::ret_t invoke(proxy&& p, Args&&... args) { + return details::invoke_impl(std::move(p), + std::forward(args)...); } template - friend auto invoke(const proxy&& p, Args&&... args) -> - typename details::overload_traits::return_type { - return details::invoke_impl(std::move(p), - std::forward(args)...); + friend details::ret_t invoke(const proxy&& p, Args&&... args) { + return details::invoke_impl(std::move(p), + std::forward(args)...); + } + template + friend R reinterpret_invoke(proxy& p, Args&&... args) { + return details::reinterpret_invoke(p, std::forward(args)...); + } + template + friend R reinterpret_invoke(const proxy& p, Args&&... args) { + return details::reinterpret_invoke( + p, std::forward(args)...); + } + template + friend R reinterpret_invoke(proxy&& p, Args&&... args) { + return details::reinterpret_invoke(std::move(p), + std::forward(args)...); + } + template + friend R reinterpret_invoke(const proxy&& p, Args&&... args) { + return details::reinterpret_invoke( + std::move(p), std::forward(args)...); } template friend const R& reflect(const proxy& p) noexcept { - return static_cast&>( - details::proxy_helper::get_meta(p)) + return details::proxy_helper::get_meta>(p) .reflector; } @@ -1216,51 +1261,43 @@ class proxy : public details::facade_traits::direct_accessor, }; template -[[deprecated("Use unqualified invoke instead")]] auto - proxy_invoke(proxy_indirect_accessor& p, Args&&... args) -> - typename details::overload_traits::return_type { +[[deprecated("Use unqualified invoke instead")]] details::ret_t + proxy_invoke(proxy_indirect_accessor& p, Args&&... args) { return invoke(p, std::forward(args)...); } template -[[deprecated("Use unqualified invoke instead")]] auto - proxy_invoke(const proxy_indirect_accessor& p, Args&&... args) -> - typename details::overload_traits::return_type { +[[deprecated("Use unqualified invoke instead")]] details::ret_t + proxy_invoke(const proxy_indirect_accessor& p, Args&&... args) { return invoke(p, std::forward(args)...); } template -[[deprecated("Use unqualified invoke instead")]] auto - proxy_invoke(proxy_indirect_accessor&& p, Args&&... args) -> - typename details::overload_traits::return_type { +[[deprecated("Use unqualified invoke instead")]] details::ret_t + proxy_invoke(proxy_indirect_accessor&& p, Args&&... args) { return invoke(std::move(p), std::forward(args)...); } template -[[deprecated("Use unqualified invoke instead")]] auto - proxy_invoke(const proxy_indirect_accessor&& p, Args&&... args) -> - typename details::overload_traits::return_type { +[[deprecated("Use unqualified invoke instead")]] details::ret_t + proxy_invoke(const proxy_indirect_accessor&& p, Args&&... args) { return invoke(std::move(p), std::forward(args)...); } template -[[deprecated("Use unqualified invoke instead")]] auto - proxy_invoke(proxy& p, Args&&... args) -> - typename details::overload_traits::return_type { +[[deprecated("Use unqualified invoke instead")]] details::ret_t + proxy_invoke(proxy& p, Args&&... args) { return invoke(p, std::forward(args)...); } template -[[deprecated("Use unqualified invoke instead")]] auto - proxy_invoke(const proxy& p, Args&&... args) -> - typename details::overload_traits::return_type { +[[deprecated("Use unqualified invoke instead")]] details::ret_t + proxy_invoke(const proxy& p, Args&&... args) { return invoke(p, std::forward(args)...); } template -[[deprecated("Use unqualified invoke instead")]] auto - proxy_invoke(proxy&& p, Args&&... args) -> - typename details::overload_traits::return_type { +[[deprecated("Use unqualified invoke instead")]] details::ret_t + proxy_invoke(proxy&& p, Args&&... args) { return invoke(std::move(p), std::forward(args)...); } template -[[deprecated("Use unqualified invoke instead")]] auto - proxy_invoke(const proxy&& p, Args&&... args) -> - typename details::overload_traits::return_type { +[[deprecated("Use unqualified invoke instead")]] details::ret_t + proxy_invoke(const proxy&& p, Args&&... args) { return invoke(std::move(p), std::forward(args)...); } @@ -1392,8 +1429,7 @@ using instantiated_conv_t = template using observer_substitution_overload = - proxy_view::return_type::facade_type>() - const noexcept; + proxy_view::facade_type>() const noexcept; template using observer_substitution_conv = instantiated_conv_t< true, substitution_dispatch,