4

我正在尝试使用 stl 算法 for_each 而不会在我的代码中增加模板。std::for_each 想要按值实例化 MyFunctor 类,但它不能因为它的抽象。我创建了一个仿函数适配器类,它传递一个指针,然后在适当的时候取消引用它。

我的问题:

STL 或 Boost 是否已经有这样的适配器类?我不想重新发明轮子!

 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); }

干杯,

戴夫

4

6 回答 6

5

您可以使用来自functional.

#include <functional>

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

如果您的容器包含指向对象的指针,请使用mem_fun_ptr,否则使用mem_fun. 在这些旁边,有成员函数的包装器,它们接受 1 个参数:mem_fun1_ptrmem_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.

于 2008-10-20T17:11:39.020 回答
4

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.

于 2008-10-20T22:52:11.547 回答
0

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.

于 2008-10-20T17:17:11.863 回答
0

why not use BOOST_FOREACH?

http://www.boost.org/doc/libs/1_35_0/doc/html/foreach.html

于 2008-10-20T17:42:39.300 回答
0

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.

于 2008-10-20T17:46:27.030 回答
0

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.

于 2008-10-20T20:59:22.990 回答