Now I can't find any compiler yet that has this support for the "one ranges proposal" so this is more of an academic question. I'm curious if the following will work like I expect
#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;
}
}
with an expected output of
5
4
3
2
1
The question has to do with the ownership semantics of the range adaptors. I say I want to move a and then wrap it with a view. What is expected to happen?
Can you return range based views from functions in c++2a?
You can.
But returning view to a local variable or temporary would be useless since behaviour of accessing through the view to the destroyed object would be undefined. Same as returning an iterator, pointer or a reference.
I say I want to move a and then wrap it with a view. What is expected to happen?
At least going by what ranges-v3 does, it static asserts that the operand is an lvalue, which fails the compilation.
Views in range-v3/C++20 ranges are non-owning by design. reverse
is always going to be non-owning, so returning that directly to a local range is going to dangle. There's no "owning view" concept in the library.
You can do it by hand though, by writing a custom type that has both the container and the view as members:
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)};
}
This could probably be generalized.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With