I dislike having magic boxes scattered all over my code...how exactly do these two classes work to allow basically any function to be mapped to a function object even if the function<> has a completely different parameter set to the one im passing to boost::bind
It even works with different calling conventions (i.e. member methods are __thiscall
under VC, but "normal" functions are generally __cdecl
or __stdcall
for those that need to be compatible with C.
boost::bind is a generalization of the standard functions std::bind1st and std::bind2nd. It supports arbitrary function objects, functions, function pointers, and member function pointers, and is able to bind any argument to a specific value or route input arguments into arbitrary positions.
boost::function makes it possible to define a pointer to a function with a specific signature. Example 40.1 defines a pointer f that can point to functions that expect a parameter of type const char* and return a value of type int .
std::bind. std::bind is a Standard Function Objects that acts as a Functional Adaptor i.e. it takes a function as input and returns a new function Object as an output with with one or more of the arguments of passed function bound or rearranged.
Bind function with the help of placeholders helps to manipulate the position and number of values to be used by the function and modifies the function according to the desired output.
boost::function
allows anything with an operator()
with the right signature to be bound as the parameter, and the result of your bind can be called with a parameter int
, so it can be bound to function<void(int)>
.
This is how it works (this description applies alike for std::function
):
boost::bind(&klass::member, instance, 0, _1)
returns an object like this
struct unspecified_type
{
... some members ...
return_type operator()(int i) const { return instance->*&klass::member(0, i);
}
where the return_type
and int
are inferred from the signature of klass::member
, and the function pointer and bound parameter are in fact stored in the object, but that's not important
Now, boost::function
doesn't do any type checking: It will take any object and any signature you provide in its template parameter, and create an object that's callable according to your signature and calls the object. If that's impossible, it's a compile error.
boost::function
is actually an object like this:
template <class Sig>
class function
{
function_impl<Sig>* f;
public:
return_type operator()(argument_type arg0) const { return (*f)(arg0); }
};
where the return_type
and argument_type
are extracted from Sig
, and f
is dynamically allocated on the heap. That's needed to allow completely unrelated objects with different sizes bind to boost::function
.
function_impl
is just an abstract class
template <class Sig>
class function_impl
{
public:
virtual return_type operator()(argument_type arg0) const=0;
};
The class that does all the work, is a concrete class derived from boost::function
. There is one for each type of object you assign to boost::function
template <class Sig, class Object>
class function_impl_concrete : public function_impl<Sig>
{
Object o
public:
virtual return_type operator()(argument_type arg0) const=0 { return o(arg0); }
};
That means in your case, the assignment to boost function:
function_impl_concrete<void(int), unspecified_type>
(that's compile time, of course)When you call the function object, it calls the virtual function of its implementation object, which will direct the call to your original function.
DISCLAIMER: Note that the names in this explanation are deliberately made up. Any resemblance to real persons or characters ... you know it. The purpose was to illustrate the principles.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With