为什么临时容器对象不能在 range-v3 中进行管道传输?

Why aren't temporary container objects pipeable in range-v3?

为什么是下面的

#include <iostream>
#include <string>
#include <range/v3/all.hpp>

std::vector<int> some_ints() {
    return { 1,2,3,4,5 };
}

int main() {
    auto num_strings = some_ints() |
        ranges::views::transform([](int n) {return std::to_string(n); }) |
        ranges::to_vector;
    
    for (auto str : num_strings) {
        std::cout << str << "\n";
    }

    return 0;
}

一个错误,而

int main() {
    auto ints = some_ints();
    auto num_strings = ints |
        ranges::views::transform([](int n) {return std::to_string(n); }) |
        ranges::to_vector;

    for (auto str : num_strings) {
        std::cout << str << "\n";
    }

    return 0;
}

可以吗?

我希望临时的生命周期延长到整个管道表达式的生命周期,所以我不明白问题出在哪里。

Clang 的错误是

<source>:10:36: error: overload resolution selected deleted operator '|'
    auto num_strings = some_ints() |
                       ~~~~~~~~~~~ ^
/opt/compiler-explorer/libs/rangesv3/0.11.0/include/range/v3/view/view.hpp:153:13: note: candidate function [with Rng = std::vector<int, std::allocator<int>>, ViewFn = ranges::detail::bind_back_fn_<ranges::views::transform_base_fn, (lambda at <source>:11:34)>] has been explicitly deleted
            operator|(Rng &&, view_closure<ViewFn> const &)    // ****** READ THIS *******

从Visual Studio我得到

error C2280: 'std::vector<int,std::allocator<int>> ranges::views::view_closure_base_ns::operator |<std::vector<int,std::allocator<int>>,ranges::detail::bind_back_fn_<ranges::views::transform_base_fn,main::<lambda_1>>>(Rng &&,const ranges::views::view_closure<ranges::detail::bind_back_fn_<ranges::views::transform_base_fn,main::<lambda_1>>> &)': attempting to reference a deleted function
1>        with
1>        [
1>            Rng=std::vector<int,std::allocator<int>>
1>        ]

这两个错误似乎都在说管道操作符被显式删除以用于 r 值引用?

简短的回答是因为他们很懒,| 不转让所有权。

I would expect the lifetime of the temporary to be extended to the lifetime of the whole pipeline expression so I don't understand what the problem is.

是的,这正是会发生的事情,但仅此而已。这意味着一旦代码命中 ;some_ints() 就会死亡,并且 num_strings 现在包含“悬空”范围。所以选择禁止编译这个例子。