Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

boost::function_output_iterator constructed from lambda function is not assignable

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 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.

Hm, ok, this StackOverflow, so I have to ask some question :) Here it is: how to workaround this? How to obtain a correct iterator given a closure, which acts like function_output_iterator?

And another one: does it worth to make a proposal or a bug report to boost?

like image 656
Mikhail Avatar asked Feb 14 '16 14:02

Mikhail


2 Answers

Simply save the closure in a std::function:

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

Test snippet.

like image 166
jrok Avatar answered Oct 25 '22 00:10

jrok


Another option, if you are sure the closure will outlive the iterator and its copies, wrap it with std::ref:

auto f = [](int x) { std::cout << x; };
auto it = boost::make_function_output_iterator(std::ref(f));

Demo.

And here is a proposal for a boost utility class fixing this particular problem: boost::regular

See the corresponding discussion in boost mailing list.

like image 45
Mikhail Avatar answered Oct 24 '22 22:10

Mikhail