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

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

Section: 26.3.11 [range.prim.ssize] Status: WP Submitter: Jonathan Wakely Opened: 2020-02-19 Last modified: 2020-11-09

Priority: 2

View all issues with WP 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 requires `ranges::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_t` or `decltype(ranges::size(E))`. Then `ranges::ssize(E)` is expression-equivalent to `static_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 26.2 [ranges.syn]:

>    > -?- Also within this clause, `make-signed-like-t<X>` for an integer-like type `X` denotes `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 26.3.11 [range.prim.ssize] as indicated:

>    > -1- The name `ranges::ssize` denotes a customization point object (16.3.3.3.6 [customization.point.object]). The expression `ranges::ssize(E)` for a subexpression `E` of type `T` is 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 of `ptrdiff_t` or `decltype(ranges::size(t))`; `ranges::ssize(E)` is expression-equivalent to `static_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 26.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 `X` denotes `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 26.3.11 [range.prim.ssize] as indicated:

   > -1- The name `ranges::ssize` denotes a customization point object (16.3.3.3.6 [customization.point.object]). The expression `ranges::ssize(E)` for a subexpression `E` of type `T` is 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 to `static_cast<D>(ranges::size(t))`.