Some code samples I have collated in the sample below, that demonstrate how boost::function can be assigned with functors, ordinary functions, class member functions and overloaded class member functions respectively.
#include <iostream>
#include <boost/function.hpp>
#include <boost/bind.hpp>
using namespace std;
// Class for example 1: functors
class int_div
{
public:
float operator()(int x, int y) const { return ((float)x)/y; };
};
// Class for example 2: : accessing functions
float average( int values[], int n )
{
int sum = 0;
for (int i = 0; i < n; i++)
sum += values[ i ];
return (float) sum / n;
}
// Class for example 3: accessing class members
class DoStuff
{
public:
void DoThis() { std::cout << "Do this" << std::endl; }
void DoThat( std::string message ) { std::cout << message << std::endl; }
};
// Class for example 4: overloaded class members
class Overload
{
public:
void Foo( int x ) { std::cout << "Integer = " << x << std::endl; } ;
void Foo( float x ) { std::cout << "Float = " << x << std::endl; } ;
};
int main()
{
// Example 1: function assigned to function object (functor):
int_div div;
boost::function<float (int x, int y)> f1 = int_div();
std::cout << "5 / 3 = " << f1(5, 3) << std::endl;
// Example 2: function assigned to normal function, with/without boost::bind:
// f2 - arguments supplied later
// f3 - arguments supplied later
// f4 - arguments supplied straight in placeholder
int vals[] = { 1, 10, 100 };
boost::function<float (int[], int)> f2 = &average;
boost::function<float (int[], int)> f3 = boost::bind( &average, _1, _2 );
boost::function<float ()> f4 = boost::bind( &average, vals , 3 );
std::cout << "Average = " << f2( vals, 3 ) << std::endl;
std::cout << "Average = " << f3( vals, 3 ) << std::endl;
std::cout << "Average = " << f4() << std::endl;
// Example 3: function assigned using boost::bind to access class member
// via value and pointer
// onClick1 - pass by value
// onClick2 - parameter not binded straight away, supplied later
// onClick3 - supplied in placeholder, with "Do other" string
DoStuff doStuff1;
DoStuff* doStuff2 = new DoStuff();
boost::function<void()> onClick1 = boost::bind( &DoStuff::DoThis, &doStuff1 );
boost::function<void(string)> onClick2 = boost::bind( &DoStuff::DoThat, doStuff2, _1 );
boost::function<void()> onClick3 = boost::bind( &DoStuff::DoThat, doStuff2, "Do other" );
onClick1();
onClick2( "Do that" );
onClick3();
delete doStuff2;
// Example 4: function assigned using using boost::bind to access overloaded class member
// use casting via static_cast<void(Overload::*)(type)>
// int1 - integer supplied later
// float1 - float supplied later
// float2 - float supplied in placeholder
Overload over;
boost::function<void(int)> int1 =
boost::bind( static_cast<void(Overload::*)(int)>(&Overload::Foo), over, _1);
boost::function<void(float)> float1 =
boost::bind( static_cast<void(Overload::*)(float)>(&Overload::Foo), over, _1);
boost::function<void()> float2 =
boost::bind( static_cast<void(Overload::*)(float)>(&Overload::Foo), over, 111.1 );
int1( 11 );
float1( 11.11 );
float2();
return 0;
}
Giving the following output:
5 / 3 = 1.66667
Average = 37
Average = 37
Average = 37
Do this
Do that
Do other
Integer = 11
Float = 11.11
Float = 111.1
The next example shows how we can wrap this kind of functionality within a class, providing additional means with which to invoke it and set it etc. In addition, Boost smart pointers (boost::shared_ptr) are used to automatically take care of garbage collection.
#include <iostream>
#include <vector>
#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
class BoostCommand
{
private:
boost::function<void()> f;
public:
BoostCommand() {}
BoostCommand( boost::function<void()> f ) : f( f ) {}
void execute()
{ if ( !f.empty() ) f(); }
};
class DoStuff
{
public:
DoStuff() {}
void DoThis() { std::cout << "Do this" << std::endl; }
void DoThat() { std::cout << "Do that" << std::endl; }
void DoNothing() { std::cout << "Do nothing" << std::endl; }
void DoOther( std::string txt) { std::cout << txt << std::endl; }
};
int main()
{
// Use the boost smart pointers for automatic garbage collection
boost::shared_ptr<DoStuff> doStuff(new DoStuff);
std::vector<boost::shared_ptr<BoostCommand>> v;
boost::shared_ptr<DoStuff> doIt(new DoStuff);
boost::function<void()> f1 = boost::bind( &DoStuff::DoThis, doStuff );
boost::function<void()> f2 = boost::bind( &DoStuff::DoThat, doStuff );
boost::function<void()> f3 = boost::bind( &DoStuff::DoNothing, doStuff );
boost::function<void()> f4 = boost::bind( &DoStuff::DoOther, doStuff, "Do other" );
// Create and insert functions into vector
boost::shared_ptr<BoostCommand> bc1( new BoostCommand( f1 ) );
boost::shared_ptr<BoostCommand> bc2( new BoostCommand( f2 ) );
boost::shared_ptr<BoostCommand> bc3( new BoostCommand( f3 ) );
boost::shared_ptr<BoostCommand> bc4( new BoostCommand( f4 ) );
v.push_back( bc1 );
v.push_back( bc2 );
v.push_back( bc3 );
v.push_back( bc4 );
for_each( v.begin(),
v.end(),
boost::bind( &BoostCommand::execute, _1 ) );
return 0;
}
Giving the following output:
Do this
Do that
Do nothing
Do other