为什么在 hana:: 中包装对按值返回的函数的调用总是规避 range::views::join 的要求?或者也许不是?

Enr*_*lis 2 c++ boost-hana c++20 std-ranges

这个函数,输入 any int,返回一个std::vector<int>值:

auto make = [](int){
    return std::vector<int>{1,2,3};
};
Run Code Online (Sandbox Code Playgroud)

因此,这样的事情是行不通的

std::vector<int> v{1,2,3};
auto z = v | std::ranges::views::transform(make)
           | std::ranges::views::join; // fails to compile
Run Code Online (Sandbox Code Playgroud)

因为,我理解(但如果我错了,请纠正我),当迭代器包装在joinadvance 中时,它会通过 触发向量的生成make,但是当迭代器 in 被join取消引用时,这些临时值已经被销毁。

但是,以下操作不会失败:

std::vector<int> v{1,2,3};
auto z = v | std::ranges::views::transform(boost::hana::always(make(int{})))
           | std::ranges::views::join;
Run Code Online (Sandbox Code Playgroud)

这是为什么?使用 引入了什么机制always

我认为以下证明了两个函数make和 都always(make(int{}))返回临时值。我犯错了吗?

static_assert(!std::is_reference_v<decltype(make(int{}))>);
static_assert(!std::is_reference_v<decltype(boost::hana::always(make(int{}))(int{}))>);
Run Code Online (Sandbox Code Playgroud)

完整演示

T.C*_*.C. 5

有两个单独的问题。

  • join_view对纯右值范围连接范围的限制是 C++20 中的缺陷,已由P2328R1纠正。transform(make) | join应该只使用实现缺陷解决方案的标准库(例如 libstdc++ trunk)。

  • hana::always根据它是作为左值还是右值调用,返回不同的内容。当作为左值调用时,它返回左值引用;当作为右值调用时,它返回纯右值。transform始终作为左值调用,而您static_assert正在检查作为右值调用的结果。