2

I have some legacy code I'd like to rewrite in C++11 style. There are some boost::function defined as following

// void One::first(int)
boost::function<void()> a1 = boost::bind(&One::first, this, this->a); 

// void Two::second()
boost::function<void()> a2 = boost::bind(&Two::second, this); 

// void Three::third(int, const std::string &)
boost::function<void()> a3 = boost::bind(&Three::third, this, 8, str); 

These variables are passed to function foo in different places:

foo(somearg,  a1);          
foo(anotherarg, a2);
foo(othearg, a3);

where foo is defined like following

void foo(const Obj &obj, boost::function<void()> caller) {
  ...
  caller();
  ...
}

What is the best way to rewrite this code in C++11 style?

Loom
  • 9,768
  • 22
  • 60
  • 112

1 Answers1

2

To start with, simply replace boost with std, and include the C++ header <functional> instead of the Boost headers. The standard function and bind are based on, and for the most part compatible with, the Boost versions.

You could make it more generic:

template <typename Function>
void foo(const Obj &obj, Function caller) {
    //...
    caller();
    //...
}

and avoid the overhead (and, as the comments point out, obscure semantic restrictions) of the function wrapper:

auto a1 = std::bind(&One::first, this, this->a); 
foo(somearg, a1);

You might find the lambda syntax more readable than a call to bind:

auto a1 = [this]{first(a);};
Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
  • worth mentioning that the placeholders live in `std::placeholders` there. And there are _not_ compatible (as in interchangeable) – sehe Apr 13 '15 at 15:08
  • @sehe: Sorry, my language was a little loose, it's more accurate now. It's a bit early on a Monday for fully pedantic answers. – Mike Seymour Apr 13 '15 at 15:29
  • I felt compelled to downvote you for suggesting that `std::function` has some truly terrible overhead. It does not. The point of using a template has nothing to do with overhead. – Puppy Apr 13 '15 at 15:33
  • @Puppy: I didn't say it was truly terrible; please don't put hyperbolic words into my mouth. Type erasure does have an overhead: indirection, a virtual function call or similar, and possibly memory allocation (if a small object optimisation can't be applied, as it should be in this simple case). The purpose of the template is to allow generic function types without the run-time cost of type erasure. – Mike Seymour Apr 13 '15 at 16:14
  • @Puppy: Also, if you feel compelled to downvote, I'd appreciate an explanation. If it has "nothing to do with overhead," I (and perhaps other readers) would like to learn what the purpose is, when `std::function` could do the same thing, slightly more conveniently, but with slightly more overhead. – Mike Seymour Apr 13 '15 at 16:21
  • @MikeSeymour: The purpose is to respect things like move-only functors, deleted or SFINAEd overloads, and other such semantics std::function cannot properly represent. It does have an overhead but it's really rather trivial and it would have to be a pretty exceptional case to merit moving to a template purely for performance reasons. – Puppy Apr 13 '15 at 21:04
  • @puppy: Fair enough. I use templates to avoid runtime overhead rather than to enable weird semantics, but perhaps others use them for your reasons. – Mike Seymour Apr 14 '15 at 01:55