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 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.
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.
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 typeX
denotesmake_signed_t<X>
ifX
is an integer type; otherwise, it denotes a corresponding unspecified signed-integer-like type of the same width asX
.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 expressionranges::ssize(E)
for a subexpressionE
of typeT
is expression-equivalent to:
(1.1) — Ifrange_difference_t<T>
has width less thanptrdiff_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 typeT
, lett
be an lvalue that denotes the reified object forE
. Ifranges::size(t)
is ill-formed,ranges::ssize(E)
is ill-formed. Otherwise, letD
be the wider ofptrdiff_t
ordecltype(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.
Add a new paragraph after paragraph 1 in 25.2 [ranges.syn]:
[Drafting note: The following does not define an analog
to-signed-like
forto-unsigned-like
since we don't need it at this time.]
-?- Also within this Clause,make-signed-like-t<X>
for an integer-like typeX
denotesmake_signed_t<X>
ifX
is an integer type; otherwise, it denotes a corresponding unspecified signed-integer-like type of the same width asX
.
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 expressionranges::ssize(E)
for a subexpressionE
of typeT
is expression-equivalent to:
(1.1) — Ifrange_difference_t<T>
has width less thanptrdiff_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 typeT
, lett
be an lvalue that denotes the reified object forE
. Ifranges::size(t)
is ill-formed,ranges::ssize(E)
is ill-formed. Otherwise letD
bemake-signed-like-t<decltype(ranges::size(t))>
, orptrdiff_t
if it is wider than that type;ranges::ssize(E)
is expression-equivalent tostatic_cast<D>(ranges::size(t))
.