Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible / advisable to return a range?

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?

like image 860
Liam Goodacre Avatar asked Feb 10 '26 00:02

Liam Goodacre


1 Answers

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

like image 150
Ender-events Avatar answered Feb 12 '26 16:02

Ender-events