Title
iota_view::size and the most negative signed integer values
Status
new
Section
[range.iota.view]
Submitter
Jiang An

Created on 2021-10-01.00:00:00 last changed 30 months ago

Messages

Date: 2021-10-14.11:35:36

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

  1. Modify [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

  1. Modify [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: […]

Date: 2021-10-15.00:00:00

[ 2021-10-14; Reflector poll ]

Set priority to 3 after reflector poll.

Date: 2021-10-01.00:00:00

According to [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.

History
Date User Action Args
2021-10-14 11:35:36adminsetmessages: + msg12170
2021-10-03 16:07:24adminsetmessages: + msg12099
2021-10-01 00:00:00admincreate