【问题标题】:Polymorphic functors in std::for_eachstd::for_each 中的多态函子
【发布时间】:2010-09-18 03:53:37
【问题描述】:

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

干杯,

戴夫

【问题讨论】:

    标签: c++ stl polymorphism


    【解决方案1】:

    您可以使用来自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 成员变量)变得更具可读性。

    【讨论】:

    • 好答案,我从他的例子中不清楚,但如果向量包含整数,他是否还需要将“this 指针”绑定到那个 mem_fun?
    • 否,因为 this 指针将作为参数传递给 for_each。成员函数指针将处理虚拟查找。
    • 无法理解为什么这得到的票数比正确答案多;它不适用于请求的仿函数对象。
    【解决方案2】:

    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 支持之前,此代码可能无法编译。

    【讨论】:

    • 看起来我在 FunctorAdapter 中实现了与 tr1::ref 返回的 reference_wrapper 非常相似的东西。
    【解决方案3】:

    【讨论】:

      【解决方案4】:

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

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

      【讨论】:

        【解决方案5】:

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

        【讨论】:

          【解决方案6】:

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-03-19
            • 2012-04-16
            • 1970-01-01
            相关资源
            最近更新 更多