std :: for_each中的多态仿函数

时间:2008-10-20 16:53:19

标签: c++ stl polymorphism

我正在尝试使用stl算法for_each而不会在我的代码中扩散模板。 std :: for_each想要按值实例化MyFunctor类,但它不能自抽象。我创建了一个functor适配器类,它传递一个指针,然后在适当的时候将其转发。

我的问题:

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

干杯,

戴夫

6 个答案:

答案 0 :(得分: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:的确,您可以使用每个对象的相同参数调用成员函数。 mem_fun1包装器的第一个参数是this指针,第二个是成员函数参数:

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

使用更多参数,自己创建一个循环变得更具可读性,或者创建一个具有表示参数的const成员变量的自定义函子。

答案 1 :(得分:4)

tr1 :: ref可以在这里帮助你 - 它应该是一个参考包装器,这样你就可以通过参考标准算法引用普通对象来引用绑定或函数对象(甚至是抽象对象)。

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

但是,请注意,没有decltype支持的编译器 MAY 拒绝传递对抽象类型的引用...所以在您获得C ++ 0x支持之前,此代码可能无法编译。

答案 2 :(得分:0)

如何忘记仿函数指针的所有包装,而是使用 bind(functor_pointer,mem_fun1(&MyFunctor::operator());  作为函子?这样,您就不必担心以任何形式或形式管理副本。

答案 3 :(得分:0)

答案 4 :(得分:0)

听起来你可以从Boost::Function中受益。

如果我没记错的话,它也是一个仅限标题的库,所以很容易理解它。

答案 5 :(得分:0)

基于@ xtofl的答案,因为数组包含int而不是“this”指针,我认为正确的咒语是

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

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

与@ xtofl代码的唯一区别是binder1st而不是binder2nd。 binder2nd允许您将相同的数字传递给各种“this”指针。 binder1st允许您将各种数字传递给一个“this”指针。