Boost logo

Boost :

Subject: [boost] [iterator] function_output_iterator constructed from a lambda function is not assignable
From: Mikhail Matrosov (mikhail.matrosov_at_[hidden])
Date: 2016-02-14 14:42:00

Consider the following code snippet:

auto f = [](int x) { std::cout << x; };auto it =
boost::make_function_output_iterator(f);decltype(it) it2 = it; // Ok,
it2 = it; // Does not compile, cannot assign!

The problem is, function_output_iterator constructed in this way is not
assignable, and thus does not satisfy the Iterator
<> concept, which requires
type to be CopyAssignable

This is not a bug, since boost Function Output Iterator documentation
 clearly says

UnaryFunction must be Assignable and Copy Constructible.

While assignment operator of a lambda function
<> is deleted:

ClosureType& operator=(const ClosureType&) = delete;

So this behaviour is technically correct, but for me is somewhat
unexpected. I think it is a perfectly reasonable desire to construct
function_output_iterator given a closure produced by lambda function. It
seems inconvenient to me why this use case causes a problem.

Can you suggest a workaround for this situation? Or maybe a way of
improving function_output_iterator to overcome this issue?

Personally, I came up with a trick to fix this in a situation, when I'm
sure iterator and its copies won't outlive the closure object. In this case
we may wrap closure with std::ref:

auto it = boost::make_function_output_iterator(std::ref(f));

This works quite fine, but obviously is not always possible.

Another options is to store closure in std::function:

std::function<void(int)> f = [](int x) { std::cout << x; };

This also works fine and is possible in most contexts, but causes related

See also:

Best regards, Mikhail Matrosov

Boost list run by bdawes at, gregod at, cpdaniel at, john at