Issue 3403: Domain of ranges::ssize(E) doesn't match ranges::size(E) (original) (raw)


This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of C++23 status.

3403. Domain of ranges::ssize(E) doesn't match ranges::size(E)

Section: 25.3.11 [range.prim.ssize] Status: C++23 Submitter: Jonathan Wakely Opened: 2020-02-19 Last modified: 2023-11-22

Priority: 2

View all issues with C++23 status.

Discussion:

ranges::size(E) works with a non-range for which E.size() or size(E) is valid. But ranges::ssize(E) requires the type range_difference_t which requiresranges::begin(E) to be valid. This means there are types for which ranges::size(E)is valid but ranges::ssize(E) is not.

Casey's reaction to this is:

I believe we want ranges::ssize to work with any argument that ranges::size accepts. That suggest to me that we're going to need _make-signed-like-t_<T> after all, so we can "Let E be an expression, and let D be the wider of ptrdiff_tor decltype(ranges::size(E)). Then ranges::ssize(E) is expression-equivalent tostatic_cast<_make-signed-like-t_<D>>(ranges::size(E))." Although this wording is still slightly icky since D isn't a valid type when ranges::size(E) isn't a valid expression, I think it's an improvement?

[2020-03-11 Issue Prioritization]

Priority to 2 after reflector discussion.

[2020-07-22 Casey provides wording]

Previous resolution [SUPERSEDED]:

This wording is relative to N4861.

  1. Add a new paragraph after paragraph 1 in 25.2 [ranges.syn]:

    -?- Also within this clause,_make-signed-like-t_<X>for an integer-like type Xdenotes make_signed_t<X>if X is an integer type; otherwise, it denotes a corresponding unspecified signed-integer-like type of the same width as X.

  2. Modify 25.3.11 [range.prim.ssize] as indicated:

    -1- The name ranges::ssize denotes a customization point object (16.3.3.3.5 [customization.point.object]).The expression ranges::ssize(E)for a subexpression E of type Tis expression-equivalent to:

    (1.1) — If range_difference_t<T> has width less than ptrdiff_t,static_cast<ptrdiff_t>(ranges::size(E)).

    (1.2) — Otherwise,static_cast<range_difference_t<T>>(ranges::size(E)).

    -?- Given a subexpression E with type T, let t be an lvalue that denotes the reified object for E. If ranges::size(t) is ill-formed,ranges::ssize(E) is ill-formed. Otherwise, let D be the wider ofptrdiff_t or decltype(ranges::size(t));ranges::ssize(E) is expression-equivalent tostatic_cast<_make-signed-like-t_<D>>(ranges::size(t)).

[2020-07-31 Casey provides updated wording]

Per discussion on the reflector.

[2020-08-21; Issue processing telecon: Tentatively Ready]

[2020-11-09 Approved In November virtual meeting. Status changed: Tentatively Ready → WP.]

Proposed resolution:

This wording is relative to N4861.

  1. Add a new paragraph after paragraph 1 in 25.2 [ranges.syn]:

    [Drafting note: The following does not define an analog _to-signed-like_ for _to-unsigned-like_since we don't need it at this time.]
    -?- Also within this Clause,_make-signed-like-t_<X>for an integer-like type Xdenotes make_signed_t<X>if X is an integer type; otherwise, it denotes a corresponding unspecified signed-integer-like type of the same width as X.

  2. Modify 25.3.11 [range.prim.ssize] as indicated:

    -1- The name ranges::ssize denotes a customization point object (16.3.3.3.5 [customization.point.object]).The expression ranges::ssize(E)for a subexpression E of type Tis expression-equivalent to:

    (1.1) — If range_difference_t<T> has width less than ptrdiff_t,static_cast<ptrdiff_t>(ranges::size(E)).

    (1.2) — Otherwise,static_cast<range_difference_t<T>>(ranges::size(E)).

    -?- Given a subexpression E with type T, let t be an lvalue that denotes the reified object for E. If ranges::size(t) is ill-formed,ranges::ssize(E) is ill-formed. Otherwise let D be_make-signed-like-t_<decltype(ranges::size(t))>, or ptrdiff_t if it is wider than that type;ranges::ssize(E) is expression-equivalent tostatic_cast<D>(ranges::size(t)).