async_wait()处理程序的实际签名

时间:2012-06-01 19:04:25

标签: c++ boost boost-asio boost-bind

我有一个双层对象结构,其中包含的对象具有deadline_timer,外部对象具有处理函数,如:

class Internal
{
    asio::deadline_timer t;
public:
    void QueueTick(void (*handler)(boost::system::error_code const&))
    {
       t.expires_from_now(posix_time::millisec(250));
       t.async_wait(handler);
    }
};

class ForClients
{
    Internal I;
    void OnTick(boost::system::error_code const&) { /*...*/ }
    void Init()
    {
        I.QueueTick(boost::bind(&cdevXcite::OnTick, this, _1));
    }
};

QueueTick()调用无法在MSVS 2008中编译,“无法将参数1从'boost :: _ bi :: bind_t'转换为'void(__cdecl *)(const boost :: system :: error_code& ;)'”

如果我将计时器成员公开并使用相同的参数直接调用I.t.async_wait(),则成功。显然,处理程序的签名比我在QueueTick声明中使用的签名更特殊;但是,我找不到定义它的符号,我不知道如何解释basic_deadline_timer<>模板内部的元编程。

2 个答案:

答案 0 :(得分:0)

如果你可以使用C ++ 11,你可以这样做:

class Internal
{
    asio::deadline_timer t;

public:
    void QueueTick(const std::function<void(const boost::system::error_code&)>& handler)
    {
        t.expires_from_now(posix_time::millisec(250));
        t.async_wait(handler);
    }
};

class ForClients
{
    Internal I;
    void OnTick(const boost::system::error_code& ec) { /*...*/ }
    void Init()
    {
        I.QueueTick([this](const boost::system::error_code& ec) { OnTick(ec); });
    }
};

答案 1 :(得分:0)

可以使用任何可调用类型调用asio定时器async_wait,可以使用boost::system::error_code const&参数调用。在任何地方都没有定义它的单一类型,它只需要用记录的参数类型来调用。

QueueTick参数的类型是一个这样的可调用类型,指向具有正确签名的普通ol'非成员函数的指针:

void QueueTick(void (*handler)(boost::system::error_code const&))

但是boost::bind的结果是一个带有重载operator()的类类型,它不能转换为该函数指针类型。

有几种方法可以解决这个问题,但最简单的方法可能是跟随async_wait本身并将QueueTick写为函数模板,接受任何类型:

class Internal
{
  asio::deadline_timer t;
public:
  template<WaitHandle>
    void QueueTick(WaitHandle handler)
    {
      t.expires_from_now(posix_time::millisec(250));
      t.async_wait(handler);
    }
};

其余代码将保持不变。

如果这不是一个选项(例如因为QueueTick需要是虚拟的)那么你可以使用boost::function来保存任何可以调用正确签名的对象:

class Internal
{
  asio::deadline_timer t;
public:
  typedef boost::function<void(boost::system::error_code const&)> handler_type;
  void QueueTick(handler_type handler)
    {
      t.expires_from_now(posix_time::millisec(250));
      t.async_wait(handler);
    }
};

由于构造boost::function对象,与模板版本相比,这将带来很小的开销。

相关问题