Title
Some problems with the wording changes of P1739R4
Status
new
Section
[range.take.overview][range.iota]
Submitter
Patrick Palka

Created on 2020-02-21.00:00:00 last changed 5 days ago

Messages

Date: 2020-03-29.00:00:00

[ 2020-03-29 Issue Prioritization ]

Priority to 2 after reflector discussion.

Date: 2020-03-15.00:00:00

[ 2020-03-16, Tomasz comments ]

A similar problem occurs for the views::drop for the subrange<I, S, subrange_kind::sized>, that explicitly stores size (i.e. sized_sentinel_for<I, S> is false). In such case, the (iterator, sentinel) constructor that views::drop will be expression-equivalent is not available.

Date: 2020-02-15.00:00:00

[ 2020-02-24, Casey comments ]

Furthermore, the pertinent subrange constructor is only available when subrange::StoreSize is false (i.e., when either the subrange specialization's third template argument is not subrange_kind::sized or its iterator and sentinel types I and S model sized_sentinel_for<S, I>).

Date: 2020-02-21.00:00:00

Section 6.1 of P1739R4 changes the specification of views::take as follows:

-2- The name views::take denotes a range adaptor object ([range.adaptor.object]). Given subexpressions E and F, the expression views::take(E, F) is expression-equivalent to take_view{E, F}. Let E and F be expressions, let T be remove_cvref_t<decltype((E))>, and let D be range_difference_t<decltype((E))>. If decltype((F)) does not model convertible_to<D>, views::take(E, F) is ill-formed. Otherwise, the expression views::take(E, F) is expression-equivalent to:

  1. — if T is a specialization of ranges::empty_view ([range.empty.view]), then ((void) F, decay-copy(E));

  2. — otherwise, if T models random_access_range and sized_range and is

    1. — a specialization of span ([views.span]) where T::extent == dynamic_extent,

    2. — a specialization of basic_string_view ([string.view]),

    3. — a specialization of ranges::iota_view ([range.iota.view]), or

    4. — a specialization of ranges::subrange ([range.subrange]),

    then T{ranges::begin(E), ranges::begin(E) + min<D>(ranges::size(E), F)}, except that E is evaluated only once;

  3. — otherwise, ranges::take_view{E, F}.

Consider the case when T = subrange<counted_iterator<int>, default_sentinel_t>. Then according to the above wording, views::take(E, F) is expression-equivalent to

T{ranges::begin(E), ranges:begin(E) + min<D>(ranges::size(E), F)};   (*)

But this expression is ill-formed for the T we chose because subrange<counted_iterator<int>, default_sentinel_t> has no matching constructor that takes an iterator-iterator pair.

More generally the above issue applies anytime T is a specialization of subrange that does not model common_range. But a similar issue also exists when T is a specialization of iota_view whose value type differs from its bound type. In this case yet another issue arises: In order for the expression (*) to be well-formed when T is a specialization of iota_view, we need to be able to construct an iota_view out of an iterator-iterator pair, and for that it seems we need to add another constructor to iota_view.

History
Date User Action Args
2020-03-29 15:38:28adminsetmessages: + msg11177
2020-03-21 11:46:21adminsetmessages: + msg11169
2020-02-24 20:22:21adminsetmessages: + msg11149
2020-02-21 00:00:00admincreate