代码之家  ›  专栏  ›  技术社区  ›  Robinson

模板化boost::bind以自动处理成员函数的多个参数

  •  3
  • Robinson  · 技术社区  · 14 年前

    我有一个带有“attach”函数的类,它接受一个函数对象并将其存储到一个集合中。类本身在函数签名上模板化。像这样:

    template<class Signature>
    class Event
    {
    public:
    
     void Attach(boost::function<Signature> signature)
     {
      MySignatures.push_back(signature);
     }
    
    private:
    
     std::list<boost::function<Signature>> MySignatures;
    };
    

    要演示用法,请考虑以下类:

    
    class Listening
    {
    public:
    
     int SomeFunction(int x, int y, int z); 
    };
    

    传递函数 Listening 进入之内 Event ,我需要写:

    
     Event<int(int, int, int)> myEvent;
     Listening myListening;
    
     myEvent.Attach(boost::bind(boost::mem_fn(&Listening::SomeFunction), &myListening, _1, _2, _3));
    

    因此,我编写了一组宏,如下所示,而不是针对可能出错的每种情况:

    
     #define EventArgument0(x, y)  boost::bind(boost::mem_fn(x), y)
     #define EventArgument1(x, y)  boost::bind(boost::mem_fn(x), y, _1)
     #define EventArgument2(x, y)  boost::bind(boost::mem_fn(x), y, _1, _2)
     #define EventArgument3(x, y)  boost::bind(boost::mem_fn(x), y, _1, _2, _3)
     #define EventArgument4(x, y)  boost::bind(boost::mem_fn(x), y, _1, _2, _3, _4)
    
     etc.
    

    然后我可以写:

    
     myEvent.Attach(EventArgument3(&Listening::SomeFunction, &myListening));
    

    这本书更容易读(我想)。现在我的问题是:我怎样才能写:

    
     myEvent.Attach(EventArgument(&Listening::SomeFunction, &MyListening));
    

    甚至更好:

    
     myEvent.Attach(&Listening::SomeFunction, &myListening);
    

    ,以便事件附加可以使用<signature>(在本例中,为 int(int, int, int) )?我愿意接受您在这里想到的任何模板元编程的魔力。

    谢谢。

    编辑:原来我不需要 boost::mem_fn 这里,因为 boost::bind 是等效的,因此在我的宏中我可以使用:

    bind(&MyClass::Hello, myClass, _1, _2, _3);
    

    ,而不是:

    bind(mem_fn(&MyClass::Hello), myClass, _1, _2, _3);
    

    然而,问题仍然存在:如何通过 &MyClass::Hello 到事件类,并使用模板重载处理 _1 , _2 , _3 等。由用于模板 事件 班级?

    2 回复  |  直到 8 年前
        1
  •  2
  •   Anthony Williams    14 年前

    超载 Attach 对于成员函数中不同数量的参数:

    template<typename R,typename T,typename U>
    void Attach(R (T::*pmf)(),U* p))
    {
        Attach(boost::bind(pmf,p));
    }
    
    template<typename R,typename T,typename U,typename A1>
    void Attach(R (T::*pmf)(A1),U* p))
    {
        Attach(boost::bind(pmf,p,_1));
    }
    
    template<typename R,typename T,typename U,typename A1,typename A2>
    void Attach(R (T::*pmf)(A1,A2),U* p))
    {
        Attach(boost::bind(pmf,p,_1,_2));
    }
    

    如果你需要处理 const 成员函数也需要第二组重载。

        2
  •  2
  •   Nick Strupat    14 年前

    制作 Attach() 一个模板可以让你实现你的目标。代码会变得混乱,但让我们按您想要的方式来命名。

    template<typename A1>
    void Attach(A1 a1);
    
    template<typename A1, typename A2>
    void Attach(A1 a1, A2 a2);
    
    template<typename A1, typename A2, typename A3>
    void Attach(A1 a1, A2 a2, A3 a3);
    
    template<typename A1, typename A3, typename A4>
    void Attach(A1 a1, A2 a2, A3 a3, A4 a4);