From 0e85573c36f0efb98d94be2b49c7aa5e58b4d38b Mon Sep 17 00:00:00 2001 From: Nikolas Klauser Date: Sat, 30 Nov 2024 12:31:53 +0100 Subject: [PATCH] [libc++] Introduce __forward_as --- libcxx/include/__utility/forward_like.h | 17 +++++++++++++++++ libcxx/include/variant | 6 ++---- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/libcxx/include/__utility/forward_like.h b/libcxx/include/__utility/forward_like.h index 0206ce23a5668..67bdf6d054ea8 100644 --- a/libcxx/include/__utility/forward_like.h +++ b/libcxx/include/__utility/forward_like.h @@ -12,6 +12,7 @@ #include <__config> #include <__type_traits/conditional.h> +#include <__type_traits/is_base_of.h> #include <__type_traits/is_const.h> #include <__type_traits/is_reference.h> #include <__type_traits/remove_reference.h> @@ -39,6 +40,22 @@ forward_like(_LIBCPP_LIFETIMEBOUND _Up&& __ux) noexcept -> _ForwardLike<_Tp, _Up return static_cast<_ForwardLike<_Tp, _Up>>(__ux); } +// This function is used for `deducing this` cases where you want to make sure the operation is performed on the class +// itself and not on a derived class. For example +// struct S { +// template +// void func(Self&& self) { +// // This will always call `do_something` of S instead of any class derived from S. +// std::__forward_as(self).do_something(); +// } +// }; +template +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _ForwardLike<_Tp, _As> +__forward_as(_LIBCPP_LIFETIMEBOUND _Up&& __val) noexcept { + static_assert(is_base_of_v<_As, remove_reference_t<_Up>>); + return static_cast<_ForwardLike<_Tp, _As>>(__val); +} + #endif // _LIBCPP_STD_VER >= 23 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/variant b/libcxx/include/variant index f604527cd2256..7e44ec54141c2 100644 --- a/libcxx/include/variant +++ b/libcxx/include/variant @@ -1309,14 +1309,12 @@ public: template <__variant_visit_barrier_tag = __variant_visit_barrier_tag{}, class _Self, class _Visitor> _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) visit(this _Self&& __self, _Visitor&& __visitor) { - using _VariantT = _OverrideRef<_Self&&, _CopyConst, variant>>; - return std::visit(std::forward<_Visitor>(__visitor), (_VariantT)__self); + return std::visit(std::forward<_Visitor>(__visitor), std::__forward_as<_Self, variant>(__self)); } template _LIBCPP_HIDE_FROM_ABI constexpr _Rp visit(this _Self&& __self, _Visitor&& __visitor) { - using _VariantT = _OverrideRef<_Self&&, _CopyConst, variant>>; - return std::visit<_Rp>(std::forward<_Visitor>(__visitor), (_VariantT)__self); + return std::visit<_Rp>(std::forward<_Visitor>(__visitor), std::__forward_as<_Self, variant>(__self)); } # endif