1 //===----------------------------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef _LIBCPP___ALGORITHM_MAKE_PROJECTED_H 10 #define _LIBCPP___ALGORITHM_MAKE_PROJECTED_H 11 12 #include <__concepts/same_as.h> 13 #include <__config> 14 #include <__functional/identity.h> 15 #include <__functional/invoke.h> 16 #include <__type_traits/decay.h> 17 #include <__type_traits/is_member_pointer.h> 18 #include <__utility/forward.h> 19 20 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 21 # pragma GCC system_header 22 #endif 23 24 #if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) 25 26 _LIBCPP_BEGIN_NAMESPACE_STD 27 28 namespace ranges { 29 30 template <class _Pred, class _Proj> 31 _LIBCPP_HIDE_FROM_ABI constexpr static 32 decltype(auto) __make_projected_pred(_Pred& __pred, _Proj& __proj) { 33 if constexpr (same_as<decay_t<_Proj>, identity> && !is_member_pointer_v<decay_t<_Pred>>) { 34 // Avoid creating the lambda and just use the pristine predicate -- for certain algorithms, this would enable 35 // optimizations that rely on the type of the predicate. 36 return __pred; 37 38 } else { 39 return [&](auto&& __x) { 40 return std::invoke(__pred, std::invoke(__proj, std::forward<decltype(__x)>(__x))); 41 }; 42 } 43 } 44 45 template <class _Comp, class _Proj> 46 _LIBCPP_HIDE_FROM_ABI constexpr static 47 decltype(auto) __make_projected_comp(_Comp& __comp, _Proj& __proj) { 48 if constexpr (same_as<decay_t<_Proj>, identity> && !is_member_pointer_v<decay_t<_Comp>>) { 49 // Avoid creating the lambda and just use the pristine comparator -- for certain algorithms, this would enable 50 // optimizations that rely on the type of the comparator. 51 return __comp; 52 53 } else { 54 return [&](auto&& __lhs, auto&& __rhs) { 55 return std::invoke(__comp, 56 std::invoke(__proj, std::forward<decltype(__lhs)>(__lhs)), 57 std::invoke(__proj, std::forward<decltype(__rhs)>(__rhs))); 58 }; 59 } 60 } 61 62 template <class _Comp, class _Proj1, class _Proj2> 63 _LIBCPP_HIDE_FROM_ABI constexpr static 64 decltype(auto) __make_projected_comp(_Comp& __comp, _Proj1& __proj1, _Proj2& __proj2) { 65 if constexpr (same_as<decay_t<_Proj1>, identity> && same_as<decay_t<_Proj2>, identity> && 66 !is_member_pointer_v<decay_t<_Comp>>) { 67 // Avoid creating the lambda and just use the pristine comparator -- for certain algorithms, this would enable 68 // optimizations that rely on the type of the comparator. 69 return __comp; 70 71 } else { 72 return [&](auto&& __lhs, auto&& __rhs) { 73 return std::invoke(__comp, 74 std::invoke(__proj1, std::forward<decltype(__lhs)>(__lhs)), 75 std::invoke(__proj2, std::forward<decltype(__rhs)>(__rhs))); 76 }; 77 } 78 } 79 80 } // namespace ranges 81 82 _LIBCPP_END_NAMESPACE_STD 83 84 #endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) 85 86 #endif // _LIBCPP___ALGORITHM_MAKE_PROJECTED_H 87