This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of New status.
4093.ranges::fold_left_first_with_iter
incorrectly constructs optional<U>
Section: 26.6.18 [alg.fold] Status: New Submitter: Hewill Kang Opened: 2024-05-03 Last modified: 2024-06-24
Priority: 3
View other active issues in [alg.fold].
View all other issues in [alg.fold].
View all issues with New status.
Discussion:
ranges::fold_left_first_with_iter
constructs the initial value through optional<U>(in_place, *first)
which is not quite right, because the exposure constraint only ensures that U
can be constructed from the value type of the iterator rather than its reference (demo):
#include <ranges> #include <algorithm> struct Op { Op() = default; Op(std::tuple<int>); Op(std::tuple<int&>) = delete; Op operator()(Op, std::tuple<int&>) const; }; int main() { std::ranges::fold_left_first_with_iter( std::views::zip(std::views::single(0)), Op{} ); // hard error in libstdc++ and MSVC-STL }
[2024-06-24; Reflector poll]
Set priority to 3 after reflector poll. Unclear what "exposure constraint" means. "Don't want to require an extra copy to accommodate this corner case."
Proposed resolution:
This wording is relative to N4981.
Modify 26.6.18 [alg.fold] as indicated:
template<input_iterator I, sentinel_for<I> S indirectly-binary-left-foldable<iter_value_t<I>, I> F> requires constructible_from<iter_value_t<I>, iter_reference_t<I>> constexpr see below ranges::fold_left_first_with_iter(I first, S last, F f); template<input_range R, indirectly-binary-left-foldable<range_value_t<R>, iterator_t<R>> F> requires constructible_from<range_value_t<R>, range_reference_t<R>> constexpr see below ranges::fold_left_first_with_iter(R&& r, F f);-9- Let
U
bedecltype(ranges::fold_left(std::move(first), last, iter_value_t<I>(*first), f))-10- Effects: Equivalent to:
if (first == last) return {std::move(first), optional<U>()}; optional<U> init(in_place, iter_value_t<I>(*first)); for (++first; first != last; ++first) *init = invoke(f, std::move(*init), *first); return {std::move(first), std::move(init)};-11- Remarks: The return type is
fold_left_first_with_iter_result<I, optional<U>>
for the first overload andfold_left_first_with_iter_result<borrowed_iterator_t<R>, optional<U>>
for the second overload.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4