Tuesday, May 7, 2013

auto, The Unstoppable


/**
 * In C++03 we had a couple of binders
 * available: std::bind1st and std::bind2nd.
 * These would have to be coupled with an
 * std::mem_fun to bind class methods- This
 * was before boost::bind came into my life.
 *
 * The Boost binders are so easy to use-
 * it makes me wonder if C++11 has adopted
 * these new binders. Well it looks as if
 * they did! And now with the new "auto"
 * keyword, there's no storage of a complicated
 * boost::function object.
 */

#include <functional>

#include <boost/bind.hpp>
#include <boost/function.hpp>

class A
{
public:
A() { }

/**
* The copy constructor would be needed
* if we were binding to an object by
* value. For example, you would use:
* std::bind(&A::Go, a) instead of
* std::bind(&A::Go, &a). The latter
* passes "a" in as a pointer.
*/
A(A const&) = delete;
A& operator=(A const&) = delete;


void Go()
{
std::cout << "A::Go()" << std::endl;
}

void Go2( std::string const& p1
, int p2 )
{
std::cout << "A::Go(string, int) = ("
<< p1 << "," << p2 << ")"
<< std::endl;
}
};


int main(int argc, char** argv)
{
A a;

/**
* Example #1: Boost style bind to
* function with no parameters. Notice
* that the boost function/bind are
* really easy to read. There's a reason
* why they are popular!
*/
boost::function<void()> func1 = boost::bind(&A::Go, &a);
func1();


/**
* Example #2: This is an example of
* a boost-style binding where we take
* functions. Notice the _1 and _2 arguments,
* these are just placeholders for other
* values.
*/
boost::function<void(std::string const&,int)> func2 =
boost::bind(&A::Go2, &a, _1, _2);
func2("Hello", 12234);


/**
* Example #3: Wow, this is even cleaner than
* the boost-style binding. The binding call is
* the same, but the C++11 improvement comes with
* the use of the auto keyword. In my opinion,
* this was one of the best additions to the new
* standard.
*/
auto func3 = std::bind( &A::Go, &a );
func3();


/**
* We can also use the binders in a similar way.
* The only surprise is having to fully qualify
* the placeholders with std::placeholders. This
* is only because we also included the boost
* versions of the placeholders. In reality, you'd
* never use both boost and std binders in the
* same file.
*/
auto func4 = std::bind( &A::Go2
, &a
, std::placeholders::_1
, std::placeholders::_2 );
func4("Daisy", 3);
}

/**
 * In conclusion, the std::bind seems to be just as powerful
 * as the boost version. Combined with the auto keyword,
 * the only word I can come up with is "Unstoppable". This
 * is a coding gift that will keep on giving. There is
 * one shortcoming: when I originally wrote this example,
 * Go2 was also named Go (overloading). The std::bind did
 * not handle this case- but boost bind did.
 *
 * If you wanted that functionality, there is nothing stopping
 * you from using the boost::bind function with the "auto"
 * keyword. That would be pretty good too!
 */

No comments:

Post a Comment