1*700637cbSDimitry Andric // -*- C++ -*- 2*700637cbSDimitry Andric //===----------------------------------------------------------------------===// 3*700637cbSDimitry Andric // 4*700637cbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5*700637cbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 6*700637cbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7*700637cbSDimitry Andric // 8*700637cbSDimitry Andric //===----------------------------------------------------------------------===// 9*700637cbSDimitry Andric 10*700637cbSDimitry Andric #ifndef _LIBCPP___ALGORITHM_RANGES_FOLD_H 11*700637cbSDimitry Andric #define _LIBCPP___ALGORITHM_RANGES_FOLD_H 12*700637cbSDimitry Andric 13*700637cbSDimitry Andric #include <__concepts/assignable.h> 14*700637cbSDimitry Andric #include <__concepts/constructible.h> 15*700637cbSDimitry Andric #include <__concepts/convertible_to.h> 16*700637cbSDimitry Andric #include <__concepts/invocable.h> 17*700637cbSDimitry Andric #include <__concepts/movable.h> 18*700637cbSDimitry Andric #include <__config> 19*700637cbSDimitry Andric #include <__functional/invoke.h> 20*700637cbSDimitry Andric #include <__functional/reference_wrapper.h> 21*700637cbSDimitry Andric #include <__iterator/concepts.h> 22*700637cbSDimitry Andric #include <__iterator/iterator_traits.h> 23*700637cbSDimitry Andric #include <__iterator/next.h> 24*700637cbSDimitry Andric #include <__ranges/access.h> 25*700637cbSDimitry Andric #include <__ranges/concepts.h> 26*700637cbSDimitry Andric #include <__ranges/dangling.h> 27*700637cbSDimitry Andric #include <__type_traits/decay.h> 28*700637cbSDimitry Andric #include <__type_traits/invoke.h> 29*700637cbSDimitry Andric #include <__utility/forward.h> 30*700637cbSDimitry Andric #include <__utility/move.h> 31*700637cbSDimitry Andric 32*700637cbSDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 33*700637cbSDimitry Andric # pragma GCC system_header 34*700637cbSDimitry Andric #endif 35*700637cbSDimitry Andric 36*700637cbSDimitry Andric _LIBCPP_PUSH_MACROS 37*700637cbSDimitry Andric #include <__undef_macros> 38*700637cbSDimitry Andric 39*700637cbSDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD 40*700637cbSDimitry Andric 41*700637cbSDimitry Andric #if _LIBCPP_STD_VER >= 23 42*700637cbSDimitry Andric 43*700637cbSDimitry Andric namespace ranges { 44*700637cbSDimitry Andric template <class _Ip, class _Tp> 45*700637cbSDimitry Andric struct in_value_result { 46*700637cbSDimitry Andric _LIBCPP_NO_UNIQUE_ADDRESS _Ip in; 47*700637cbSDimitry Andric _LIBCPP_NO_UNIQUE_ADDRESS _Tp value; 48*700637cbSDimitry Andric 49*700637cbSDimitry Andric template <class _I2, class _T2> 50*700637cbSDimitry Andric requires convertible_to<const _Ip&, _I2> && convertible_to<const _Tp&, _T2> in_value_resultin_value_result51*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr operator in_value_result<_I2, _T2>() const& { 52*700637cbSDimitry Andric return {in, value}; 53*700637cbSDimitry Andric } 54*700637cbSDimitry Andric 55*700637cbSDimitry Andric template <class _I2, class _T2> 56*700637cbSDimitry Andric requires convertible_to<_Ip, _I2> && convertible_to<_Tp, _T2> in_value_resultin_value_result57*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr operator in_value_result<_I2, _T2>() && { 58*700637cbSDimitry Andric return {std::move(in), std::move(value)}; 59*700637cbSDimitry Andric } 60*700637cbSDimitry Andric }; 61*700637cbSDimitry Andric 62*700637cbSDimitry Andric template <class _Ip, class _Tp> 63*700637cbSDimitry Andric using fold_left_with_iter_result = in_value_result<_Ip, _Tp>; 64*700637cbSDimitry Andric 65*700637cbSDimitry Andric template <class _Fp, class _Tp, class _Ip, class _Rp, class _Up = decay_t<_Rp>> 66*700637cbSDimitry Andric concept __indirectly_binary_left_foldable_impl = 67*700637cbSDimitry Andric convertible_to<_Rp, _Up> && // 68*700637cbSDimitry Andric movable<_Tp> && // 69*700637cbSDimitry Andric movable<_Up> && // 70*700637cbSDimitry Andric convertible_to<_Tp, _Up> && // 71*700637cbSDimitry Andric invocable<_Fp&, _Up, iter_reference_t<_Ip>> && // 72*700637cbSDimitry Andric assignable_from<_Up&, invoke_result_t<_Fp&, _Up, iter_reference_t<_Ip>>>; 73*700637cbSDimitry Andric 74*700637cbSDimitry Andric template <class _Fp, class _Tp, class _Ip> 75*700637cbSDimitry Andric concept __indirectly_binary_left_foldable = 76*700637cbSDimitry Andric copy_constructible<_Fp> && // 77*700637cbSDimitry Andric invocable<_Fp&, _Tp, iter_reference_t<_Ip>> && // 78*700637cbSDimitry Andric __indirectly_binary_left_foldable_impl<_Fp, _Tp, _Ip, invoke_result_t<_Fp&, _Tp, iter_reference_t<_Ip>>>; 79*700637cbSDimitry Andric 80*700637cbSDimitry Andric struct __fold_left_with_iter { 81*700637cbSDimitry Andric template <input_iterator _Ip, sentinel_for<_Ip> _Sp, class _Tp, __indirectly_binary_left_foldable<_Tp, _Ip> _Fp> operator__fold_left_with_iter82*700637cbSDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr auto operator()(_Ip __first, _Sp __last, _Tp __init, _Fp __f) { 83*700637cbSDimitry Andric using _Up = decay_t<invoke_result_t<_Fp&, _Tp, iter_reference_t<_Ip>>>; 84*700637cbSDimitry Andric 85*700637cbSDimitry Andric if (__first == __last) { 86*700637cbSDimitry Andric return fold_left_with_iter_result<_Ip, _Up>{std::move(__first), _Up(std::move(__init))}; 87*700637cbSDimitry Andric } 88*700637cbSDimitry Andric 89*700637cbSDimitry Andric _Up __result = std::invoke(__f, std::move(__init), *__first); 90*700637cbSDimitry Andric for (++__first; __first != __last; ++__first) { 91*700637cbSDimitry Andric __result = std::invoke(__f, std::move(__result), *__first); 92*700637cbSDimitry Andric } 93*700637cbSDimitry Andric 94*700637cbSDimitry Andric return fold_left_with_iter_result<_Ip, _Up>{std::move(__first), std::move(__result)}; 95*700637cbSDimitry Andric } 96*700637cbSDimitry Andric 97*700637cbSDimitry Andric template <input_range _Rp, class _Tp, __indirectly_binary_left_foldable<_Tp, iterator_t<_Rp>> _Fp> operator__fold_left_with_iter98*700637cbSDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr auto operator()(_Rp&& __r, _Tp __init, _Fp __f) { 99*700637cbSDimitry Andric auto __result = operator()(ranges::begin(__r), ranges::end(__r), std::move(__init), std::ref(__f)); 100*700637cbSDimitry Andric 101*700637cbSDimitry Andric using _Up = decay_t<invoke_result_t<_Fp&, _Tp, range_reference_t<_Rp>>>; 102*700637cbSDimitry Andric return fold_left_with_iter_result<borrowed_iterator_t<_Rp>, _Up>{std::move(__result.in), std::move(__result.value)}; 103*700637cbSDimitry Andric } 104*700637cbSDimitry Andric }; 105*700637cbSDimitry Andric 106*700637cbSDimitry Andric inline constexpr auto fold_left_with_iter = __fold_left_with_iter(); 107*700637cbSDimitry Andric 108*700637cbSDimitry Andric struct __fold_left { 109*700637cbSDimitry Andric template <input_iterator _Ip, sentinel_for<_Ip> _Sp, class _Tp, __indirectly_binary_left_foldable<_Tp, _Ip> _Fp> operator__fold_left110*700637cbSDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr auto operator()(_Ip __first, _Sp __last, _Tp __init, _Fp __f) { 111*700637cbSDimitry Andric return fold_left_with_iter(std::move(__first), std::move(__last), std::move(__init), std::ref(__f)).value; 112*700637cbSDimitry Andric } 113*700637cbSDimitry Andric 114*700637cbSDimitry Andric template <input_range _Rp, class _Tp, __indirectly_binary_left_foldable<_Tp, iterator_t<_Rp>> _Fp> operator__fold_left115*700637cbSDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr auto operator()(_Rp&& __r, _Tp __init, _Fp __f) { 116*700637cbSDimitry Andric return fold_left_with_iter(ranges::begin(__r), ranges::end(__r), std::move(__init), std::ref(__f)).value; 117*700637cbSDimitry Andric } 118*700637cbSDimitry Andric }; 119*700637cbSDimitry Andric 120*700637cbSDimitry Andric inline constexpr auto fold_left = __fold_left(); 121*700637cbSDimitry Andric } // namespace ranges 122*700637cbSDimitry Andric 123*700637cbSDimitry Andric #endif // _LIBCPP_STD_VER >= 23 124*700637cbSDimitry Andric 125*700637cbSDimitry Andric _LIBCPP_END_NAMESPACE_STD 126*700637cbSDimitry Andric 127*700637cbSDimitry Andric _LIBCPP_POP_MACROS 128*700637cbSDimitry Andric 129*700637cbSDimitry Andric #endif // _LIBCPP___ALGORITHM_RANGES_FOLD_H 130