您可以从c ++ 2a中的函数返回基于范围的视图吗?

bra*_*ing 3 c++ c++20

现在,我找不到任何支持“一个范围建议”的编译器,因此这更多是一个学术问题。我很好奇以下各项是否能按预期工作

#include <iostream>
#include <vector>
#include <ranges>

auto Foo (){
    std::vector<int> a = {1,2,3,4,5};
    return std::move(a) | std::reverse;
}


int  main(){
   for(auto a : Foo()){
       std::cout << a << std::endl;
   }
}
Run Code Online (Sandbox Code Playgroud)

预期输出为

5
4
3
2
1
Run Code Online (Sandbox Code Playgroud)

这个问题与范围适配器的所有权语义有关。我说我想先移动a然后将其包装成一个视图。预计会发生什么?

  1. 不编译。
  2. 编译但可能因内存损坏而崩溃
  3. 按预期工作

eer*_*ika 5

您可以从c ++ 2a中的函数返回基于范围的视图吗?

您可以。

但是将视图返回到局部变量或临时视图将是无用的,因为通过视图访问被破坏对象的行为是不确定的。与返回迭代器,指针或引用相同。

我说我想移动一个,然后将其包装成一个视图。预计会发生什么?

至少按照range-v3的操作,它会静态断言该操作数是一个左值,这会使编译失败。


Bar*_*rry 5

range-v3/C++20 范围内的视图在设计上是非拥有的。reverse始终是非拥有的,因此将其直接返回到本地范围将会悬而未决。图书馆里没有“拥有视图”的概念。

不过,您可以通过编写将容器和视图作为成员的自定义类型来手动完成此操作:

auto Foo() {
    std::vector<int> a = {1, 2, 3, 4, 5};

    struct X {
        std::vector<int> a;
        decltype(a | views::reverse) view = a | views::reverse;

        // plus copy/move ctor/assignment

        auto begin() { return view.begin(); }
        auto end()   { return view.end(); }
    };
    return X{std::move(a)};
}
Run Code Online (Sandbox Code Playgroud)

这也许可以概括。

  • 但复制该类型是危险的。 (3认同)