你能 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 包裹它。预计会发生什么?
- 不编译。
- 编译但可能因内存损坏而崩溃
- 按预期工作
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)};
}
这可能是普遍的。
现在我找不到任何支持 "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 包裹它。预计会发生什么?
- 不编译。
- 编译但可能因内存损坏而崩溃
- 按预期工作
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)};
}
这可能是普遍的。