Question

I'm trying to use stl algorithm for_each without proliferating templates throughout my code. std::for_each wants to instantiate MyFunctor class by value, but it can't since its abstract. I've created a functor adapter class which passes a pointer around and then derefernces it when appropriate.

My Question:

Does the STL or Boost already have such an adapter class? I don't want to have to reinvent the wheel!

 struct MyFunctor  {
     virtual ~MyFunctor() {}
     virtual void operator()(int a) = 0; 
 }

 namespace {
     template<typename FunctorType, typename OperandType> struct
 FunctorAdapter
     {
         FunctorAdapter(FunctorType* functor) : mFunctor(functor) {}
         void operator()(OperandType& subject)
         {
             (*mFunctor)(subject);
         }

         FunctorType* mFunctor;
     }; }

 void applyToAll(MyFunctor &f) {
     FunctorHelper<MyFunctor, int> tmp(&f);
     std::for_each(myvector.begin(), myvector.end(), tmp); }

Cheers,

Dave

Was it helpful?

Solution

tr1::ref may help you here --- it's meant to be a reference wrapper so that you can pass normal objects by reference to bind or function objects (even abstract ones) by reference to standard algorithms.

// requires TR1 support from your compiler / standard library implementation
#include <functional>

void applyToAll(MyFunctor &f) {
    std::for_each(
        myvector.begin(), 
        myvector.end(), 
        std::tr1::ref(f) 
    ); 
}

However, NOTE that compilers without decltype support MAY reject passing a reference to an abstract type... so this code may not compile until you get C++0x support.

OTHER TIPS

You could use the function adapters (and their shims) from functional.

#include <functional>

using namespace std;
for_each( vec.begin(), vec.end(), :mem_fun_ptr( &MyClass::f ) );

If your container contains pointers-to-objects, use mem_fun_ptr, else use mem_fun. Next to these, there are wrappers for member functions that take 1 argument: mem_fun1_ptr and mem_fun1.

@Evan: indeed, you could call the member function with the same argument for each object. The first argument of the mem_fun1 wrappers is the this pointer, the second is the member function argument:

for_each( vec.begin(), vec.end(), bind2nd( mem_fun_ptr( &MyClass::f ), 1 ) );

With more arguments, it becomes more readable to create a loop yourself, or create a custom functor that has const member variables representing the arguments.

Sounds like you could benefit from Boost::Function.

If I remember correctly it's a header only library too, so it's easy to get it going with it.

What about forgetting all the wrapping of the functor pointer, and instead use bind(functor_pointer,mem_fun1(&MyFunctor::operator()); as the functor? that way, you don't have to worry about managing the copy in any way shape or form.

Building on @xtofl's answer, since the array contains int's and not "this" pointers, I think the correct incantation is

class MyClass
{
  virtual void process(int number) = 0;
};
MyClass *instance = ...;

for_each( vec.begin(), vec.end(), binder1st(instance, mem_fun_ptr(&MyClass::process) );

The only difference versus @xtofl's code is binder1st rather than binder2nd. binder2nd allows you to pass teh same number to various "this" pointers. binder1st allows you to pass various numbers to one "this" pointer.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top