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