Results 1 to 6 of 6

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

  1. #1

    Default 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

    Code:
    //
    // 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 << "\n";
        ++(*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 << "\n";
    
      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:laceholders::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


    Code:
    //
    // 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_ << "\n";
      }
    
      void print()
      {
        if (count_ < 5)
        {
          std::cout << count_ << "\n";
          ++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&)?

  2. #2
    Join Date
    Jun 2008
    Location
    Netherlands
    Posts
    15,724

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

    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.
    Henk van Velden

  3. #3

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

    Quote Originally Posted by hcvv View Post
    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.

  4. #4
    Join Date
    Jun 2008
    Location
    Netherlands
    Posts
    15,724

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

    Quote Originally Posted by hattons View Post
    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?
    Nevertheless, I hope you will get usefull help.
    Henk van Velden

  5. #5
    Join Date
    Aug 2009
    Location
    Mountain View, CA
    Posts
    201

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

    The boost::bind function helps to modify the signature of any of your functions to:
    Code:
    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:
    Code:
    A(int, float, char)
    But your
    Code:
    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.

    Code:
    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
    Code:
    obj.memberFn()
    To get the address of the variable obj from one of the member functions you use the this pointer.

  6. #6

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

    That did help. I was confused by the presence of
    Code:
    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.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •