asio计时器的参数async_wait差异lambda,绑定,函数指针

时间:2018-09-19 08:42:26

标签: c++ c++11 boost c++14 asio

使用boost::asio::steady_timer时,发现lambdabindfunction 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*/),那么一切都正确。但是timer4/timer.cc和&timeouts/server.cc的asio示例使用了不带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;
}

1 个答案:

答案 0 :(得分: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;
}