This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of New status.
Section: 26.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 26.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.
I believe that we can simply convert 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 26.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 26.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: […]