Using boost::bind to assign functions

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

Leave a Reply