是否可以/建议返回一个范围?

Lia*_*cre 10 c++ range-v3 c++20

我正在使用范围库来帮助我的类中的文件管理器数据,如下所示:

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;
};
Run Code Online (Sandbox Code Playgroud)

在这种情况下,函数中构造了一个新向量getEvents()。为了节省这种开销,我想知道是否可以/建议直接从函数返回范围?

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;
};
Run Code Online (Sandbox Code Playgroud)

如果可能的话,我是否需要考虑任何终生注意事项?

我也有兴趣知道是否可以/建议将范围作为参数传递,或将其存储为成员变量。或者范围库更适合在单个函数的范围内使用?

小智 5

在 c++23 中,您可以使用std::generatorco_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';
    }
}
Run Code Online (Sandbox Code Playgroud)

工作演示(GCC 13.1 不带std::ranges::elements_of):https ://godbolt.org/z/oehd59oEz


j5w*_*j5w 2

标准中对STL组件的使用没有限制。当然,有一些最佳实践(例如,string_view代替string const &)。

在这种情况下,我可以预见直接处理视图返回类型不会出现问题。也就是说,最佳实践尚未确定,因为该标准太新,而且还没有编译器具有完整的实现。

在我看来,你可以选择以下内容:

class MyClass
{
public:
    MyClass(std::vector<int> v) : vec(std::move(v)) {}

    auto getEvens() const
    {
        return vec | ranges::views::filter([](int i) { return ! (i % 2); });
    }

private:
    std::vector<int> vec;
};
Run Code Online (Sandbox Code Playgroud)