1

I'm trying to write a wrapper method set_timer() that takes a time and callback (expressed using boost::bind) and sets up a deadline_timer to run that callback.

The callback is real simple at the moment:

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

For set_timer() I have:

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);
}

And I'm trying to call it from within the foo object for now:

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

Error message when compiling is:

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&)>)

Looks like the signature is either much more complex or much simpler than I'm thinking.

I'd like to replace the callback signature with something like:

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

I'm on CentOS 6.6 with gcc 4.4.7 and -std=gnu++0x, so no access to auto.

No luck working off How do you pass boost::bind objects to a function? or What is the return type of boost::bind?, and I don't understand what's different about my situation.

Community
  • 1
  • 1
  • You need a placeholder (_1) for the argument to the callback method in your boost::bind. – Dale Wilson Mar 12 '15 at 17:50
  • Are you thinking `set_timer(boost::posix_time::seconds(1), boost::bind (&foo::callback, this, _1));`? That's not doing the trick. I'm thinking that `boost::asio::placeholders::error` needs to be in the signature. – Andreas Yankopolus Mar 12 '15 at 20:58
  • you are correct, of course. – Dale Wilson Mar 12 '15 at 20:59
  • Doing `set_timer(boost::posix_time::seconds(1), boost::bind (&foo::callback, this, boost::asio::placeholders::error));` results in a similar error message. The compiler error above tells me that I'm creating a much more complex signature with the `boost:bind()` call than is present in the receiving argument in `set_timer()`. There's some important concept I'm missing. – Andreas Yankopolus Mar 12 '15 at 22:29

1 Answers1

3

Indeed the return type of boost::bind is an expression template, and much more complicated than a function type. It is, after all, not a function but a function object (complete with bound attribute values) of an on-the-fly synthesized type.

This type is implementation defined and you don't need to know it as long as you make sure the resulting signature is congruent with the one you are trying to assign to. Indeed, the handler requires a single unbound argument of type error_code, so add the placeholder as suggested in the comment:

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

A few general fixes, and a few more steps to make it self contained:

  • time_duration is not convertible to ptime. Perhaps you wanted to say expires_from_now instead of expires_at. But in case you did want the latter, specify an absolute deadline:

    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();
}

Prints after 1 second:

callback: Success
sehe
  • 374,641
  • 47
  • 450
  • 633