Title
Unsigned integer types don't model advanceable
Status
c++23
Section
[range.iota.view]
Submitter
Jiang An

Created on 2021-09-23.00:00:00 last changed 4 months ago

Messages

Date: 2022-11-17.00:42:33

Proposed resolution:

This wording is relative to N4917.

  1. Modify [range.iota.view] as indicated:

    constexpr explicit iota_view(W value);

    -6- Preconditions: Bound denotes unreachable_sentinel_t or Bound() is reachable from value. When W and Bound model totally_ordered_with, then bool(value <= Bound()) is true.

    -7- Effects: Initializes value_ with value.

    constexpr iota_view(type_identity_t<W> value, type_identity_t<Bound> bound);

    -8- Preconditions: Bound denotes unreachable_sentinel_t or bound is reachable from value. When W and Bound model totally_ordered_with, then bool(value <= bound) is true.

    -9- Effects: Initializes value_ with value and bound_ with bound.

Date: 2022-11-12.00:00:00

[ 2022-11-12 Approved at November 2022 meeting in Kona. Status changed: Voting → WP. ]

Date: 2022-10-15.00:00:00

[ 2022-10-19; Reflector poll ]

Set status to "Tentatively Ready" after seven votes in favour in reflector poll.

Date: 2022-10-15.00:00:00

[ 2022-10-12; Jonathan provides wording ]

Date: 2021-10-14.11:35:36

[ Tim Song commented: ]

The advanceable part of the issue is NAD. This is no different from NaN and totally_ordered, see [structure.requirements]/8.

The part about iota_view<uint8_t, uint8_t>(1) is simply this: when we added "When W and Bound model ..." to [range.iota.view]/8, we forgot to add its equivalent to the single-argument constructor. We should do that.

Date: 2021-10-15.00:00:00

[ 2021-10-14; Reflector poll ]

Set priority to 3 after reflector poll.

Date: 2021-09-23.00:00:00

Unsigned integer types satisfy advanceable, but don't model it, since

every two values of an unsigned integer type are reachable from each other, and modular arithmetic is performed on unsigned integer types,

which makes the last three bullets of the semantic requirements of advanceable ([range.iota.view]/5) can't be satisfied, and some (if not all) uses of iota_views of unsigned integer types ill-formed, no diagnostic required.

Some operations that are likely to expect the semantic requirements of advanceable behave incorrectly for unsigned integer types. E.g. according to [range.iota.view]/6 and [range.iota.view]/16, std::ranges::iota_view<std::uint8_t, std::uint8_t>(std::uint8_t(1)).size() is well-defined IMO, because

Bound() is std::uint8_t(0), which is reachable from std::uint8_t(1), and not modeling advanceable shouldn't affect the validity, as both W and Bound are integer types.

However, it returns unsigned(-1) on common implementations (where sizeof(int) > sizeof(std::uint8_t)), which is wrong.

Perhaps the semantic requirements of advanceable should be adjusted, and a refined definition of reachability in [range.iota] is needed to avoid reaching a from b when a > b (the iterator type is also affected).

History
Date User Action Args
2023-11-22 15:47:43adminsetstatus: wp -> c++23
2022-11-17 00:42:33adminsetmessages: + msg13048
2022-11-17 00:42:33adminsetstatus: voting -> wp
2022-11-08 03:46:49adminsetstatus: ready -> voting
2022-10-19 20:27:16adminsetmessages: + msg12878
2022-10-19 20:27:16adminsetstatus: new -> ready
2022-10-12 20:23:18adminsetmessages: + msg12868
2022-10-12 20:23:18adminsetmessages: + msg12867
2021-10-14 11:35:36adminsetmessages: + msg12154
2021-10-14 11:35:36adminsetmessages: + msg12153
2021-09-23 00:00:00admincreate