[libcxx-commits] [libcxx] [libc++] Add `ranges::fold_left_first` and ranges::`fold_left_first_with_iter` (PR #121558)
A. Jiang via libcxx-commits
libcxx-commits at lists.llvm.org
Fri Jan 3 05:29:54 PST 2025
================
@@ -118,6 +121,54 @@ struct __fold_left {
};
inline constexpr auto fold_left = __fold_left();
+
+struct __fold_left_first_with_iter {
+ template <input_iterator _Ip, sentinel_for<_Ip> _Sp, __indirectly_binary_left_foldable<iter_value_t<_Ip>, _Ip> _Fp>
+ requires constructible_from<iter_value_t<_Ip>, iter_reference_t<_Ip>>
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr auto operator()(_Ip __first, _Sp __last, _Fp __f) {
+ using _Up = decltype(fold_left(std::move(__first), __last, iter_value_t<_Ip>(*__first), __f));
+
+ // case of empty range
+ if (__first == __last) {
+ return fold_left_first_with_iter_result<_Ip, optional<_Up>>{std::move(__first), optional<_Up>()};
+ }
+
+ optional<_Up> __result(std::in_place, *__first);
+ for (++__first; __first != __last; ++__first) {
+ *__result = std::invoke(__f, std::move(*__result), *__first);
+ }
----------------
frederick-vs-ja wrote:
I think it's OK to construct a `_Up` object, use it in the loop, and finally constructs the `optional<_Up>`. This approach seemingly behaves better in debugging and constant evaluation, as less steps are executed.
```suggestion
_Up __result(*__first);
for (++__first; __first != __last; ++__first) {
__result = std::invoke(__f, std::move(__result), *__first);
}
```
https://github.com/llvm/llvm-project/pull/121558
More information about the libcxx-commits
mailing list