Search code examples
c++boostfunction-pointersboost-bindboost-function

Using boost::function and boost::bind to a member variable


I'm trying to create a boost::function that allows setting of a member variable of an object. I've created the simplest example I can think of to get across what I'm trying (and failing) to do. I feel like I have a grasp of boost::bind, but I'm new to boost and I believe I'm using boost::function incorrectly.

#include <iostream>
#include <Boost/bind.hpp>
#include <boost/function.hpp>

class Foo
{
public:
    Foo() : value(0) {}

    boost::function<void (int&)> getFcn()
    {
        return boost::function<void (int&)>( boost::bind<void>( Foo::value, this, _1 ) );
    }

    int getValue() const    { return value; }

private:
    int value;
};

int main(int argc, const char * argv[])
{
    Foo foo;

    std::cout << "Value before: " << foo.getValue();

    boost::function<void (int&)> setter = foo.getFcn();
    setter(10);     // ERROR: No matching function for call to object of type 'boost::function<void (int &)>'
                    // and in bind.hpp: Called object type 'int' is not a function or function pointer

    std::cout << "Value after: " << foo.getValue();

    return 0;
}

I'm having the error on line 28, where I want to use the function to set Foo::value to 10. Am I just going about this whole thing wrong? Should I just be passing back an int* or something instead of using boost for all of this? The reason I'm calling 'getFcn()' is because in my actual project I'm using a messaging system, and if the object with the data I want is no longer there, getFcn would return an empty boost::function. But I guess with an int* I could just return NULL if nothing was found.


Solution

  • This boost::bind<void>( Foo::value, this, _1 ) in your code is essentially using Foo::value as a member function. Which is wrong. Foo::value is not a function.

    Lets build this step by step:

    class Foo
    {
        ...
        boost::function< void (Foo*, int) > getFcn ()
        {
            return boost::function< void (Foo*, int) >( &Foo::setValue );
        }
    
        void setValue (int v)
        {
            value = v;
        }
        ...
    }
    
    int main ()
    {
        ...
        boost::function< void (Foo*, int) > setter = foo.getFcn();
        setter( &foo, 10);
        ...
    }
    

    So here the function takes this object explicitly. Let's use boost.bind to bind this as first parameter.

    class Foo
    {
        ...
        boost::function< void (int) > getFcn ()
        {
            return boost::bind(&Foo::setValue, this, _1);
        }
    
        void setValue (int v)
        {
            value = v;
        }
        ...
    }
    
    int main ()
    {
        ...
        boost::function< void (int) > setter = foo.getFcn();
        setter( 10);
        ...
    }
    

    (untested code)