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