views:

233

answers:

1

Given a functor appropriate for use with std::for_each and friends:

template <typename T> struct Foo {
    void operator()(T const& t) { ... }
};

std::for_each(v.begin(), v.end(), Foo<Bar>());

Is there some standard way to convert this into an output iterator appropriate for use with std::copy and friends? (or the opposite adaptation) Something like:

std::copy(v.begin(), v.end(), functor_output_iterator(Foo<Bar>()));

Which would call the functor each time a value is assigned to the iterator:

adapter(F f) : functor(f) { }
adapter& operator*()  { return *this; }
operator=(T const& t) { functor(t); }
operator++()          { }
...

Or, alternatively:

std::for_each(..., some_adapter(std::ostream_iterator(std::cout)));

Background:

I have a class that exposes a collection using an output iterator:

template <typename It> GetItems(It out) {
    MutexGuard guard(mutex);
    std::copy(items.begin(), items.end(), out);
}

This allows callers to get access to the items without forcing them to use a specific container type and without messing around with locking or other internal details.

e.g., to get only unique items:

std::set<whatever> set;
obj->GetItems(std::inserter(set, set.end()));

This beats the hell out of:

ObjLock lock = obj->GetLock();
for (int i = 0; i < obj->GetItemCount(); ++i) {
    Item* item = obj->GetItem(i);
    ...

Now I also want to be able to aggregate these items, rather than copying them. (See this question). Where I would normally do something like:

std::for_each(v.begin(), v.end(), Joiner<Foo>());

Now I could make two separate methods for the same data elements, one that calls std::copy and one that calls std::for_each but it would be nice to be able to define just one such method, using an iterator or a functor, and have callers be able to pass either functors or iterators to it, adapting them as necessary to the appropriate type.

What I'm doing now is defining the aggregator in such a way that it can be used as either an output iterator or a functor, but this leads to unwanted complexity.

+3  A: 

How about boost::function_output_iterator?

villintehaspam
Okay, that's just embarrassing. I looked right at the boost iterator docs, and apparently skipped right over that. I guess I was looking for "functor" and nothing else.
Tim Sylvester