iota_view::size
and the most negative signed integer valuesSection: 25.6.4.2 [range.iota.view] Status: New Submitter: Jiang An Opened: 2021-10-01 Last modified: 2021-10-14
Priority: 3
View all other issues in [range.iota.view].
View all issues with New status.
Discussion:
According to 25.6.4.2 [range.iota.view]/15, when both W
and Bound
are
integer-like, the expression in the return statement uses -value_
and -bound_
.
These operations result in undefined behavior when -
is applied to the most negative integer
value of a promoted type.
value_
and bound_
to the return type
(make-unsigned-like-t<common_type_t<W, Bound>>
) and then perform the subtraction.
Such method should give the same results with UB eliminated.
Additionally, if we decide that iota_view<uint8_t, uint8_t>(uint8_t(1)).size()
is well-defined
(LWG 3597), it should give the correct result. We can truncate the result to fit the type W
.
[2021-10-14; Reflector poll]
Set priority to 3 after reflector poll.
Proposed resolution:
This wording is relative to N4892.
[Drafting Note: Two mutually exclusive options are prepared, depicted below by Option A and Option B, respectively.]
Option A: Just fixes the most negative values
Modify 25.6.4.2 [range.iota.view] as indicated:
constexpr auto size() const requires see below;-15- Effects: Equivalent to:
if constexpr (is-integer-like<W> && is-integer-like<Bound>) {return (value_ < 0) ? ((bound_ < 0) ? to-unsigned-like(-value_) - to-unsigned-like(-bound_) : to-unsigned-like(bound_) + to-unsigned-like(-value_)) : to-unsigned-like(bound_) - to-unsigned-like(value_);using UC = make-unsigned-like-t<common_type_t<W, Bound>>; return UC(bound_) - UC(value_); } else return to-unsigned-like(bound_ - value_);-16- Remarks: […]
Option B: Also fixes pathological cases involving unsigned-integer-like types
Modify 25.6.4.2 [range.iota.view] as indicated:
constexpr auto size() const requires see below;-15- Effects: Equivalent to:
if constexpr (is-integer-like<W> && is-integer-like<Bound>) {return (value_ < 0) ? ((bound_ < 0) ? to-unsigned-like(-value_) - to-unsigned-like(-bound_) : to-unsigned-like(bound_) + to-unsigned-like(-value_)) : to-unsigned-like(bound_) - to-unsigned-like(value_);using UC = make-unsigned-like-t<common_type_t<W, Bound>>; if constexpr (is-signed-integer-like<W>) return UC(bound_) - UC(value_); else return UC(W(UC(bound_) - UC(value_))); } else return to-unsigned-like(bound_ - value_);-16- Remarks: […]