Can you help me to understand why this bind works? - c++

I'm trying to understand bind and pre-fill functions in C++.
Here's my example:
#include <iostream>
#include <functional>
#include <vector>
class Voice
{
public:
double mValue;
private:
};
class VoiceManager
{
public:
VoiceManager() { }
~VoiceManager() { }
typedef std::function<void(Voice &)> VoiceChangerFunction;
inline void UpdateVoices(VoiceChangerFunction callback) {
for (int i = 0; i < mNumOfVoices; i++) {
callback(mVoices[i]);
}
}
static void SetValue(Voice &voice, unsigned int value) {
voice.mValue = value;
std::cout << voice.mValue << std::endl;
}
private:
static const int mNumOfVoices = 4;
Voice mVoices[mNumOfVoices];
};
int main()
{
VoiceManager voiceManager;
VoiceManager::VoiceChangerFunction callback;
callback = std::bind(&VoiceManager::SetValue, std::placeholders::_1, 100);
voiceManager.UpdateVoices(callback);
}
Basically, I create a VoiceChangerFunction function (object) that takes a Voice & as first parameter and returns void.
Later, I bind a function that will take as first parameter the one I'll give to it when I call it, and another parameter that I give when I bind it (100, in my example).
Right?
What I don't understand is: then, this function is passed to UpdateVoices(), which take as input a function/object that has 1 param (Voice &), not 2 as created in my bind function (Voice &, unsigned int).
How can it works?
Its like to have void VoiceChangerFunction(Voice &voice) and call VoiceChangerFunction(Voice &voice, unsigned int value ).
The function prototype is different. I mean: the callback bind I created isn't a VoiceChangerFunctions function, because it takes more parameters.
How can it works/match?

That is exactly the beauty of bind and std::function at works. You are defining the callback as function taking one argument, and bind is returning a function object which takes one argument.
The main point here is that it actually calls the function which takes 2 parameters, but the second one is fixed, and will always be 100 (in your case). This is the sole purpose of binders - to provide a way to call functions with different set of arguments with some fixed values. If you would be calling the function taking the same set of arguments, there would be no reason to use binders at all!
Knowing that bind is similar to lambdas, the same code could be written as - and probably be more clear:
VoiceManager::VoiceChangerFunction callback;
callback = [](Voice& v) { VoiceManager::SetValue(v, 100); };
voiceManager.UpdateVoices(callback);
And if you are curious how it works, you might try to create a binder framework yourself. If you are only doing it for educational purposes and not worried about too many details, it is not that hard.

When you bind, you're making a new function that only takes Voice as a param, that's why it works.
void a_func(int x) { return; }
std::function<void(void)> new_func = std::bind(&a_func, 1);
new_func now has the signature of void(void), so you could pass it around to anywhere that expects a function of type void(void).
When you call new_func, it really calls a_func(1).

Your assumption about bind is wrong.
Your bind call returns a function object that will accept one parameter, namely the placeholder. The other parameter on your function is already bound to 100.
A little example:
void foo(int i1, int i2) {};
std::function<void(int,int)> fn1 = std::bind(foo, std::placeholders::_1, std::placeholders::_2);
std::function<void(int)> fn1 = std::bind(foo, std::placeholders::_1, 1);
std::function<void()> fn1 = std::bind(foo, 1, 1);
The bind will create a matching function depending on bound and unbound parameters.
Update
The compiler will generate a struct from the bind expression and a copy of your parameter. Simplified something like this(this will not compile):
struct Function_{
void(*fn)(Voice &, unsigned int)
unsigned int i_;
Function_(void(*f)(Voice &, unsigned int), unsigned int i):fn(f),i_(i){}
void operator()(Voice& v){
fn(v, i_);
}
}
fn is the first parameter which is a function pointer and the bound (100) is the second. Then all you need is some type erasure and your own bind is ready to go.

Related

Is it possible to access the arguments from an std::bind object?

Please consider the following scenario.
A hypothetical pop-up menu class that displays some actions, and when one of them is selected it will call the passed in action which is in form of an std::function:
PopupMenu::PopupMenu(std::function<void(RowItem*)> editRowFunction, RowItem *item)
: _editRowFunction(editRowFunction)
, _item(item) {
}
Then at some point it might call execute:
PopupMenu::execute(} {
_editRowFunction(_item);
}
Then I have this other class that's a UI object:
class EditorWidget {
void editRow(RowItem *row) {
//edit the row
}
}
And here's how I am using all of them:
int main() {
auto item = new RowItem();
auto editorWidget = new EditorWidget();
PopupMenu menu(std::bind(&EditorWidget::editRow, editorWidget, item), item);
menu.execute();
return 0;
}
Everything works. My question is the following:
If I am already passing the argument item in std::bind, why do I have to pass it again as a second parameter in order to be able to call the bound function with that argument? If I don't, and try to call the function just by itself from PopupMenu::execute(), I get a compiler error.
The other way around it is to make the constructor of PopupMenu like this:
PopupMenu::PopupMenu(std::function<void()> editRowFunction)
: _editRowFunction(editRowFunction) {}
And if I do it that way then I call it this way:
PopupMenu::execute() {
_editRowFunction();
}
What I don't like about this method is that I can pretty much pass any bound function in the PopupMenu constructor and it will be called. But that's not what I want, I want to enforce only a function with a specific signature.
I can also pass a lambda, yes. But let's try to solve it without lambdas.
Thank you all in advance for your help.
std::bind(&EditorWidget::editRow, editorWidget, item)
std::bind here is creating a functional object that takes a pointer to a member function EditorWidget::editRow, bound to an object editorWidget, using the parameter item. What you've done is actually fix the parameter to the function EditorWidget::editRow with the parameter item. So effectively you've created a function object that takes no argument (since you've fixed it), and returns void.
There's actually no need for the constructor of PopupMenu to have a second parameter of type RowItem*. You could change the constructor like so:
PopupMenu::PopupMenu(std::function<void()> editRowFunction)
: _editRowFunction(editRowFunction)
{
}
and then call your function object like this:
PopupMenu::execute(} {
_editRowFunction();
}
In your current code the parameter _item is not being used by the function object you pass into the constructor PopupMenu. It satisfies the compiler since _editRowFunction is of type std::function<void(RowItem*)>.
Here's a simple example to illustrate to the point:
#include <iostream>
#include <functional>
struct callable
{
callable(std::function<void(std::string)> fn) : mFn(fn)
{}
std::function<void(std::string)> mFn;
void Run() { mFn("world"); }
};
struct Foo {
void print(std::string msg)
{
std::cout << msg << '\n';
}
};
int main()
{
Foo f;
auto fn = std::bind(&Foo::print, &f, "hello");
fn();
callable c(fn);
c.Run(); //expecting "world" to be printed
}
You might expect the output to be:
hello
world
but actually it's:
hello
hello
Live demo.
What I could do is change the definition of the function object like this:
auto fn = std::bind(&Foo::print, &f, std::placeholders::_1); //uses a placeholder
and I get the expected output. You could do something similar without having to make many changes to your current implementation.

Hold a collection of member function pointers and decorated member function pointers

As a part of a much larger project, one of my objects (Thing in MWE) has a set of filters (filterStrong, filterWeak) defined on it. The goal is to use all the implemented filters in complexFilteringProcedure, where the user could chose the filtering rule through a parameter, and the function itself would depend on the success of the filtering rule chosen. The function complexFilteringProcedure would act on an object of type Thing, and call one of its private methods (filtering rules) depending on the parameter.
I implemented this by holding a vector of all possible filters in filteringOptions and implementing a single public filtering interface, filterUsingRule. Ideally, this would allow me to later on add new filtering rules to the project as I need them, and only modify the setFilteringFunction where the filter list is initialized.
Now, I started writing a new set of filtering rules, and realized all of them could be obtained by decorating the current filtering rules all in the same manner (softenFilter; please do correct me if "decorating" is the wrong expression here). I remembered reading into std::bind recently and taught, great. I would also like to add all the decorated filtering rules in my list of filteringOptions, that is, every original filter decorated with softenFilter.
Reading up a little bit more on std::bind, I think the possible reasons for my problems are twofold:
the return type of std::bind is a templated mess, and definitely not Thing::filteringFunction
I might be binding the this referring to the calling object when defining softStrong and softWeak
But, I am stuck further than that, not sure how to look for a solution to my specific problem. My main question are: Can this functionality be achieved? (functionality of filterUsingRule) and further, Can this functionality be achieved elegantly? (I know I could always define a set of functions bool softStrong(int param) { return softenFilter(filterStrong, param); } that manually bind the filters to the decorator, but I was hoping that std::bind or some new C++ magic would help with that).
The MWE recreating what I have successfully done and what I would like to achieve is as follows:
#include <iostream>
#include <vector>
#include <functional>
class Thing{
private:
int basicFilter;
typedef bool (Thing::*filteringFunction)(int);
static std::vector<filteringFunction> filteringOptions;
bool filterStrong(int parameter) {return parameter > basicFilter*2;}
bool filterWeak(int parameter) {return parameter > basicFilter;}
bool softenFilter(filteringFunction f, int parameter){
if (!((this->*(f))(parameter)))
return (this->*(f))(parameter+2);
return true;
}
void setFilteringFunctions(void){
Thing::filteringOptions.emplace_back(&Thing::filterStrong);
Thing::filteringOptions.emplace_back(&Thing::filterWeak);
auto softStrong = std::bind(&Thing::softenFilter,
&Thing::filterStrong,
std::placeholders::_1); // ok
auto softWeak = std::bind(&Thing::softenFilter,
&Thing::filterWeak,
std::placeholders::_1); // ok
filteringOptions.emplace_back(&softStrong); // how?
filteringOptions.emplace_back(softWeak); // how?
}
public:
Thing(int basicFilter) : basicFilter(basicFilter){
if (Thing::filteringOptions.empty())
setFilteringFunctions();
}
bool filterUsingRule(int parameter, int rule = 0){
return ((int)Thing::filteringOptions.size() > rule) &&
(this->*(Thing::filteringOptions[rule]))(parameter);
}
};
std::vector <Thing::filteringFunction> Thing::filteringOptions(0);
void complexFilteringProcedure(Thing &aThing, int parameter, int rule){
// do a lot of things
if (aThing.filterUsingRule(parameter, rule))
std::cout << "Filtering with " << rule << "successful" << std::endl;
else
std::cout << "Filtering with " << rule << "failed" << std::endl;
// and some more things
}
int main(void){
Thing myThing(5), otherThing(10);
complexFilteringProcedure(myThing, 7, 0); // uses strong rule
complexFilteringProcedure(otherThing, 7, 1); // uses weak rule
complexFilteringProcedure(myThing, 7, 2); // how to do this correctly?
complexFilteringProcedure(otherThing, 7, 3); // or this?
}
You might use std::function
using filteringFunction = std::function<bool (Thing&, int)>;
and then
void setFilteringFunctions()
{
Thing::filteringOptions.emplace_back(&Thing::filterStrong);
Thing::filteringOptions.emplace_back(&Thing::filterWeak);
auto softStrong = std::bind(&Thing::softenFilter,
std::placeholders::_1,
&Thing::filterStrong,
std::placeholders::_2
);
auto softWeak = std::bind(&Thing::softenFilter,
std::placeholders::_1,
&Thing::filterWeak,
std::placeholders::_2);
Thing::filteringOptions.emplace_back(&softStrong);
Thing::filteringOptions.emplace_back(&softWeak);
// or
Thing::filteringOptions.emplace_back([](Thing& instance, int param){
return instance.filterStrong(param + 2) });
}
You'll have to use a specialization of std::function as your vector element type. The key issue is that the object returned by std::bind() is not a bare function pointer. It is rather a Callable -- a function object -- it is some type (exactly what type is unimportant and in fact unspecified) that has an operator() with the appropriate return type which takes the appropriate parameters. This is exactly the role of std::function -- a type which can wrap any Callable of the correct signature in a way that lets you handle it with a known concrete type regardless of the actual type of the Callable.
typedef std::function<bool(int)> filteringFunction;
static std::vector<filteringFunction> filteringOptions;
// now can you store your member function pointers in
// filteringOptions after bind()ing the first parameter
// as you've already done
To satisfy the skeptics, here is the OP's code modified to use this technique.
#include <iostream>
#include <vector>
#include <functional>
class Thing{
private:
int basicFilter;
typedef std::function<bool(int)> filteringFunction;
static std::vector<filteringFunction> filteringOptions;
bool filterStrong(int parameter) {return parameter > basicFilter*2;}
bool filterWeak(int parameter) {return parameter > basicFilter;}
bool softenFilter(filteringFunction f, int parameter){
if (!f(parameter))
return f(parameter + 2);
return true;
}
void setFilteringFunctions(void){
filteringFunction strong = std::bind(&Thing::filterStrong,
this, std::placeholders::_1);
filteringFunction weak = std::bind(&Thing::filterWeak,
this, std::placeholders::_1);
filteringFunction softStrong = std::bind(&Thing::softenFilter,
this, strong, std::placeholders::_1);
filteringFunction softWeak = std::bind(&Thing::softenFilter,
this, weak, std::placeholders::_1);
filteringOptions.emplace_back(softStrong);
filteringOptions.emplace_back(softWeak);
}
public:
Thing(int basicFilter) : basicFilter(basicFilter){
if (Thing::filteringOptions.empty())
setFilteringFunctions();
}
bool filterUsingRule(int parameter, int rule = 0){
return ((int)Thing::filteringOptions.size() > rule) &&
filteringOptions[rule](parameter);
}
};
std::vector <Thing::filteringFunction> Thing::filteringOptions(0);
void complexFilteringProcedure(Thing &aThing, int parameter, int rule){
// do a lot of things
std::cout << "Filtering: " << aThing.filterUsingRule(parameter, rule) << std::endl;
// and some more things
}
int main(void){
Thing myThing(5), otherThing(10);
complexFilteringProcedure(myThing, 7, 0); // uses strong rule
complexFilteringProcedure(otherThing, 7, 1); // uses weak rule
//complexFilteringProcedure(myThing, 7, 2); // how to use soft strong rule?
//complexFilteringProcedure(otherThing, 7, 3); // how to use soft weak rule?
}
typedef std::function<bool(Thing*, int)> filteringFuction;
Now you can use static functions as well as std::bind and lambda or any callable that accepts an int and returns bool.
static bool test(Thing*, int);
static bool decoratee(Thing*, bool , int);
this->filteringOptions.emplace_back([](Thing* sth, int x){return false;});
this->filteringOptions.emplace_back(&Thing::weakFilter);
this->filteringOptions.emplace_back(std::bind(decoratee, _1, false, _2));
this->filteringOptions.emplace_back(&test);
int param;
for(auto& callee:this->filteringOptions)
callee(this,param);

How do I Pass a Member Function to a Function as a Function Pointer?

Source of Problem https://github.com/claydonkey/PointerToMember/tree/master
Although touched on in How Can I Pass a Member Function to a Function Pointer?, I feel somewhat dissatisfied with the solutions provided, as I don't want to introduce a dependency on the Boost library.
Comparing std::function for member functions is a post that gets close to a solution but ultimately is less optimistic about the use of std::function in .
(it seems that member functions cannot be passed as function pointers)
The Problem:
A function simpleFunction which cannot be altered takes a callback pfunc:
typedef int (*FuncPtr_t)(void*, std::pair<int,int>&);
static int simpleFunction(FuncPtr_t pfunc, void *context, std::pair<int,int>& nos)
{
pfunc(context, nos);
}
This function is intended to callback the method memberFunction in class SimpleClass:
NB removed void from original post as it better represents a real world usage.* was int memberFunction(void*, std::pair<int,int>& nos)
class SimpleClass {
public:
int memberFunction(std::pair<int,int>& nos) { return nos.first + nos.second; }
};
I expected the following to work:
MemFuncPtr_t MemFunction = &SimpleClass::memberFunction;
simpleFunction(obj.*MemFunction, nos);
but obj.*MemFunction has a type: int (SimpleClass::)(std::pair<int,int>&)
and it needs to be: int (*)(std::pair<int,int>&)
(wheras (obj.*MemFunction) (nos); returns as expected)
I can create and pass a trampoline:
int functionToMemberFunction(void* context, std::pair<int,int> & nos) {
return static_cast<SimpleClass*>(context)->memberFunction(nos);
}
and pass it
simpleFunction(&functionToMemberFunction, &obj, nos);
but it compiles to around 40 instructions.
I can pass a lambda:
simpleFunction((FuncPtr_t)[](void* , std::pair<int,int> & nos) {
return nos.first + nos.second;
}, &obj, nos);
That's surprisingly well optimised but a bit ugly and syntactically cumbersome.
(NB Both and lambdas require C++11)
I can add a static member to SimpleClass:
class SimpleClass {
public:
int memberFunction(void*, std::pair<int,int>& nos) { return nos.first + nos.second; }
static int staticFunction(void*, std::pair<int,int> & nos) { return nos.first + nos.second; }
};
FuncPtr_t StaticMemFunction = &SimpleClass::staticFunction;
and pass it
simpleFunction(StaticMemFunction, nullptr, nos);
and that's just, well ... a static function inside a class.
I can use the <functional> header:
using namespace std::placeholders;
std::function<int(std::pair<int,int>&) > f_simpleFunc =
std::bind(&SimpleClass::memberFunction, obj, _1);
auto ptr_fun = f_simpleFunc.target<int (std::pair<int,int> & ) >();
and try and pass it...
simpleFunction(*ptr_fun, nos);
but ptr_fun reports null.
Looking at the x86 assembly - I am at a loss at how memory is addressed, calling a member function (there are an extra 5 instructions [3 mov, 1 lea and 1 add] over the StaticMemFunction call). I can only imagine that this is down to locating the class instance in memory and then the function within it.
All the suggestions have been useful and I think if I collate them all and return to the original problem, I may have a solution that works for me.
So I thought a solution would be derived from:
simpleFunction(([](void* context,std::pair<int, int> & nos) {
return nos.first + nos.second;
}), &obj, nos);
to become:
simpleFunction(([&](void* context,std::pair<int, int> & nos) {
obj.memberFunction(nos);
}), &obj, nos);
right?
error: cannot convert main()::<lambda(std::pair<int, int>&, void*)> to int (*)(std::pair<int, int>&, void*)
Lambdas that accept closures cannot be cast to a function pointer
The closure type for a lambda-expression with no lambda-capture has a
public non-virtual non-explicit const conversion function to pointer
to function having the same parameter and return types as the closure
type’s function call operator. The value returned by this conversion
function shall be the address of a function that, when invoked, has
the same effect as invoking the closure type’s function call operator.
This makes sense as function pointers carry no state and this is why simpleFunction was gifted with a context pointer void* context (like most callbacks!), which is in turn handled by pFunc- the function pointer. (The context being the SimpleObject instance obj whose member function we wish to delegate to.)
Ergo a good solution seems to be:
solution 1
simpleFunction(([](void* context, std::pair<int,int>& n) {
return static_cast<SimpleClass*>(context)->memberFunction(n);
}), &obj, nos);
NB If obj is moved from local -> global scope the lambda would not require the object to be passed in at all. but that changes the original problem.
Incredibly, if the member-function has no calls to the class within which it resides, it behaves as a static function, the lambda obviating the need for the class instance
solution 2
simpleFunction(([](void* context, std::pair<int,int>& n) {
return static_cast<SimpleClass*>(context)->memberFunction(n);
}), nullptr /* << HERE */, nos); //WILL WORK even though the context is null!
This works perfectly as a solution to the original question: the member function indeed does not rely on anything outside the function scope (is this expected C++ behaviour or a happy hack?).
In conclusion, in trying to compose a simple analogy to a real world problem I have been naive in my the original question and I really want all the functionality of a member-function so solution 1 seems more realistic.
I am little more savvy in distinguishing between member functions and c functions - I spose the clue was in the name member (of a class)
This was all part of a learning experience and the source code including move-semantics solutions is in the link in the original post.
Implement a simple trampoline with a lambda:
#include <iostream>
typedef int (*FuncPtr_t)(void*, int);
static int simpleFunction(FuncPtr_t pfunc, void *context, int nos)
{
return pfunc(context, nos);
}
struct A {
int i;
int pf(int nos) { std::cout << i << " nos = " << nos << "\n"; return i; }
};
int main() {
A a { 1234 };
// could combine the next two lines into one, I didn't.
auto trampoline = [](void *inst, int nos) { return ((A*)inst)->pf(nos); };
simpleFunction(trampoline, &a, 42);
}
http://ideone.com/74Xhes
I've modified it to consider the assembly:
typedef int (*FuncPtr_t)(void*, int);
static int simpleFunction(FuncPtr_t pfunc, void *context, int nos)
{
return pfunc(context, nos);
}
struct A {
int i;
int pf(int nos) { return nos + i; }
};
int f(A& a) {
auto trampoline = [](void *inst, int nos) { return ((A*)inst)->pf(nos); };
return simpleFunction(trampoline, &a, 42);
}
Compiled with -O3 we get:
f(A&):
movl (%rdi), %eax
addl $42, %eax
ret
https://godbolt.org/g/amDKu6
I.e. the compiler is able to eliminate the trampoline entirely.
std::function<> plus lambdas are a nice way to go. Just capture the this in the lambda, an do what you need. You don't event need to write a separate callback if what is being executed is small. Plus std::function is required to not need a heap allocation for lambda that only captures a single pointer.
class A {
std::function <void()> notify;
void someProcessingFunction () {
// do some work
if (notify != nullptr)
notify ();
}
};
class B {
void processNotification () {
// do something in response to notification
}
};
int main ()
{
A a;
B b;
a.notify = [&b] () { b.processNotification (); };
a.someProcessingFunction ();
}
The usual approach is to pass the object as your callback data, as you do in the first example. Any overhead is likely a consequence of the calling convention on your target (or perhaps too low a setting on your compiler's optimiser).
In these circumstances I use a fusion of your first two methods. That is, I create a trampoline, but make it a static function inside the class, to avoid clutter. It does not do what the member function does (as in your second example): it just calls the member function.
Don't worry about a handful of instructions in the calling process. If you ever do need to worry that much about clock cycles, use assembler.

Passing "part" of a function pointer as an argument

I'm sure this has been asked before, but it's just hard to search for...
So, what I've got is a function that accepts a function pointer. This function pointer has, say, 3 arguments. So, I want to pass to another function, the same pointer, but with 2 arguments filled in.
So, something like this:
int func1 (int (*funcptr)(int, int, int)) {
return func2(funcptr(,8,9));
}
int func2 (int (*funcptr)(int)) {
return (*funcptr)(2);
}
EDIT:
Ok so I got this now with the usage of a lambda
int func2(int (*funcptr2)(int)) {
return (*funcptr2)(2);
}
int func1(int (*funcptr1)(int, int, int)) {
return func2(
[funcptr1](int i)->int {
return (*funcptr1)(i,8,9);
}
);
}
But it's giving me
"cannot convert func1(int (*)(int, int, int))::<lambda(int)> to int (*)(int) for argument 1 to int func2(int (*)(int))"
This is called a lambda, and you can do it with newer C++ versions, std::bind, boost::bind or boost::function.
To answer your updated question, a lambda which captures variables (as your lambda does with funcptr1) cannot be converted to a function pointer. Intuitively this makes sense since your lambda must store this captured variable per lambda; whereas there is no way to do that with a function pointer.
The best solution is probably to take an argument of type std::function, which is a wrapper for any callable type:
int func2(std::function<int(int)> funcptr2) {
return funcptr2(2);
}
int func1(std::function<int(int,int,int)> funcptr1) {
return func2(
[funcptr1](int i)->int {
return funcptr1(i,8,9);
}
);
}
You can also use templates to make your functions work for any callable type:
template <typename F>
int func2(F funcptr2) {
return funcptr2(2);
}
template <typename F>
int func1(F funcptr1) {
return func2(
[funcptr1](int i)->int {
return funcptr1(i,8,9);
}
);
}
In C, you can't. You would have to pass the function pointer, and the two arguments.
In C++, you can use std::bind (or boost::bind in older versions) to achieve this.

Why does this work?

I have just been working with boost::bind and boost::function and noticed the following behaviour (which I thought was a bit odd). You can bind a function with fewer parameters than required by the boost::function type! It appears as though any additional parameters are simply ignored and just fall away.
So why is this behaviour correct? My expectation would be that a compile error should be raised stating the incompatibility.
See below for working code example that shows the issue
#include "boost/bind.hpp"
#include "boost/function.hpp"
namespace
{
int binder(const char& testChar,
const int& testInt,
const std::string& testString)
{
return 3;
}
}
int main(int c, char** argv)
{
boost::function<int(const char&,
const int&,
const std::string&,
const float&,
const std::string&,
const int&)> test;
test = boost::bind(&::binder, _1, _2, _3);
std::cout << test('c', 1, "something", 1.f, "more", 10) << std::endl;
}
Isn't this the point of boost::bind - to allow you to remap the prototype of the function? You're making test be usable with 6 input parameters where your underlying function needs only 3.
This page: http://blog.think-async.com/2010/04/bind-illustrated.html has a really good overview of how boost::bind works.
It is a paradigm from functional programming, currying: http://en.wikipedia.org/wiki/Currying meaning that you transform a function taking more than 0 parameters into a function taking less parameters, with those you supplied filled in to be constant; the values you supplied.
E.g. using bind/currying you are able to do this:
// takes 2 arguments
function multiply(x,y) { return x*y; }
// make shorthand for multiply-by-two
function mult_by_two(x) = multiply(x, 2)
h.