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

Why wrapping call to function returning by value in hana::always circumvent requirements of ranges::views::join? Or maybe it doesn't?

这个函数,输入任何 int,returns a std::vector<int> 按值:

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

所以,这样的事情是行不通的

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

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

但是,以下不会失败:

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

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

我认为下面是两个函数的证明,makealways(make(int{})),return暂时。我是不是搞错了?

static_assert(!std::is_reference_v<decltype(make(int{}))>);
static_assert(!std::is_reference_v<decltype(boost::hana::always(make(int{}))(int{}))>);

Full demo.

有两个不同的问题。

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

  • hana::always returns 不同的事情取决于它是作为左值还是右值调用。它 returns 当作为左值调用时是左值引用,当作为右值调用时是纯右值。 transform 始终作为左值调用,而您的 static_assert 正在检查作为右值调用的结果。