std::for_each中的多态函子

Polymorphic functors in std::for_each

本文关键字:多态 each for std      更新时间:2023-10-16

我正在尝试使用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); }

干杯,

Dave

您可以使用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 ) );

有了更多的参数,您可以自己创建一个循环,或者创建一个具有表示参数的常量成员变量的自定义函子。

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的编译器可能会拒绝传递对抽象类型的引用。。。因此,在获得C++0x支持之前,此代码可能不会编译。

为什么不使用BOOST_FOREACH?

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

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

如果我没记错的话,它也是一个只有头的库,所以很容易使用它。

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

基于@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"指针。