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?
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With