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

  • From: "Homme, James" <james.homme@xxxxxxxxxxxx>
  • To: "programmingblind@xxxxxxxxxxxxx" <programmingblind@xxxxxxxxxxxxx>
  • Date: Tue, 12 Apr 2011 06:48:25 -0400

Hi Ty,
Thanks for posting this.

Jim

Jim Homme,
Usability Services,
Phone: 412-544-1810. Skype: jim.homme. NonVisualDevelopment.org: Blind people 
can drive computers. Demonstration GUI Programs: You can program GUI's while 
blind.


-----Original Message-----
From: programmingblind-bounce@xxxxxxxxxxxxx 
[mailto:programmingblind-bounce@xxxxxxxxxxxxx] On Behalf Of Littlefield, Tyler
Sent: Monday, April 11, 2011 11:01 PM
To: programmingblind@xxxxxxxxxxxxx
Subject: a quick tutorial on boost::bind and boost::function.

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


This e-mail and any attachments to it are confidential and are intended solely 
for use of the individual or entity to whom they are addressed.  If you have 
received this e-mail in error, please notify the sender immediately and then 
delete it.  If you are not the intended recipient, you must not keep, use, 
disclose, copy or distribute this e-mail without the author's prior permission. 
 The views expressed in this e-mail message do not necessarily represent the 
views of Highmark Inc., its subsidiaries, or affiliates.
__________
View the list's information and change your settings at
//www.freelists.org/list/programmingblind

Other related posts: