[libcxx-commits] [clang-tools-extra] [libcxx] [clang] [llvm] [libcxx] adds ranges::fold_left_with_iter and ranges::fold_left (PR #75259)

Christopher Di Bella via libcxx-commits libcxx-commits at lists.llvm.org
Thu Dec 28 13:28:08 PST 2023


================
@@ -0,0 +1,118 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___ALGORITHM_FOLD_H
+#define _LIBCPP___ALGORITHM_FOLD_H
+
+#include <__concepts/assignable.h>
+#include <__concepts/convertible_to.h>
+#include <__concepts/invocable.h>
+#include <__concepts/movable.h>
+#include <__config>
+#include <__functional/invoke.h>
+#include <__functional/reference_wrapper.h>
+#include <__iterator/concepts.h>
+#include <__iterator/iterator_traits.h>
+#include <__iterator/next.h>
+#include <__ranges/access.h>
+#include <__ranges/concepts.h>
+#include <__ranges/dangling.h>
+#include <__type_traits/decay.h>
+#include <__type_traits/invoke.h>
+#include <__utility/forward.h>
+#include <__utility/move.h>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#  pragma GCC system_header
+#endif
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+#if _LIBCPP_STD_VER >= 23
+
+namespace ranges {
+template <class _Ip, class _Tp>
+struct in_value_result {
+  _Ip in;
+  _Tp result;
+};
+
+template <class _Ip, class _Tp>
+using fold_left_with_iter_result = in_value_result<_Ip, _Tp>;
+
+template <class _Fp, class _Tp, class _Ip, class _Rp, class _Up = decay_t<_Rp>>
+concept __indirectly_binary_left_foldable_impl =
+    convertible_to<_Rp, _Up> &&                    //
+    movable<_Tp> &&                                //
+    movable<_Up> &&                                //
+    convertible_to<_Tp, _Up> &&                    //
+    invocable<_Fp&, _Up, iter_reference_t<_Ip>> && //
+    assignable_from<_Up&, invoke_result_t<_Fp&, _Up, iter_reference_t<_Ip>>>;
+
+template <class _Fp, class _Tp, class _Ip>
+concept __indirectly_binary_left_foldable =
+    copy_constructible<_Fp> &&                     //
+    invocable<_Fp&, _Tp, iter_reference_t<_Ip>> && //
+    __indirectly_binary_left_foldable_impl<_Fp, _Tp, _Ip, invoke_result_t<_Fp&, _Tp, iter_reference_t<_Ip>>>;
+
+struct __fold_left_with_iter {
+  template <input_iterator _Ip, sentinel_for<_Ip> _Sp, class _Tp, __indirectly_binary_left_foldable<_Tp, _Ip> _Fp>
+  _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static constexpr auto
+  operator()(_Ip __first, _Sp __last, _Tp __init, _Fp __f) {
+    using _Up = decay_t<invoke_result_t<_Fp&, _Tp, iter_reference_t<_Ip>>>;
+
+    if (__first == __last) {
+      return fold_left_with_iter_result<_Ip, _Up>{std::move(__first), _Up(std::move(__init))};
+    }
+
+    _Up __result = std::invoke(__f, std::move(__init), *__first);
+    for (++__first; __first != __last; ++__first) {
+      __result = std::invoke(__f, std::move(__result), *__first);
+    }
+
+    return fold_left_with_iter_result<_Ip, _Up>{std::move(__first), std::move(__result)};
+  }
+
+  template <input_range _Rp, class _Tp, __indirectly_binary_left_foldable<_Tp, iterator_t<_Rp>> _Fp>
+  _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static constexpr auto operator()(_Rp&& __r, _Tp __init, _Fp __f) {
+    auto __result = operator()(ranges::begin(__r), ranges::end(__r), std::move(__init), std::ref(__f));
+
+    using _Up = decay_t<invoke_result_t<_Fp&, _Tp, range_reference_t<_Rp>>>;
+    return fold_left_with_iter_result<borrowed_iterator_t<_Rp>, _Up>{
+        std::move(__result.in), std::move(__result.result)};
+  }
+};
+
+inline namespace __cpo {
+inline constexpr auto fold_left_with_iter = __fold_left_with_iter();
+} // namespace __cpo
+
+struct __fold_left {
+  template <input_iterator _Ip, sentinel_for<_Ip> _Sp, class _Tp, __indirectly_binary_left_foldable<_Tp, _Ip> _Fp>
----------------
cjdb wrote:

I am okay with the current resolution given that a discussion has happened, and am happy to make a dedicated migration patch for all `_Ip`/`_Sp` names. This has **not** been applied in #76534: I'll make a dedicated commit for that in about an hour.

I think that the contribution guidelines should probably issue guidance on what kinds of names we expect, especially when it comes to names that we want to have some element of consistency for. Perhaps that could be the subject of the new discussion.

https://github.com/llvm/llvm-project/pull/75259


More information about the libcxx-commits mailing list