Created on 2022-09-15.00:00:00 last changed 25 months ago
Proposed resolution:
This wording is relative to N4917.
Modify [alg.fold] as indicated:
template<bidirectional_iterator I, sentinel_for<I> S, class T, indirectly-binary-right-foldable<T, I> F> constexpr auto ranges::fold_right(I first, S last, T init, F f); template<bidirectional_range R, class T, indirectly-binary-right-foldable<T, iterator_t<R>> F> constexpr auto ranges::fold_right(R&& r, T init, F f);[…]-3- Effects: Equivalent to:
using U = decay_t<invoke_result_t<F&, iter_reference_t<I>, T>>; if (first == last) return static_cast<U>(std::move(init)); I tail = ranges::next(first, last); U accum = invoke(f, *--tail, std::move(init)); while (first != tail) accum = invoke(f, *--tail, std::move(accum)); return accum;template<input_iterator I, sentinel_for<I> S, class T, indirectly-binary-left-foldable<T, I> F> constexpr see below ranges::fold_left_with_iter(I first, S last, T init, F f); template<input_range R, class T, indirectly-binary-left-foldable<T, iterator_t<R>> F> constexpr see below ranges::fold_left_with_iter(R&& r, T init, F f);-6- Let U be decay_t<invoke_result_t<F&, T, iter_reference_t<I>>>.
-7- Effects: Equivalent to:if (first == last) return {std::move(first), static_cast<U>(std::move(init))}; U accum = invoke(f, std::move(init), *first); for (++first; first != last; ++first) accum = invoke(f, std::move(accum), *first); return {std::move(first), std::move(accum)};
[ 2022-11-30 LWG telecon. Status changed: Tentatively NAD → NAD. ]
[ 2022-10-12; Reflector poll ]
Set status to "Tentatively NAD" after reflector poll.
"The example doesn't compile. The accumulator should be be the second param, but with that fixed the constraints are not satisfied. The convertible_to constraint prevents the undesirable casting."
In the Effects element of ranges::fold_right, we get the following code:
using U = decay_t<invoke_result_t<F&, iter_reference_t<I>, T>>;
if (first == last)
return U(std::move(init)); // functional-style C cast
[…]
Given the following function object:
struct Second { static char* operator()(const char*, char* rhs) { return rhs; } };
calling fold_right as:
char* p = fold_right(views::empty<char*>, "Hello", Second{});
initializes p with const_cast<char*>("Hello").
The same problem exists in fold_left_with_iter, and thus in fold_left. One can get the reinterpret_cast behavior by replacing const char* with unsigned long long.History | |||
---|---|---|---|
Date | User | Action | Args |
2022-11-30 17:59:24 | admin | set | messages: + msg13141 |
2022-10-12 14:38:10 | admin | set | messages: + msg12852 |
2022-10-12 14:38:10 | admin | set | status: new -> nad |
2022-09-17 15:36:52 | admin | set | messages: + msg12771 |
2022-09-15 00:00:00 | admin | create |