我有一个双层对象结构,其中包含的对象具有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<>
模板内部的元编程。
答案 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
对象,与模板版本相比,这将带来很小的开销。