Created on 2022-09-19.00:00:00 last changed 12 months ago
Proposed resolution:
This wording is relative to N4917.
Modify [range.utility.conv.to] as indicated:
[Drafting note: We need to be careful that this short-circuits, since if C does not satisfy input_range, then range_value_t<C> will be ill-formed.]
template<class C, input_range R, class... Args> requires (!view<C>) constexpr C to(R&& r, Args&&... args);-1- Returns: An object of type C constructed from the elements of r in the following manner:
(1.1) — If C does not satisfy input_range or convertible_to<range_reference_t<R>, range_value_t<C>> is true:
(1.1.1) — If constructible_from<C, R, Args...> is true:
C(std::forward<R>(r), std::forward<Args>(args)...)(1.1.2) — Otherwise, if constructible_from<C, from_range_t, R, Args...> is true:
C(from_range, std::forward<R>(r), std::forward<Args>(args)...)(1.1.3) — Otherwise, if
(1.1.3.1) — common_range<R> is true,
(1.1.3.2) — cpp17-input-iterator<iterator_t<R>> is true, and
(1.1.3.3) — constructible_from<C, iterator_t<R>, sentinel_t<R>, Args...> is true:
C(ranges::begin(r), ranges::end(r), std::forward<Args>(args)...)(1.1.4) — Otherwise, if
(1.1.4.1) — constructible_from<C, Args...> is true, and
(1.1.4.2) — container-insertable<C, range_reference_t<R>> is true:
C c(std::forward<Args>(args)...); if constexpr (sized_range<R> && reservable-container<C>) c.reserve(ranges::size(r)); ranges::copy(r, container-inserter<range_reference_t<R>>(c));(1.2) — Otherwise, if input_range<range_reference_t<R>> is true:
to<C>(r | views::transform([](auto&& elem) { return to<range_value_t<C>>(std::forward<decltype(elem)>(elem)); }), std::forward<Args>(args)...);(1.3) — Otherwise, the program is ill-formed.
[ 2022-11-12 Approved at November 2022 meeting in Kona. Status changed: Voting → WP. ]
[ 2022-09-28; Reflector poll ]
Set status to Tentatively Ready after five votes in favour during reflector poll.
During telecon review we agreed that supporting non-ranges was an intended
part of the original design, but was inadvertently broken when adding
range_value_t
for other reasons.
The current wording in [range.utility.conv.to] starts:
If convertible_to<range_reference_t<R>, range_value_t<C>> is true
and then tries to do C(r, args...) and then C(from_range, r, args...). The problem is that C might not be a range — indeed we explicitly removed that requirement from an earlier revision of the paper — which makes this check ill-formed. One example use-case is using ranges::to to convert a range of expected<T, E> into a expected<vector<T>, E> — expected isn't any kind of range, but it could support this operation, which is quite useful. Unfortunately, the wording explicitly rejects that. This change happened between R6 and R7 of the paper and seems to have unintentionally rejected this use-case.
History | |||
---|---|---|---|
Date | User | Action | Args |
2023-11-22 15:47:43 | admin | set | status: wp -> c++23 |
2022-11-17 00:42:33 | admin | set | status: voting -> wp |
2022-11-11 02:39:56 | admin | set | status: ready -> voting |
2022-11-10 23:33:20 | admin | set | messages: + msg13005 |
2022-11-10 23:33:20 | admin | set | status: voting -> ready |
2022-11-08 03:46:49 | admin | set | status: ready -> voting |
2022-09-28 16:10:02 | admin | set | messages: + msg12824 |
2022-09-28 16:10:02 | admin | set | status: new -> ready |
2022-09-25 07:28:52 | admin | set | messages: + msg12812 |
2022-09-19 00:00:00 | admin | create |