boost::function_output_iterator constructed from l

2019-02-06 15:08发布

问题:

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?

回答1:

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.



回答2:

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.