为什么 C++23 范围适配器要求可调用对象是可复制构造的?
Why does the C++23 ranges adaptor require a callable object to be copy_constructible?
一些范围适配器,例如filter_view
, take_while_view
and transform_view
use std::optional
's cousin copyable-box
来存储可调用对象:
template<input_range V, copy_constructible F>
class transform_view : public view_interface<transform_view<V, F>> {
private:
V base_ = V();
copyable-box<F> fun_;
};
要求可调用 F
为 copy_constructible
, this also prevents us from passing in the callable that captures the move only object into transform_view
(Godbolt):
#include <ranges>
#include <memory>
struct MoveOnlyFun {
std::unique_ptr<int> x;
MoveOnlyFun(int x) : x(std::make_unique<int>(x)) { }
int operator()(int y) const { return *x + y; }
};
int main() {
auto r = std::views::iota(0, 5)
| std::views::transform(MoveOnlyFun(1));
}
既然 view
不需要是 copy_constructible
,为什么我们要求可调用对象是 copy_constructible
?为什么我们不直接使用 moveable-box
来存储可调用对象而不是 copyable-box
?这背后的考虑是什么?
更新:
最近的提议 P2494R0 也解决了这个问题并提出了详细的解决方案。
所有的算法都需要可复制构造的函数对象,视图基本上是惰性算法。
从历史上看,当添加这些适配器时,视图需要 copyable
,因此我们要求函数对象为 copy_constructible
(我们不能要求 copyable
没有裁定出捕获的 lambdas)。使 view
只需要 movable
的更改稍后出现。
放宽限制是有可能的,但是需要论文,优先级不是很高。
一些范围适配器,例如filter_view
, take_while_view
and transform_view
use std::optional
's cousin copyable-box
来存储可调用对象:
template<input_range V, copy_constructible F>
class transform_view : public view_interface<transform_view<V, F>> {
private:
V base_ = V();
copyable-box<F> fun_;
};
要求可调用 F
为 copy_constructible
, this also prevents us from passing in the callable that captures the move only object into transform_view
(Godbolt):
#include <ranges>
#include <memory>
struct MoveOnlyFun {
std::unique_ptr<int> x;
MoveOnlyFun(int x) : x(std::make_unique<int>(x)) { }
int operator()(int y) const { return *x + y; }
};
int main() {
auto r = std::views::iota(0, 5)
| std::views::transform(MoveOnlyFun(1));
}
既然 view
不需要是 copy_constructible
,为什么我们要求可调用对象是 copy_constructible
?为什么我们不直接使用 moveable-box
来存储可调用对象而不是 copyable-box
?这背后的考虑是什么?
更新:
最近的提议 P2494R0 也解决了这个问题并提出了详细的解决方案。
所有的算法都需要可复制构造的函数对象,视图基本上是惰性算法。
从历史上看,当添加这些适配器时,视图需要 copyable
,因此我们要求函数对象为 copy_constructible
(我们不能要求 copyable
没有裁定出捕获的 lambdas)。使 view
只需要 movable
的更改稍后出现。
放宽限制是有可能的,但是需要论文,优先级不是很高。