Some ranges adaptors such as filter_view
, take_while_view
and transform_view
use std::optional
's cousin copyable-box
to store the callable object:
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_;
};
which requires the callable F
to be 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));
}
Since the view
is not required to be copy_constructible
, why do we require the callable to be copy_constructible
? why don't we just use moveable-box
to store callable instead of copyable-box
? What are the considerations behind this?
Update:
The recent proposal P2494R0 also addresses this issue and proposes a detailed resolution.