1 // -*- C++ -*- 2 //===----------------------------------------------------------------------===// 3 // 4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5 // See https://llvm.org/LICENSE.txt for license information. 6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7 // 8 //===----------------------------------------------------------------------===// 9 10 #ifndef _LIBCPP___UTILITY_FORWARD_LIKE_H 11 #define _LIBCPP___UTILITY_FORWARD_LIKE_H 12 13 #include <__config> 14 #include <__type_traits/conditional.h> 15 #include <__type_traits/is_base_of.h> 16 #include <__type_traits/is_const.h> 17 #include <__type_traits/is_reference.h> 18 #include <__type_traits/remove_reference.h> 19 20 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 21 # pragma GCC system_header 22 #endif 23 24 _LIBCPP_BEGIN_NAMESPACE_STD 25 26 #if _LIBCPP_STD_VER >= 23 27 28 template <class _Ap, class _Bp> 29 using _CopyConst _LIBCPP_NODEBUG = _If<is_const_v<_Ap>, const _Bp, _Bp>; 30 31 template <class _Ap, class _Bp> 32 using _OverrideRef _LIBCPP_NODEBUG = _If<is_rvalue_reference_v<_Ap>, remove_reference_t<_Bp>&&, _Bp&>; 33 34 template <class _Ap, class _Bp> 35 using _ForwardLike _LIBCPP_NODEBUG = _OverrideRef<_Ap&&, _CopyConst<remove_reference_t<_Ap>, remove_reference_t<_Bp>>>; 36 37 template <class _Tp, class _Up> 38 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto 39 forward_like(_LIBCPP_LIFETIMEBOUND _Up&& __ux) noexcept -> _ForwardLike<_Tp, _Up> { 40 return static_cast<_ForwardLike<_Tp, _Up>>(__ux); 41 } 42 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 59 #endif // _LIBCPP_STD_VER >= 23 60 61 _LIBCPP_END_NAMESPACE_STD 62 63 #endif // _LIBCPP___UTILITY_FORWARD_LIKE_H 64