How can boost::bind swallow an argument to a member function?

In the example here, it is necessary for the function print to have the signature void(const boost::system::error_code&)

The boost::asio::deadline_timer::async_wait() function expects a handler function (or function object) with the signature void(const boost::system::error_code&). Binding the additional parameters converts your print function into a function object that matches the signature correctly.

Timer.3 - Binding arguments to a handler

//
// timer.cpp
// ~~~~~~~~~
//
// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//

#include <iostream>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>

void print(const boost::system::error_code& /*e*/,
  boost::asio::deadline_timer* t, int* count)
{
  if (*count < 5)
  {
    std::cout << *count << "
";
    ++(*count);

    t->expires_at(t->expires_at() + boost::posix_time::seconds(1));
    t->async_wait(boost::bind(print,
          boost::asio::placeholders::error, t, count));
  }
}

int main()
{
  boost::asio::io_service io;

  int count = 0;
  boost::asio::deadline_timer t(io, boost::posix_time::seconds(1));
  t.async_wait(boost::bind(print, boost::asio::placeholders::error, &t, &count));

  io.run();

  std::cout << "Final count is " << count << "
";

  return 0;
}

According to the discussion in this example, the same is true, except it is somehow disappeared from the member function definition.

The boost::bind() function works just as well with class member functions as with free functions. Since all non-static class member functions have an implicit this parameter, we need to bind this to the function. As in tutorial Timer.3, boost::bind() converts our callback handler (now a member function) into a function object that can be invoked as though it has the signature void(const boost::system::error_code&).

You will note that the boost::asio::placeholders::error placeholder is not specified here, as the print member function does not accept an error object as a parameter.

Timer.4 - Using a member function as a handler

//
// timer.cpp
// ~~~~~~~~~
//
// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//

#include <iostream>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>

class printer
{
public:
  printer(boost::asio::io_service& io)
    : timer_(io, boost::posix_time::seconds(1)),
      count_(0)
  {
    timer_.async_wait(boost::bind(&printer::print, this));
  }

  ~printer()
  {
    std::cout << "Final count is " << count_ << "
";
  }

  void print()
  {
    if (count_ < 5)
    {
      std::cout << count_ << "
";
      ++count_;

      timer_.expires_at(timer_.expires_at() + boost::posix_time::seconds(1));
      timer_.async_wait(boost::bind(&printer::print, this));
    }
  }

private:
  boost::asio::deadline_timer timer_;
  int count_;
};

int main()
{
  boost::asio::io_service io;
  printer p(io);
  io.run();

  return 0;
}

This makes no sense to me. I looked at the documentation for boost::bind Boost: bind.hpp documentation but saw nothing that helped me understand this.

Can someone please explain how the use of boost::bind on a member function which only takes the implicit this pointer results in a function with the signature void(const boost::system::error_code&)?

Would have been nice if you would have stated which programming/scripting language this is about. Either in the Title or in the beginning of the post.
Thus those who know the language would be attrackted (what is what you hope for) and those who don’t could have skipped this thread.

Sorry for the confusion. I figured mentioning boost:: would have been sufficient for that purpose. Boost is a standards-track C++ extension library.

You would understand it when I would show you a piece of ksh script that it is ksh even if you do not know much of ksh? :wink:
Nevertheless, I hope you will get usefull help.

The boost::bind function helps to modify the signature of any of your functions to:

void(const boost::system::error_code&)

Internally it does not modify any signature, but this new function acts as a wrapper function to your actual function.

Say you have a function:

A(int, float, char)

But your

registerHandler(HandlerFunction)

expects the HandlerFunction to be of the signature void(const boost::system::error_code&)

I want to register my function A as the handler function but since the signatures do not match I cannot directly register it. This is where boost:bind does its wrapping to give you a function with the signature void(const boost::system::error_code&) for your function A.

boost::bind(&A, p, q, r)

So when the registered handler function is invoked, it would call the function returned by boost::bind say some X. This function X would internally invoke the function you had mentioned in the argument to bind called with the arguments you mentioned - all this is taken care by the boost library.

If you’re clear on this part and how non-static class methods can be invoked using the this pointer of the class’s object, it should answer your question.

Just to explain how class methods work:
All the non-static member functions need to be called using the this pointer.

So if you have a class B and its object created as B obj. You can call one of the class methods say memberFn() in this fashion

obj.memberFn()

To get the address of the variable obj from one of the member functions you use the this pointer.

That did help. I was confused by the presence of

const boost::system::error_code

in the first example. Apparently it has nothing to do with satisfying the requirement that a parameter of the same type appear in the signature of the handler. I modified the code to completely remove that parameter, and it compiles and runs.

I’m still a bit confused about this. How does bind produce a function object with the correct signature? The information has to somehow come from the context. I’m not seeing that explained in the documentation for boost::bind, but I might be overlooking something.