zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

blob 5245e523 (3988B) - Raw


      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/enable_if.h>
     18 #include <__type_traits/integral_constant.h>
     19 #include <__type_traits/is_member_pointer.h>
     20 #include <__type_traits/is_same.h>
     21 #include <__utility/declval.h>
     22 #include <__utility/forward.h>
     23 
     24 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
     25 #  pragma GCC system_header
     26 #endif
     27 
     28 _LIBCPP_BEGIN_NAMESPACE_STD
     29 
     30 template <class _Pred, class _Proj>
     31 struct _ProjectedPred {
     32   _Pred& __pred; // Can be a unary or a binary predicate.
     33   _Proj& __proj;
     34 
     35   _LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI _ProjectedPred(_Pred& __pred_arg, _Proj& __proj_arg)
     36       : __pred(__pred_arg), __proj(__proj_arg) {}
     37 
     38   template <class _Tp>
     39   typename __invoke_of<_Pred&, decltype(std::__invoke(std::declval<_Proj&>(), std::declval<_Tp>()))>::type
     40       _LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI
     41       operator()(_Tp&& __v) const {
     42     return std::__invoke(__pred, std::__invoke(__proj, std::forward<_Tp>(__v)));
     43   }
     44 
     45   template <class _T1, class _T2>
     46   typename __invoke_of<_Pred&,
     47                        decltype(std::__invoke(std::declval<_Proj&>(), std::declval<_T1>())),
     48                        decltype(std::__invoke(std::declval<_Proj&>(), std::declval<_T2>()))>::type _LIBCPP_CONSTEXPR
     49   _LIBCPP_HIDE_FROM_ABI
     50   operator()(_T1&& __lhs, _T2&& __rhs) const {
     51     return std::__invoke(
     52         __pred, std::__invoke(__proj, std::forward<_T1>(__lhs)), std::__invoke(__proj, std::forward<_T2>(__rhs)));
     53   }
     54 };
     55 
     56 template <
     57     class _Pred,
     58     class _Proj,
     59     __enable_if_t<!(!is_member_pointer<__decay_t<_Pred> >::value && __is_identity<__decay_t<_Proj> >::value), int> = 0>
     60 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _ProjectedPred<_Pred, _Proj> __make_projected(_Pred& __pred, _Proj& __proj) {
     61   return _ProjectedPred<_Pred, _Proj>(__pred, __proj);
     62 }
     63 
     64 // Avoid creating the functor and just use the pristine comparator -- for certain algorithms, this would enable
     65 // optimizations that rely on the type of the comparator. Additionally, this results in less layers of indirection in
     66 // the call stack when the comparator is invoked, even in an unoptimized build.
     67 template <
     68     class _Pred,
     69     class _Proj,
     70     __enable_if_t<!is_member_pointer<__decay_t<_Pred> >::value && __is_identity<__decay_t<_Proj> >::value, int> = 0>
     71 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Pred& __make_projected(_Pred& __pred, _Proj&) {
     72   return __pred;
     73 }
     74 
     75 _LIBCPP_END_NAMESPACE_STD
     76 
     77 #if _LIBCPP_STD_VER >= 20
     78 
     79 _LIBCPP_BEGIN_NAMESPACE_STD
     80 
     81 namespace ranges {
     82 
     83 template <class _Comp, class _Proj1, class _Proj2>
     84 _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) __make_projected_comp(_Comp& __comp, _Proj1& __proj1, _Proj2& __proj2) {
     85   if constexpr (__is_identity<decay_t<_Proj1>>::value && __is_identity<decay_t<_Proj2>>::value &&
     86                 !is_member_pointer_v<decay_t<_Comp>>) {
     87     // Avoid creating the lambda and just use the pristine comparator -- for certain algorithms, this would enable
     88     // optimizations that rely on the type of the comparator.
     89     return __comp;
     90 
     91   } else {
     92     return [&](auto&& __lhs, auto&& __rhs) -> bool {
     93       return std::invoke(__comp,
     94                          std::invoke(__proj1, std::forward<decltype(__lhs)>(__lhs)),
     95                          std::invoke(__proj2, std::forward<decltype(__rhs)>(__rhs)));
     96     };
     97   }
     98 }
     99 
    100 } // namespace ranges
    101 
    102 _LIBCPP_END_NAMESPACE_STD
    103 
    104 #endif // _LIBCPP_STD_VER >= 20
    105 
    106 #endif // _LIBCPP___ALGORITHM_MAKE_PROJECTED_H