0

我有一个两层对象结构,其中包含的对象有一个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<>模板内正在进行的元编程。

4

2 回答 2

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); });
    }
};
于 2012-06-01T22:21:53.687 回答
0

async_wait可以使用任何可以使用参数调用的可调用类型来调用asio 计时器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::functionwith 可以保存正确签名的任何可调用对象:

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由于构造对象,与模板版本相比,这将具有较小的开销。

于 2012-06-02T02:59:42.467 回答