Reputation: 2060
OrderProcessor::ProcessRange
function in the code below accepts a range as an argument and iterates over it. When I try to call it with a range constructed with std::views::filter
it does not compile, but when I copy and paste OrderProcessor::ProcessRange
function implementation into the code it compiles:
#include <iostream>
#include <ranges>
#include <vector>
namespace data
{
struct Order
{
};
}
namespace app
{
template <class R, class Value>
concept range_over = std::ranges::range<R> &&
std::same_as<std::ranges::range_value_t<R>, Value>;
class OrderProcessor
{
public:
void Process(const data::Order&) {}
template <range_over<data::Order> Range>
void ProcessRange(const Range& range)
{
for (const data::Order& order : range)
{
Process(order);
}
}
};
}
int main()
{
using namespace app;
std::vector<data::Order> sample_orders;
auto range = sample_orders | std::views::filter([](const data::Order&) -> bool { return true; });
OrderProcessor processor;
processor.ProcessRange(range); //-does not compile
//But the following loop compiles:
//for (const data::Order& order : range)
//{
// processor.Process(order);
//}
}
it also compiles if I remove std::views::filter
, what can be the difference?
GCC errors:
prog.cc: In instantiation of 'void app::OrderProcessor::ProcessRange(const Range&) [with Range = std::ranges::filter_view<std::ranges::ref_view<std::vector<data::Order> >, main()::<lambda(const data::Order&)> >]' :
prog.cc : 51 : 27 : required from here
prog.cc : 32 : 13 : error : passing 'const std::ranges::filter_view<std::ranges::ref_view<std::vector<data::Order> >, main()::<lambda(const data::Order&)> >' as 'this' argument discards qualifiers[-fpermissive]
32 | for (const data::Order& order : range)
| ^ ~~
In file included from prog.cc : 2 :
/ opt / wandbox / gcc - 11.1.0 / include / c++ / 11.1.0 / ranges : 1307 : 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<std::vector<data::Order> >; _Pred = main()::<lambda(const data::Order&)>]'
1307 | begin()
| ^ ~~~~
prog.cc : 32 : 13 : error : passing 'const std::ranges::filter_view<std::ranges::ref_view<std::vector<data::Order> >, main()::<lambda(const data::Order&)> >' as 'this' argument discards qualifiers[-fpermissive]
32 | for (const data::Order& order : range)
| ^ ~~
In file included from prog.cc : 2 :
/ opt / wandbox / gcc - 11.1.0 / include / c++ / 11.1.0 / ranges : 1321 : 7 : note : in call to 'constexpr auto std::ranges::filter_view<_Vp, _Pred>::end() [with _Vp = std::ranges::ref_view<std::vector<data::Order> >; _Pred = main()::<lambda(const data::Order&)>]'
1321 | end()
| ^ ~~
Upvotes: 1
Views: 63
Reputation: 131554
You just need to drop the const
on the range argument to ProcessOrder()
. A range may change when you iterate it - and apparently that's true for the filter view. Perhaps the library or the compiler could have guessed otherwise, but they don't.
Without the const
- it compiles: https://godbolt.org/z/MnEczfTjG
Also note that if you make the range
variable const to begin with, you'll be in trouble with your loop as well.
Upvotes: 1