4

First, using Range-v3, I noticed that

std::vector<int> v;
auto w = v | ranges::views::enumerate;
auto [x, y] = *w.begin();
static_assert(std::is_same_v<std::size_t, decltype(x)>);

which makes sense to me because std::size_t is the right type to use for indexing into objects, as far as I've understood.

Then, with C++20 ranges, the static assertion fails. Instead, the following passes,

static_assert(std::is_same_v<long, decltype(x)>);

but long is not the same as std::size_t on my system, where I verified that

static_assert(std::is_same_v<unsigned long, std::size_t>)

On, GCC 13.2.1, here's the example.

Barry
  • 286,269
  • 29
  • 621
  • 977
Enlico
  • 23,259
  • 6
  • 48
  • 102
  • That's going to depend on the type of `v`. – user17732522 Aug 03 '23 at 17:40
  • @user17732522, why does it matter? – Enlico Aug 03 '23 at 17:43
  • Suppose `v` is a container and has `size_type = unsigned short` and `difference_type = short` for memory efficiency reasons because the container type may never hold more elements than fit these types. Then `enumerate` should not produce a much larger type. And the other way around a range's size could be larger than `std::size_t` can hold. A range doesn't need to hold each element in memory at the same time. – user17732522 Aug 03 '23 at 17:45
  • Also, `ranges::views::enumerate` uses `difference_type` for the first element of the tuple, i.e. it produces a signed result. – user17732522 Aug 03 '23 at 17:50
  • @HolyBlackCat, added. – Enlico Aug 03 '23 at 18:03

1 Answers1

4

Does std::ranges::views::enumerate use the wrong type for indexing on GCC?

No.

std::views::enumerate is specified to use range_difference_t<Base> as its index value. gcc implementation is correct to the specification.

On the other hand, range-v3's implementation used make_unsigned<range_difference_t<Base>> as its index value.

Signed seems like a much better choice here, given that you probably want subtraction to be sensible. Although there's no discussion of this choice as far as I can see in P2164 (or any revision thereof).


but long is not the same as std::size_t on my system

long is not the same as std::size_t on any system. long is signed and size_t is unsigned.

Barry
  • 286,269
  • 29
  • 621
  • 977