
On 10/5/07, François Duranleau <duranlef@iro.umontreal.ca> wrote:
Why boost::function_output_iterator has no accessor to the wrapped function/functor?
In STL, algorithms using an output iterator or a function/functor usually return the iterator or function/functor received in parameter (e.g. std::copy, std::for_each) because they are passed by copy. Then if I use a boost::function_output_iterator, I can get a copy of that iterator in return, but then there is no way to extract the function/functor.
Example: I have a set of points stored in a structure for range query (e.g. a kd-tree). There is a member function to get all points falling inside a given area and it produces its output in an output iterator. Now, suppose I only want to do some computation on those points for which I would actually don't need to store them all, e.g. an average of some kind. I could do the computation on the fly using a boost::function_output_iterator with a functor that accumulates the sum and the number of points and at the end, I would do the division. Alas, I can't unless the functor only keeps reference. I can't do it the classical way I could with std::for_each because I can't access the functor with boost::function_output_iterator.
So, long story just to try to show that it would be useful, or is there some other considerations I didn't see that makes it a bad idea?
In the exact same scenario (except I'm using a Bounding Interval Hierarchy, not a kd-tree), I decided to make a within_if(bounds, output_iterator, predicate), rather than just a within(bounds, output_iterator) because I didn't know of the existance of boost::function_output_iterator. I believe I'll be changing this with my new knowledge. Shouldn't you be able to accomplish what you want following the example at http://www.boost.org/libs/iterator/doc/function_output_iterator.html ? You would have struct averager { averager(float3& p, int &t) : m_avg(&p), m_num(&t) {} void operator()(const float3& rhs) const { *m_avg += rhs; *m_num++; } float3* m_str; int *m_num; }; float3 avg(0, 0, 0); int total = 0; kdtree.within(bounds, boost::make_function_output_iterator(averager(avg, total))); avg /= total; --Michael Fawcett