Skip to content

Commit 6157dbe

Browse files
authored
[libc++] Introduce __forward_as (llvm#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.
1 parent 10f23d1 commit 6157dbe

File tree

2 files changed

+19
-4
lines changed

2 files changed

+19
-4
lines changed

libcxx/include/__utility/forward_like.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
#include <__config>
1414
#include <__type_traits/conditional.h>
15+
#include <__type_traits/is_base_of.h>
1516
#include <__type_traits/is_const.h>
1617
#include <__type_traits/is_reference.h>
1718
#include <__type_traits/remove_reference.h>
@@ -39,6 +40,22 @@ forward_like(_LIBCPP_LIFETIMEBOUND _Up&& __ux) noexcept -> _ForwardLike<_Tp, _Up
3940
return static_cast<_ForwardLike<_Tp, _Up>>(__ux);
4041
}
4142

43+
// This function is used for `deducing this` cases where you want to make sure the operation is performed on the class
44+
// itself and not on a derived class. For example
45+
// struct S {
46+
// template <class Self>
47+
// void func(Self&& self) {
48+
// // This will always call `do_something` of S instead of any class derived from S.
49+
// std::__forward_as<Self, S>(self).do_something();
50+
// }
51+
// };
52+
template <class _Tp, class _As, class _Up>
53+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _ForwardLike<_Tp, _As>
54+
__forward_as(_LIBCPP_LIFETIMEBOUND _Up&& __val) noexcept {
55+
static_assert(is_base_of_v<_As, remove_reference_t<_Up>>);
56+
return static_cast<_ForwardLike<_Tp, _As>>(__val);
57+
}
58+
4259
#endif // _LIBCPP_STD_VER >= 23
4360

4461
_LIBCPP_END_NAMESPACE_STD

libcxx/include/variant

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1311,14 +1311,12 @@ public:
13111311

13121312
template <__variant_visit_barrier_tag = __variant_visit_barrier_tag{}, class _Self, class _Visitor>
13131313
_LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) visit(this _Self&& __self, _Visitor&& __visitor) {
1314-
using _VariantT = _OverrideRef<_Self&&, _CopyConst<remove_reference_t<_Self>, variant>>;
1315-
return std::visit(std::forward<_Visitor>(__visitor), (_VariantT)__self);
1314+
return std::visit(std::forward<_Visitor>(__visitor), std::__forward_as<_Self, variant>(__self));
13161315
}
13171316

13181317
template <class _Rp, class _Self, class _Visitor>
13191318
_LIBCPP_HIDE_FROM_ABI constexpr _Rp visit(this _Self&& __self, _Visitor&& __visitor) {
1320-
using _VariantT = _OverrideRef<_Self&&, _CopyConst<remove_reference_t<_Self>, variant>>;
1321-
return std::visit<_Rp>(std::forward<_Visitor>(__visitor), (_VariantT)__self);
1319+
return std::visit<_Rp>(std::forward<_Visitor>(__visitor), std::__forward_as<_Self, variant>(__self));
13221320
}
13231321
# endif
13241322

0 commit comments

Comments
 (0)