If I create a view, then it's a range. That seems reasonable.
However, if it's const, then it becomes a non-range:
#include <ranges>
int main()
{
int values[] = { 1, 2, 3 };
auto odd_values = values | std::views::filter([](int i){ return i % 2; });
static_assert(std::ranges::range<decltype(odd_values)>);
auto const odd_ref = odd_values;
static_assert(!std::ranges::range<decltype(odd_ref)>); // WHY NOT?
}
This is surprising - I don't see any reason I shouldn't be able to read the contents, just as I could from, say a const std::vector
.
In case it's an implementation bug, I experienced this with GCC 11, using -std=c++20
; library is libstdc++-11.
If I add a call to std::ranges::begin()
I get plenty of diagnostics, showing it not finding a member function nor anything via ADL, then running up against the backstop deleted function that's there to prevent std::begin
matching.
From the error messages, it seems that we're lacking const versions of begin()
and end()
member functions from the view class. Is that expected, or have they just been missed out?
That led me to a simpler failing example:
#include <ranges>
int main()
{
int values[] = { 1, 2, 3 };
auto const odd_values = values | std::views::filter([](int i){ return i % 2; });
odd_values.begin(); // ERROR HERE
}
view.cpp: In function ‘int main()’:
view.cpp:9:21: error: passing ‘const std::ranges::filter_view<std::ranges::ref_view<int [3]>, main()::<lambda(int)> >’ as ‘this’ argument discards qualifiers [-fpermissive]
9 | odd_values.begin(); // ERROR HERE
| ~~~~~~~~~~~~~~~~^~
In file included from view.cpp:1:
/usr/include/c++/11/ranges:1452:7: note: in call to ‘constexpr std::ranges::filter_view<_Vp, _Pred>::_Iterator std::ranges::filter_view<_Vp, _Pred>::begin() [with _Vp = std::ranges::ref_view<int [3]>; _Pred = main()::<lambda(int)>]’
1452 | begin()
| ^~~~~
So why doesn't the view have const versions of begin()
and end()
?