c++ - asio 定时器的参数 async_wait 差异 lambda、bind、函数指针
问题描述
当我使用时,我发现, ,boost::asio::steady_timer
之间有些不同。lambda
bind
function pointer
#include <iostream>
#include <boost/asio.hpp>
void print() { std::cout << "Hello, world!" << std::endl; }
int main()
{
boost::asio::io_context io;
boost::asio::steady_timer t(io, boost::asio::chrono::seconds(5));
t.async_wait(&print); // Error
t.async_wait([]{print();}) // Error
t.async_wait(std::bind(print)); // Done
io.run();
return 0;
}
我阅读了 asio 手册,async_wait 处理程序需要const boost::system::error_code& error
参数。因此,如果我更改print
为void print(const boost::system::error_code & /*e*/)
,则一切正常。但是 asio 的timer4/timer.cc
&&timeouts/server.cc
使用的处理程序的例子是通过绑定创建的,而没有void print(const boost::system::error_code & /*e*/)
. 当我更改为 lambda 时,编译错误。那么,bind && lambda 之间的签名有什么区别。
#include <iostream>
#include <functional>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
class printer
{
public:
printer(boost::asio::io_context &io)
: timer_(io, boost::asio::chrono::seconds(1)), count_(0)
{
timer_.async_wait(std::bind(&printer::print, this));
}
~printer() { std::cout << "Final count is " << count_ << std::endl; }
void print()
{
if (count_ < 5) {
std::cout << count_ << std::endl;
++count_;
timer_.expires_at(timer_.expiry() +
boost::asio::chrono::seconds(1));
timer_.async_wait(boost::bind(&printer::print, this));
// timer_.async_wait([this]{print();}); Error
}
}
private:
boost::asio::steady_timer timer_;
int count_;
};
int main()
{
boost::asio::io_context io;
printer p(io);
io.run();
return 0;
}
解决方案
通过std::bind
检测并忽略调用点提供的参数而不是显式连接到绑定代码的“部分”。
一个简约的例子(godbolted):
#include <functional>
#include <iostream>
void callme(std::function<void(int, float)> arg) {
arg(42, 4.2);
}
// or like this
// template <typename F> void callme(F&& arg) {
// arg(42, 4.2);
// }
int main()
{
auto fn = std::bind([](){std::cout << "hi there" << std::endl; });
// auto fn = std::bind([](auto&& x){std::cout << "x=" << x << std::endl; }, std::placeholders::_1); <-- this works too and prints 42
// auto fn = std::bind([](auto&& x){std::cout << "x=" << x << std::endl; }, std::placeholders::_2); <-- and works too and prints 4.2
callme(fn);
return 0;
}