a quick tutorial on boost::bind and boost::function.

  • From: "Littlefield, Tyler" <tyler@xxxxxxxxxxxxx>
  • To: programmingblind@xxxxxxxxxxxxx
  • Date: Mon, 11 Apr 2011 21:00:34 -0600

I've found these incredibly useful in the last few days, so I figured I'd pass the information along to help someone out. First, a brief bit of information as to the point of boost::bind and boost::function. Boost::function is ment to take a function and wrap it up so that you can call it with the () operator, which also allows you to pass arguments to it. The cool thing about boost::function is that it allows for you to pass in static function pointers, member functions, global function pointers or functors, as well as lambdas. This came in useful for me recently while I was working on my mud engine, because I wanted events to be able to be OOP based. That is to say, I wanted them to be able to be declared either as global functions if needed, or on classes either as member functions or as static functions. Enter boost::function and boost::bind.


With boost::function, I can accept a callback as I mentioned earlier of a boost::lambda, a static function, a member function or a global function. So what are each of these?

From the boost docs:
" - Define small unnamed function objects at the actual call site, and more, from Jaakko Järvi and Gary Powell." So, translating this to english, it means that you can define a function in the middle of another function and pass it in.

So, lets say for a second that you have a player in a text-based game, and there is an event that gets fired off every two seconds. Now, this player is going to engage in some combat, which means he will probably take some damage. It would be nice to be able to heal this player for a set amount of points every two seconds. Rather than writing an extra function, you could use a lambda, which would look something like:
player.hp = min(player.max_hp, player.hp+5);

Static functions are particularly useful when a specific function is associated with an object, but it does not need to operate on an instance of that object. For example, you could have something like:
class Car
{
public:
static std::string GetType() const
{
return "a generic car.";
}
};

This means that you could do:
Car::GetType();
This is useful when you do not have an instance of an object to work with.

A member is almost like the static function I showed, but a bit different in that it operates on a specific instance of an object. Lets go back to our car example, but rewrite it so that it is a member function.
class Car
{
public:
std::string GetType() const
{
return "A generic car.";
}
};
In order to use this, you need to do:
Car c;
c.GetType();
C is an instance of a car.

A global function is not associated with any specific object, but is just declared as your normal function.
std::string GetType()
{
return "A generic car.";
}
This would be called with:
GetType();

boost::bind allows you to take a callback and give it any of the four types of functions we just explained.

So, for example, lets say that you have a math class, and after you pass in some numbers, you would like it to print out the result; this is easily done.
typedef boost::function<void (int)> cb;
class Math
{
public:
void add(int a, int b, int c, cb callback)
{
cb(a+b+c);
}
void Multiply(int a, int b, int c, cb callback)
{
callback(a*b*c);
}
};

void result(int num)
{
std::cout << num << std::endl;
}

using this, you can do something like:
Math m;
boost::bind(&Math::Add, m, _1, _2, _3, result) f;
which allows you to do:
f(1,2,3);

This is particularly useful because a function object is generated, which allows you to set up your arguments however you like. For example:
boost::bind(&Math::Add, m, _1, _1, _3) f;
This means that if you do:
f(1,3,4)
it will translate to:
m.add(1,1,4);

Why is this?
The _x (_1, _2, _3) arguments are what are called placeholders. For every placeholder, the specific argument fed to the function is passed in. So since we used _1, _1, _3, it will use the first argument for arguments 1 and 2, (discarding argument 2), then argument 3 for argument 3.

this code was untested; I just wanted to throw something out as an introduction; I'm hoping to start covering features of boost on my blog, so that I can learn and also explain a bit about boost and it's applications. Comments, suggestions and ideas are welcome and would be appreciated.
---
Thanks,
Ty
__________
View the list's information and change your settings at //www.freelists.org/list/programmingblind

Other related posts: