0

Can I use boost::bind to make the resulting function object store an object which is not declared as argument to the bound target function? For example:

void Connect(const error_code& errorCode)
{
    ...
}

// Invokes Connect after 5 seconds.
void DelayedConnect()
{
    boost::shared_ptr<boost::asio::deadline_timer> timer =
        boost::make_shared<boost::asio::deadline_timer>(ioServiceFromSomewhere);

    timer->expires_from_now(
        boost::posix_time::seconds(5));

    // Here I would like to pass the smart pointer 'timer' to the 'bind function object'
    // so that the deadline_timer is kept alive, even if it is not an actual argument
    // to 'Connect'. Is this possible with the bind syntax or similar?
    timer->async_wait(
        boost::bind(&Connect, boost::asio::placeholders::error));
}

ps. I'm mostly interested in an already existing syntax of doing this. I know I can make custom code to do it myself. I also know I can keep the timer alive manually, but I would like to avoid that.

shadow_map
  • 313
  • 3
  • 15

2 Answers2

2

Yes, you can do this by binding the extra parameters. I often did that with asio, e.g. in order to keep buffers or other state alive during the async operation.

You can also access these extra arguments from the handler afterwards by extending the handler signature to utilize them:

void Connect(const error_code& errorCode, boost::shared_ptr<asio::deadline_timer> timer)
{
}

timer.async_wait(
    boost::bind(&Connect, boost::asio::placeholders::error, timer));
Matthias247
  • 9,836
  • 1
  • 20
  • 29
  • Thanks. That's kinda what I plan to do as well. Do you have any preference on what smart pointer types to use in such situations (in the scope of boost and STL)? – shadow_map Jan 30 '17 at 15:03
  • I used boost::shared_ptr and std::shared_ptr. I guess unqiue_ptr could work too, if the object is then moved into the handler object. But I have no experience with this, since I needed the shared_ptr anyway. – Matthias247 Jan 30 '17 at 16:18
  • Unfortunately I get compilation errors with the Visual Studio 2012 compiler when using extra parameters as suggested: error C2039: 'result_type' : is not a member of '`global namespace'' error C2208: 'boost::_bi::type' : no members defined using this type error C2825: 'F': must be a class or namespace when followed by '::' – shadow_map Jan 31 '17 at 11:24
  • It seem the extra parameter causes and overload of bind, which takes return type as an input, to be used, therefore the confusing error. If I change to use boost::bind(&Connect, boost::asio::placeholders::error, timer) I get a more clear error message, but only when actually invoking the bound function object: error C2197: too many arguments for call – shadow_map Jan 31 '17 at 12:08
  • If it doesn't work out with boost::bind you could also try std::bind with `std::bind(&Connect, std::placeholders::_1, timer)`. Sorry, I have no idea about that error message – Matthias247 Jan 31 '17 at 13:31
1

Yes, you can simply bind "too many" parameters, and they won't get passed to the underlying handler. See Why do objects returned from bind ignore extra arguments?

This is ok, unless you needed to "talk to" the timer object from withing Connect.

PS. Also, don't forget to expect the timer completion with operation_abandoned when the timer is destructed.

Community
  • 1
  • 1
sehe
  • 374,641
  • 47
  • 450
  • 633
  • Ok. I guess I can do the "talk to" thing like Matthias247 described in the previous answer. Good point about the operation_abandoned. – shadow_map Jan 30 '17 at 15:06