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);
}
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.
sized_rangeis a stronger requirement than it can provide.It would be incorrect to just report the
takeparameter, because the underlying range could be smaller. Sosizeis called on the underlying range. This means thattake_viewcan only be asized_rangeif the underlying range is one too.Hypothetically, there could be a concept
infinite_range, and applyingtaketo such a range would be sized, but that isn't how it was specified.