Search code examples
c++language-lawyerstd-rangessize-tc++23

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


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.


Solution

  • 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.