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,
copied
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
<http://en.cppreference.com/w/cpp/concept/Iterator> concept, which requires
type to be CopyAssignable
<http://en.cppreference.com/w/cpp/concept/CopyAssignable>.

This is not a bug, since boost Function Output Iterator documentation
<http://www.boost.org/doc/libs/1_60_0/libs/iterator/doc/function_output_iterator.html>
 clearly says
<http://www.boost.org/doc/libs/1_60_0/libs/iterator/doc/function_output_iterator.html#function-output-iterator-requirements>
:

UnaryFunction must be Assignable and Copy Constructible.

While assignment operator of a lambda function
<http://en.cppreference.com/w/cpp/language/lambda> 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
overheads.

See also: http://stackoverflow.com/q/35392919/261217

-----
Best regards, Mikhail Matrosov


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk