|
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