Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

A look at the Boost Bind and Function libraries

0.00/5 (No votes)
9 Feb 2006 1  
A small introduction to the Boost Bind and Function libraries.

Introduction

If you are a C++ developer and aren�t yet familiar with the Boost libraries, I encourage you to start experimenting with it. Boost is comprised of many different libraries covering categories from generic programming to memory pool management & smart pointers. Many of the libraries are standalone thus allowing you as the developer to focus only upon those functions of interest.

The libraries are peer-reviewed portable C++ code. The libraries are free. The licensing agreements permit free redistribution satisfying the Open Source Initiative�s Open Source Definition. In order to get started, visit the Boost library website for additional details & downloads.

One last point worth mentioning before introducing the Bind & Function libraries is that all the libraries rely on advanced C++ features such as templates and the Standard Template Library (STL). Boost is designed to work with STL. In those areas where the STL and Boost overlap (i.e. Bind library), it is best to look towards Boost which will most likely have a more feature rich implementation. A large number of the Boost libraries have been included in the C++ Standard Library Technical Report as a step towards becoming part of the Standard.

Boost::bind augments the capabilities provided by the standard library functions std::bind1st and bind2nd. Typically, the syntax associated with functional composition programming can be quite daunting. Boost::bind functionality is exposed through a normalized syntax making it exceptionally easy to deal with function objects and functions. Its function adapters simplify the code you must write. You need not concern yourself with the usage of adapters such as ptr_fun, mem_fun_ref, and the like. This library adds functionality not achievable through the STL.

I have chosen to illustrate the power of the bind & function libraries by implementing the Command Pattern using static polymorphism. Dynamic polymorphism is the more commonly known mechanism obtained through the use of abstract base classes, class pointers, and virtual functions. Static polymorphism can be achieved through the use of class templates, functions, and functors.

In my opinion, one of the major benefits of this methodology is that it is vetted via the compiler as opposed to runtime checks.

/// command object

class command
{
 private:
   boost::function<void ()> _f;
 public:
   command() {;}
   command(boost::function<void ()> f) : _f(f) {;}

   template <typename T> void setFunction (T t) {_f = t ;}
   void execute()
    {
     if(!_f.empty())
    _f();
    }};

The Command class, shown in its entirety above, provides a means by which to encapsulate an action within an object. As defined, the Command class contains a private data element defined as boost::function<void ()>. The boost::function library provides function object wrappers which can serve as call interfaces and call-back mechanisms providing a safer and more capable implementation than a traditional function pointer. The declaration of a function includes the return type and the function signature. The library provides two syntax variations in order to support the largest breadth of compilers. I am using the preferred syntax which is supported under MSVC 2005 and MSVC 2003.

The preferred syntax flows nicely, replicating a function declaration. The declaration in the Command object calls for a function without any parameters returning a void. As an aside, if I wished to declare a function returning an int which took a double and an int as arguments, I would write: boost::function<int (double, int)>.

The boost::function, for the most part, can be used anywhere you would use a function pointer. The benefits come at a cost of an increased memory footprint and a small performance hit. If my recollection serves me, I have read that the use of this function can require two additional calls through function pointers.

The remainder of the class exists to support the encapsulation of the function wrapper and provide a means to invoke it. The interesting bit is in how we initialize the function pointer. That is where boost::bind comes into play.

Bind can be used to operate upon free functions as well as member functions of dynamically allocated objects. The library offers a consistent syntax when working with functions and function objects. The key to understanding bind is the concept of placeholders. The placeholders are defined as _1 through _9, and you use them where you would normally use an argument.

Let us say we wish to bind the free function void comm (std::string str) {�}. To do this, we bind to the free function, and since it expects one argument we use one placeholder.

(boost::bind(&comm, _1)) (�Isn�t this fun?�);

If the comm function is a member function, binding is still possible. You must account for the passing of the implicit �this� reference to all non-static member functions. Under these conditions, the first placeholder is for the class instance of the member function followed by the other arguments as described previously.

inFlight fly;
(boost::bind (&comm, _1,_2)) (fly, �Isn�t this fun?�);

In our sample program, we need to bind one of the member functions in our Final class to the function object wrapper within the command object. This is accomplished via:

boost::bind(&Final::decAlt, fa)

Through the constructor, the binding is then assigned to the private member function wrapper. Part 2 of the sample program extends the basic idea to show that everything remains the same when dealing with dynamically allocated objects. It also illustrates how well boost::bind works with STL algorithms such as for_each.

// PART 2

// create a series of commands and stuff them into a container to be sequenced later

vector<boost::shared_ptr<command> > v;

boost::shared_ptr<command> spCmd1(new 
       command(boost::bind(&Final::incAlt, final)));
boost::shared_ptr<command> spCmd2(new 
       command(boost::bind(&Final::decSpeed, final)));
boost::shared_ptr<command> spCmd3(new 
       command(boost::bind(&Final::decAlt, final)));

v.push_back(spCmd1);
v.push_back(spCmd2);
v.push_back(spCmd3);

// run the command sequence

for_each(v.begin(), v.end(), 
      boost::bind(&command::execute, _1));
return 0;

I hope this short introduction has sparked your interest in the Boost Library. This author has found that for each foray into the library, I am presented with another gem of a solution. It is the perfect compliment to the STL.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here