你能 return 从 c++2a 中的函数中基于范围的视图吗?

Can you return range based views from functions in c++2a?

现在我找不到任何支持 "one ranges proposal" 的编译器,所以这更像是一个学术问题。我很好奇以下是否会像我预期的那样工作

#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;
   }
}

预期输出为

5
4
3
2
1

问题与范围适配器的所有权语义有关。我说我想移动 a 然后用 view 包裹它。预计会发生什么?

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

Can you return range based views from functions in c++2a?

可以。

但是将视图返回到局部变量或临时变量将毫无用处,因为通过视图访问被销毁对象的行为是未定义的。与返回迭代器、指针或引用相同。

I say I want to move a and then wrap it with a view. What is expected to happen?

至少按照 ranges-v3 的做法,它静态断言操作数是左值,这导致编译失败。

range-v3/C++20 范围内的视图在设计上是非拥有的。 reverse 始终是非拥有的,因此将其直接返回到本地范围将会悬空。库中没有 "owning view" 概念。

不过,您可以手动完成,方法是编写一个同时具有容器和视图作为成员的自定义类型:

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)};
}

这可能是普遍的。