以 boost::bind 作为参数的函数签名(boost::asio 计时器回调)?

Signature for function taking boost::bind as an argument (boost::asio timer callback)?

我正在尝试编写一个包装器方法 set_timer(),它需要时间和回调(使用 boost::bind 表示)并设置一个 deadline_timer 到 运行那个回调。

目前回调非常简单:

void foo::callback(const boost::system::error_code& error) {
    std::cout << "callback" << std::endl;
}

对于 set_timer() 我有:

void foo::set_timer(boost::posix_time::ptime time,
                    boost::function<void(const boost::system::error_code&)> handler) {
    pimpl->t.expires_at(time);
    pimpl->t.async_wait(handler);
}

现在我正尝试从 foo 对象中调用它:

set_timer(boost::posix_time::seconds(1), boost::bind (&foo::callback, this));

编译时的错误信息是:

foo.cpp: In member function ‘void foo::run()’:
foo.cpp:50: error: no matching function for call to ‘foo::set_timer(boost::posix_time::seconds, boost::_bi::bind_t<void (&)(const boost::system::error_code&), boost::_mfi::dm<void(const boost::system::error_code&), foo>, boost::_bi::list1<boost::_bi::value<foo*> > >)’
src/foo_sdr.cpp:43: note: candidates are: void foo::set_timer(boost::posix_time::ptime, boost::function<void(const boost::system::error_code&)>)

看起来签名比我想象的要复杂或简单得多。

我想用类似的东西替换回调签名:

typedef std::function<void(const boost::system::error_code&)> timer_callback_t;

我在 CentOS 6.6 上使用 gcc 4.4.7 和 -std=gnu++0x,所以无法访问 auto

工作不顺利 How do you pass boost::bind objects to a function? or What is the return type of boost::bind?,我不明白我的情况有什么不同。

确实boost::bind的return类型是表达式模板,比函数类型复杂多了。毕竟,它不是一个函数,而是一个动态合成类型的函数 object(具有绑定属性值)。

这种类型是实现定义的,您不需要知道它只要您确保生成的签名与您尝试分配给的签名一致。实际上,处理程序 需要 类型为 error_code 的单个未绑定参数,因此请按照评论中的建议添加占位符:

boost::bind (&foo::callback, this, ai::placeholders::error)

一些常规修复,以及一些使其独立的步骤:

  • time_duration 不能转换为 ptime。也许您想说 expires_from_now 而不是 expires_at。但如果您确实想要后者,请指定一个绝对截止日期:

    posix_time::microsec_clock::universal_time() + posix_time::seconds(1)
    

Live On Coliru

#include <boost/asio.hpp>
#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <iostream>

namespace ai = boost::asio;

struct foo {

    ai::io_service svc;
    ai::deadline_timer t{svc};

    void callback(const boost::system::error_code& error) {
        std::cout << "callback: " << error.message() << std::endl;
    }

    void set_timer(boost::posix_time::ptime time, boost::function<void(const boost::system::error_code&)> handler) {
        t.expires_at(time);
        t.async_wait(handler);
    }

    void fornow() {
        set_timer(
                boost::posix_time::microsec_clock::universal_time() + boost::posix_time::seconds(1),
                boost::bind (&foo::callback, this, ai::placeholders::error)
            );

        svc.run();
    }
};

int main() {
    foo o;
    o.fornow();
}

1 秒后打印:

callback: Success