I'm using the ranges library to help filer data in my classes, like this:
class MyClass
{
public:
MyClass(std::vector<int> v) : vec(v) {}
std::vector<int> getEvens() const
{
auto evens = vec | ranges::views::filter([](int i) { return ! (i % 2); });
return std::vector<int>(evens.begin(), evens.end());
}
private:
std::vector<int> vec;
};
In this case, a new vector is constructed in the getEvents() function. To save on this overhead, I'm wondering if it is possible / advisable to return the range directly from the function?
class MyClass
{
public:
using RangeReturnType = ???;
MyClass(std::vector<int> v) : vec(v) {}
RangeReturnType getEvens() const
{
auto evens = vec | ranges::views::filter([](int i) { return ! (i % 2); });
// ...
return evens;
}
private:
std::vector<int> vec;
};
If it is possible, are there any lifetime considerations that I need to take into account?
I am also interested to know if it is possible / advisable to pass a range in as an argument, or to store it as a member variable. Or is the ranges library more intended for use within the scope of a single function?
In c++23, you can use std::generator and co_yield std::ranges::elements_of
class MyClass
{
public:
MyClass(std::vector<int> v) : vec(v) {}
std::generator<int> getEvens() const
{
auto evens = vec | std::ranges::views::filter([](int i) { return ! (i % 2); });
co_yield std::ranges::elements_of(evens);
}
private:
std::vector<int> vec;
};
int main() {
MyClass mc{{1,2,3,4,5,6,7,8,9}};
for (int i : mc.getEvens()) {
std::cout << i << '\n';
}
}
Working demo (GCC 13.1 without std::ranges::elements_of): https://godbolt.org/z/oehd59oEz
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With