Why does std::views::take not yield a sized_range?

43 views Asked by At

I’m using C++23. I have a function do_something that needs a std::ranges::sized_range, i.e. the size of the range should be known in constant time.

#include <ranges>
#include <vector>


void do_something(std::ranges::sized_range auto& r);

void doesnt_work() {
    auto range = std::views::iota(0) | std::views::take(42);
    do_something(range);
}

(Compiler Explorer)

Why does std::views::take not yield a std::ranges::sized_range?

If I copy the elements into a vector, it works.

#include <ranges>
#include <vector>


void do_something(std::ranges::sized_range auto& r);

void works() {
    auto range = std::views::iota(0) | std::views::take(42);
    auto container = range | std::ranges::to<std::vector>();
    do_something(container);
}

I don’t want to copy the elements of the range into a container (like std::vector), because the function do_something also copies the elements. I don’t want to copy them twice.

1

There are 1 answers

0
Caleth On BEST ANSWER

sized_range is a stronger requirement than it can provide.

The sized_range concept specifies the requirements of a range type that knows its size in constant time with the size function.

It would be incorrect to just report the take parameter, because the underlying range could be smaller. So size is called on the underlying range. This means that take_view can only be a sized_range if the underlying range is one too.

Hypothetically, there could be a concept infinite_range, and applying take to such a range would be sized, but that isn't how it was specified.