Now let’s go wild. One problem that everyone runs into sooner or later with C++ is that passing functions to other functions is hard. You sometimes want to pass in a function that happens to be a template, or happens to have a default argument, or maybe is part of an overload set, or can only be found with ADL… and in all those cases, just passing in foo isn’t going to cut it. In the worst case, you do manual overload resolution yourself on which foo you had intended to call, which possibly involves doing template deduction by hand too. The better way to do it is to write a macro which lifts your name into a function object that you can actually pass around. In Boost.HOF, this is BOOST_HOF_LIFT . This handles most of the cases you will run into.

But not all the cases. There is one case that I wanted to walk through here, which is this: I want to call a member function (that is a template or overloaded or …), but either the class instance will be passed into me (so I can’t just write BOOST_HOF_LIFT(obj.mem) or equivalent) or I do have the class instance but I am getting it from a function that my function object needs to own. The motivation example of the paper proposing bind_front is:

bind_front(&Strategy::process, createStrategy())

This function object needs to own the Strategy (and not call createStrategy() every time!). This works fine if process is a simple, non-overloaded, non-template function. But.. what if it’s not? I want to provide something to that first argument of bind_front that just works.

What do I mean by just works? Let’s call this function f . What I want f(p, a, b, c, ...) to mean is:

If p is a pointer to Strategy or a type derived from Strategy , then p->process(a, b, c, ...)

is a pointer to or a type derived from , then If p is a reference to Strategy or a type derived from Strategy , then p.process(a, b, c, ...)

is a reference to or a type derived from , then If p is a reference_wrapper of Strategy or a type derived from Strategy , then p.get().process(a, b, c, ...) . This one I’ll even extend to any type implicitly convertible to a reference to Strategy .

is a of or a type derived from , then . This one I’ll even extend to any type implicitly convertible to a reference to . If p is a smart pointer to Strategy or an iterator to Strategy or any other kind of thing that p->process(a, b, c, ...) invokes process on a Strategy , then that.

In other words, this is a fairly complex series of potential behaviors that all kind of sums up to: just do what I mean. We want to support both Strategy and SpecialStrategy , because that’s how normal function calls work. We want to support pointers and references, because that’s too specific otherwise. And we want to support unique_ptr<Strategy> and vector<Strategy>::iterator and reference_wrapper<Strategy> because we want to be as useful as possible.

Daunting.

As before, let’s just break it down into small pieces. Let’s start with the pointer case. We can’t have the class instance argument be deduced (i.e. have type auto ) because we want to ensure that we are calling Strategy::process and not SomeOtherThingEntirely::process . We could deduce a pointer and check that this pointer is convertible to Strategy const* , but I’m just going to take the easy road here and write two functions: one for Strategy* and one for Strategy const* . We could use first_of here and ensure that we write the non-const overload first, but these cases are mutually exclusive so we’ll use best-match instead of first-match. In HOF, that is spelled match :

Okay, cool. Now, let’s do the reference case. Here, I am deliberately not deducing the class instance argument because I want the reference case to just work for reference_wrapper . reference_wrapper<T> is implicitly convertible to T& , so having the instance argument not be a template parameter allows this conversion to happen.

We need to write out the four cases, which is a bit repetitive. Using match instead of first_of means we don’t have to carefully reason about what the right order is:

So far so good. Now, we’re just left with the smart pointer case. How do we do this one?

What we want to do is say that if p.operator->() is a pointer to some kind of Strategy , just fall back to the pointer case we already have. In other words, recursively call ourselves. There’s an adapter for that too! It’s called fix . It adapts all of the functions you provide it to take additionally as their first argument the instance of the combined function object. This idea is also known as a Y-combinator, or a fixed-point combinator.

Rather than showing this final step separately, I’m going to show this all put together. Note that the pointer and reference cases gained an extra argument which they do not use:

Now that’s already pretty cool to me. Here’s this fairly complex requirement set that we can just methodically break down into little pieces. We know how to write those little pieces, and we know how to put those pieces together — it’s really the power of higher order functions at how elegant this ends up being.

Indeed, as Paul points out, rather than three cases (pointer, reference, smart pointer), we can simplify this further to only have two cases: reference and dereference:

Of course, I’m not going to write a 17-line thing whenever I need to do something like this. To make this practical, I will have to resort to writing a macro:

And now, the motivating example for bind_front becomes:

bind_front(CLASS_MEMBER(Strategy, process), createStrategy())

which works even if process is overloaded, or a function template, or takes default arguments. It works if we pass it a pointer, or a reference, or a smart pointer, or an iterator, or a reference_wrapper .

Pretty cool stuff!