Consider the following code snippet (full code: https://godbolt.org/z/PMM4z9KvM):
int main() {
{
std::cout << "begin std::views::as_rvalue\n";
auto iss = std::istringstream("12");
auto is = std::views::istream<X>(iss);
auto _ = is | std::views::as_rvalue | std::ranges::to<std::vector>();
std::cout << "end std::views::as_rvalue\n\n" << std::flush;
}
{
std::cout << "\nbegin my::as_rvalue\n";
auto iss = std::istringstream("12");
auto is = std::views::istream<X>(iss);
auto _ = is | my::as_rvalue | std::ranges::to<std::vector>();
std::cout << "end my::as_rvalue\n\n" << std::flush;
}
}
The output is as follows:
begin std::views::as_rvalue
X()
X(X const&)
X(X&&)
~X()
X(X&&)
X(X&&)
X(X&&)
~X()
~X()
end std::views::as_rvalue
~X()
~X()
~X()
begin my::as_rvalue
X()
X(X&&)
X(X&&)
X(X&&)
~X()
end my::as_rvalue
~X()
~X()
~X()
It seems std::views::as_rvalue has more operations than my::as_rvalue.
Why is std::views::as_rvalue not so cheap as std::move_iterator?
is | views::as_rvalueequalsviews::as_rvalue(is)equalsranges::as_rvalue_view(is). Since isisan lvalue, so there is a copy.AsRvView_will lead to dangling if the input range is not aborrowed_range.AsRvView_only acceptsborrowed_range.vector{...} | views::as_rvalue, orr | views::filter(...) | views::as_rvalue, etc.v | views::filter(...) | my::as_rvaluewill faied evenvis lvalue vector, there is nothing to do withowning_viewfor such cases.