1*4bdff4beSrobert //===----------------------------------------------------------------------===// 2*4bdff4beSrobert // 3*4bdff4beSrobert // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*4bdff4beSrobert // See https://llvm.org/LICENSE.txt for license information. 5*4bdff4beSrobert // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*4bdff4beSrobert // 7*4bdff4beSrobert //===----------------------------------------------------------------------===// 8*4bdff4beSrobert 9*4bdff4beSrobert #ifndef _LIBCPP___ALGORITHM_MAKE_PROJECTED_H 10*4bdff4beSrobert #define _LIBCPP___ALGORITHM_MAKE_PROJECTED_H 11*4bdff4beSrobert 12*4bdff4beSrobert #include <__concepts/same_as.h> 13*4bdff4beSrobert #include <__config> 14*4bdff4beSrobert #include <__functional/identity.h> 15*4bdff4beSrobert #include <__functional/invoke.h> 16*4bdff4beSrobert #include <__type_traits/decay.h> 17*4bdff4beSrobert #include <__type_traits/enable_if.h> 18*4bdff4beSrobert #include <__type_traits/integral_constant.h> 19*4bdff4beSrobert #include <__type_traits/is_member_pointer.h> 20*4bdff4beSrobert #include <__type_traits/is_same.h> 21*4bdff4beSrobert #include <__utility/declval.h> 22*4bdff4beSrobert #include <__utility/forward.h> 23*4bdff4beSrobert 24*4bdff4beSrobert #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 25*4bdff4beSrobert # pragma GCC system_header 26*4bdff4beSrobert #endif 27*4bdff4beSrobert 28*4bdff4beSrobert _LIBCPP_BEGIN_NAMESPACE_STD 29*4bdff4beSrobert 30*4bdff4beSrobert template <class _Pred, class _Proj> 31*4bdff4beSrobert struct _ProjectedPred { 32*4bdff4beSrobert _Pred& __pred; // Can be a unary or a binary predicate. 33*4bdff4beSrobert _Proj& __proj; 34*4bdff4beSrobert _ProjectedPred_ProjectedPred35*4bdff4beSrobert _LIBCPP_CONSTEXPR _ProjectedPred(_Pred& __pred_arg, _Proj& __proj_arg) : __pred(__pred_arg), __proj(__proj_arg) {} 36*4bdff4beSrobert 37*4bdff4beSrobert template <class _Tp> 38*4bdff4beSrobert typename __invoke_of<_Pred&, 39*4bdff4beSrobert decltype(std::__invoke(std::declval<_Proj&>(), std::declval<_Tp>())) 40*4bdff4beSrobert >::type operator_ProjectedPred41*4bdff4beSrobert _LIBCPP_CONSTEXPR operator()(_Tp&& __v) const { 42*4bdff4beSrobert return std::__invoke(__pred, std::__invoke(__proj, std::forward<_Tp>(__v))); 43*4bdff4beSrobert } 44*4bdff4beSrobert 45*4bdff4beSrobert template <class _T1, class _T2> 46*4bdff4beSrobert typename __invoke_of<_Pred&, 47*4bdff4beSrobert decltype(std::__invoke(std::declval<_Proj&>(), std::declval<_T1>())), 48*4bdff4beSrobert decltype(std::__invoke(std::declval<_Proj&>(), std::declval<_T2>())) 49*4bdff4beSrobert >::type operator_ProjectedPred50*4bdff4beSrobert _LIBCPP_CONSTEXPR operator()(_T1&& __lhs, _T2&& __rhs) const { 51*4bdff4beSrobert return std::__invoke(__pred, 52*4bdff4beSrobert std::__invoke(__proj, std::forward<_T1>(__lhs)), 53*4bdff4beSrobert std::__invoke(__proj, std::forward<_T2>(__rhs))); 54*4bdff4beSrobert } 55*4bdff4beSrobert 56*4bdff4beSrobert }; 57*4bdff4beSrobert 58*4bdff4beSrobert template <class _Pred, class _Proj, class = void> 59*4bdff4beSrobert struct __can_use_pristine_comp : false_type {}; 60*4bdff4beSrobert 61*4bdff4beSrobert template <class _Pred, class _Proj> 62*4bdff4beSrobert struct __can_use_pristine_comp<_Pred, _Proj, __enable_if_t< 63*4bdff4beSrobert !is_member_pointer<typename decay<_Pred>::type>::value && ( 64*4bdff4beSrobert #if _LIBCPP_STD_VER > 17 65*4bdff4beSrobert is_same<typename decay<_Proj>::type, identity>::value || 66*4bdff4beSrobert #endif 67*4bdff4beSrobert is_same<typename decay<_Proj>::type, __identity>::value 68*4bdff4beSrobert ) 69*4bdff4beSrobert > > : true_type {}; 70*4bdff4beSrobert 71*4bdff4beSrobert template <class _Pred, class _Proj> 72*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR static 73*4bdff4beSrobert __enable_if_t< 74*4bdff4beSrobert !__can_use_pristine_comp<_Pred, _Proj>::value, 75*4bdff4beSrobert _ProjectedPred<_Pred, _Proj> 76*4bdff4beSrobert > 77*4bdff4beSrobert __make_projected(_Pred& __pred, _Proj& __proj) { 78*4bdff4beSrobert return _ProjectedPred<_Pred, _Proj>(__pred, __proj); 79*4bdff4beSrobert } 80*4bdff4beSrobert 81*4bdff4beSrobert // Avoid creating the functor and just use the pristine comparator -- for certain algorithms, this would enable 82*4bdff4beSrobert // optimizations that rely on the type of the comparator. Additionally, this results in less layers of indirection in 83*4bdff4beSrobert // the call stack when the comparator is invoked, even in an unoptimized build. 84*4bdff4beSrobert template <class _Pred, class _Proj> 85*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR static 86*4bdff4beSrobert __enable_if_t< 87*4bdff4beSrobert __can_use_pristine_comp<_Pred, _Proj>::value, 88*4bdff4beSrobert _Pred& 89*4bdff4beSrobert > 90*4bdff4beSrobert __make_projected(_Pred& __pred, _Proj&) { 91*4bdff4beSrobert return __pred; 92*4bdff4beSrobert } 93*4bdff4beSrobert 94*4bdff4beSrobert _LIBCPP_END_NAMESPACE_STD 95*4bdff4beSrobert 96*4bdff4beSrobert #if _LIBCPP_STD_VER > 17 97*4bdff4beSrobert 98*4bdff4beSrobert _LIBCPP_BEGIN_NAMESPACE_STD 99*4bdff4beSrobert 100*4bdff4beSrobert namespace ranges { 101*4bdff4beSrobert 102*4bdff4beSrobert template <class _Comp, class _Proj1, class _Proj2> 103*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI constexpr static 104*4bdff4beSrobert decltype(auto) __make_projected_comp(_Comp& __comp, _Proj1& __proj1, _Proj2& __proj2) { 105*4bdff4beSrobert if constexpr (same_as<decay_t<_Proj1>, identity> && same_as<decay_t<_Proj2>, identity> && 106*4bdff4beSrobert !is_member_pointer_v<decay_t<_Comp>>) { 107*4bdff4beSrobert // Avoid creating the lambda and just use the pristine comparator -- for certain algorithms, this would enable 108*4bdff4beSrobert // optimizations that rely on the type of the comparator. 109*4bdff4beSrobert return __comp; 110*4bdff4beSrobert 111*4bdff4beSrobert } else { 112*4bdff4beSrobert return [&](auto&& __lhs, auto&& __rhs) { 113*4bdff4beSrobert return std::invoke(__comp, 114*4bdff4beSrobert std::invoke(__proj1, std::forward<decltype(__lhs)>(__lhs)), 115*4bdff4beSrobert std::invoke(__proj2, std::forward<decltype(__rhs)>(__rhs))); 116*4bdff4beSrobert }; 117*4bdff4beSrobert } 118*4bdff4beSrobert } 119*4bdff4beSrobert 120*4bdff4beSrobert } // namespace ranges 121*4bdff4beSrobert 122*4bdff4beSrobert _LIBCPP_END_NAMESPACE_STD 123*4bdff4beSrobert 124*4bdff4beSrobert #endif // _LIBCPP_STD_VER > 17 125*4bdff4beSrobert 126*4bdff4beSrobert #endif // _LIBCPP___ALGORITHM_MAKE_PROJECTED_H 127