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 _Comp, class _Proj> 31 _LIBCPP_HIDE_FROM_ABI constexpr static 32 decltype(auto) __make_projected_comp(_Comp& __comp, _Proj& __proj) { 33 if constexpr (same_as<decay_t<_Proj>, identity> && !is_member_pointer_v<decay_t<_Comp>>) { 34 // Avoid creating the lambda and just use the pristine comparator -- for certain algorithms, this would enable 35 // optimizations that rely on the type of the comparator. 36 return __comp; 37 38 } else { 39 return [&](auto&& __lhs, auto&& __rhs) { 40 return std::invoke(__comp, 41 std::invoke(__proj, std::forward<decltype(__lhs)>(__lhs)), 42 std::invoke(__proj, std::forward<decltype(__rhs)>(__rhs))); 43 }; 44 } 45 } 46 47 template <class _Comp, class _Proj1, class _Proj2> 48 _LIBCPP_HIDE_FROM_ABI constexpr static 49 decltype(auto) __make_projected_comp(_Comp& __comp, _Proj1& __proj1, _Proj2& __proj2) { 50 if constexpr (same_as<decay_t<_Proj1>, identity> && same_as<decay_t<_Proj2>, identity> && 51 !is_member_pointer_v<decay_t<_Comp>>) { 52 // Avoid creating the lambda and just use the pristine comparator -- for certain algorithms, this would enable 53 // optimizations that rely on the type of the comparator. 54 return __comp; 55 56 } else { 57 return [&](auto&& __lhs, auto&& __rhs) { 58 return std::invoke(__comp, 59 std::invoke(__proj1, std::forward<decltype(__lhs)>(__lhs)), 60 std::invoke(__proj2, std::forward<decltype(__rhs)>(__rhs))); 61 }; 62 } 63 } 64 65 } // namespace ranges 66 67 _LIBCPP_END_NAMESPACE_STD 68 69 #endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) 70 71 #endif // _LIBCPP___ALGORITHM_MAKE_PROJECTED_H 72