[libcxx-commits] [libcxx] 6157dbe - [libc++] Introduce __forward_as (#118168)

via libcxx-commits libcxx-commits at lists.llvm.org
Sat Dec 14 06:09:19 PST 2024


Author: Nikolas Klauser
Date: 2024-12-14T15:09:16+01:00
New Revision: 6157dbe48c21d900da1c7df11a8072a235f82001

URL: https://github.com/llvm/llvm-project/commit/6157dbe48c21d900da1c7df11a8072a235f82001
DIFF: https://github.com/llvm/llvm-project/commit/6157dbe48c21d900da1c7df11a8072a235f82001.diff

LOG: [libc++] Introduce __forward_as (#118168)

This allows forwarding an object as a specific type. This is usually
useful when using `deducing this` to avoid calling any functions in a
deriving class.

Added: 
    

Modified: 
    libcxx/include/__utility/forward_like.h
    libcxx/include/variant

Removed: 
    


################################################################################
diff  --git a/libcxx/include/__utility/forward_like.h b/libcxx/include/__utility/forward_like.h
index 0206ce23a56681..67bdf6d054ea8b 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 <class Self>
+//     void func(Self&& self) {
+//       // This will always call `do_something` of S instead of any class derived from S.
+//       std::__forward_as<Self, S>(self).do_something();
+//     }
+//   };
+template <class _Tp, class _As, class _Up>
+[[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 9006e7ca35b093..fd91bd293910f0 100644
--- a/libcxx/include/variant
+++ b/libcxx/include/variant
@@ -1311,14 +1311,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<remove_reference_t<_Self>, variant>>;
-    return std::visit(std::forward<_Visitor>(__visitor), (_VariantT)__self);
+    return std::visit(std::forward<_Visitor>(__visitor), std::__forward_as<_Self, variant>(__self));
   }
 
   template <class _Rp, class _Self, class _Visitor>
   _LIBCPP_HIDE_FROM_ABI constexpr _Rp visit(this _Self&& __self, _Visitor&& __visitor) {
-    using _VariantT = _OverrideRef<_Self&&, _CopyConst<remove_reference_t<_Self>, 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
 


        


More information about the libcxx-commits mailing list