如何传递然后调用泛型回调函数而不会导致循环依赖

时间:2009-02-23 16:22:04

标签: c++ boost callback

无法创造性地缩短标题:)

我一直在使用以下解决方案的变体,但我总是想知道是否有更好/更清洁的方法来实现它。我正在寻找非增压解决方案。但是,我们可以看一下boost和C ++ 0x的实现,因为它很快就会相关。

//Notice the use of template template parameter
template <template <typename> class Callback>   
class A {
   Callback <A> m_func;
   public:
     A (Callback <A>  func):  m_func (func) {}
     void call () { m_func(*this);}

};

template <typename T>
struct MYCallback
{
   void operator () (const T&t) {}

};


void Test()
{
   typedef A<MYCallback> AType;

   MYCallback<AType> callback;
   AType a (callback);
   a.call ();

}

另一种更加阳刚的方式是使用tr1 :: function,它将成为 通过新的标准化来解决问题:

#include <tr1/functional>


class A {
   std::tr1::function <void (const A&)>  m_func;
   public:
     template <class Callback>
     A (Callback func) :  m_func (func) {}

     void call () { m_func(*this);}

};

template <class T>
struct My_callback
{
   void operator () (const T&t) {}

};

void Test ()
{
   My_callback <A> c;
   A a (c);
   a.call ();
}

3 个答案:

答案 0 :(得分:1)

我总是相信,当你在这些事情中想要优雅时,无效*就是你的朋友。

答案 1 :(得分:0)

你能做到的一种方法是使用派生类:

template <class Callback>   
class A {
   Callback m_func;
   public:
     A (Callback  func):  m_func (func){}
     void call () { m_func(*this);}

};

template <typename T>
struct MYCallback
{
   void operator () (const T&t) {}

};


struct AConcrete : public A<MYCallback<AConcrete> >
{
  template <class T>
  AConcrete(T t): A<MYCallback<AConcrete> > (t) {}
};

void Test()
{

   MYCallback<AConcrete> callback;
   AConcrete a (callback);
   a.call ();

}

PS:使用C ++模板进行递归很难。

答案 2 :(得分:0)

如果您只是在寻找清理建议,我建议将'My_callback'作为普通类,而不是类模板。在这种情况下,没有明显需要它成为模板。相反,如果My_callback仅处理A实例,则将其apply运算符模板化或直接填入A:

#include <tr1/functional>

class A {
   std::tr1::function <void (const A&)>  m_func;
   public:
     template <class Callback>
     A (Callback func) :  m_func (func) {}

     void call () { m_func(*this);}

};

struct My_callback
{
   template <class T>
   void operator () (const T&t) {}
};

int main ()
{
   My_callback c;
   A a (c);
   a.call ();
}

否则,它看起来很不错。您是否可以更具体地了解如何清理或简化它?