How can I store a boost::bind object as a class member?
Asked Answered
C

4

5

I'm writing an application that uses boost::asio. Asio's async_receive (or async_read) is invariably shown using a boost::bind object given for callback:

boost::asio::async_read(socket_,
                        boost::asio::buffer(read_msg_.data(),
                                            chat_message::header_length),
                        boost::bind(&chat_session::handle_read_header,
                                    shared_from_this(),
                                    boost::asio::placeholders::error));

That's perfectly nice, but I'd like not to have to recreate the bind object after each call to the callback. Instead, I'd like to create the object, say, in the constructor of my class, and give it to async_receive.

The problem is, I don't know how to declare that object as a class member. All I know is auto, and it obviously won't work as a class member.

class Whatever
{
public:
    Whatever()
    {
        functor = boost::bind(&Whatever::Callback);
    }
private:
    void Callback()
    {
        boost::asio::async_read(socket_,
                        boost::asio::buffer(read_msg_.data(),
                                            chat_message::header_length),
                        functor);
    }

    ?? functor; // How do I declare this?
    ...
};

Note: This may very well be premature optimization, but I'd still like to know how to declare a bind object without auto.

Clywd answered 13/10, 2011 at 16:10 Comment(0)
H
11

Use boost::function:

class Whatever
{
public:
    Whatever()
    {
        functor = boost::bind(
            &chat_session::handle_read_header,
            shared_from_this(),
            boost::asio::placeholders::error,
            boost::asio::placeholders::bytes_transferred
        );
        boost::asio::async_read(
            socket_,
            boost::asio::buffer(
               read_msg_.data(),
               chat_message::header_length
            ),
            functor
        );
    }
private:
    boost::function<void(const error_code, const size_t)> functor;
};

... or something like that.

Hoenack answered 13/10, 2011 at 16:14 Comment(1)
+1, :) almost, need the place holder for the bytes transferred too when you bind - then it will match your functor declaration.Juliennejuliet
C
0

I guess you are looking for boost function.
You can assign the result of your bind expression to a boost::function object as long as the signature is correct.

Chasten answered 13/10, 2011 at 16:14 Comment(0)
S
0

The "standard" way of doing this is to make functor be a std::function.

If you really want to store the actual binder object, then look at compile error messages involving the binder to figure out the exact type, and try using those to determine the actual type of the binder object.

Spiritism answered 13/10, 2011 at 16:17 Comment(0)
A
0

The return type of boost::bind is a boost::function. Here's a quick example using a very simple function:

double f(int i, double d) { 
    cout << "int = " << i << endl; 
    return d; 
} 

boost::function<double (int)> bound_func = boost::bind(f, _1, 1.234); 
int i = 99; 
cout << bound_func(i) << endl;

In your case the function has this type:

boost::function<void(const error_code, const size_t)> f;
Alitta answered 13/10, 2011 at 16:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.