Mordachai
Mordachai

Reputation: 9662

how do I compose multiple functors using boost bind?

I've got a situation where I have a series of member functions which produce simple information on a target object:

double MyDoc::GetX(thing)
double MyDoc::GetY(thing)
etc.

I've made some "pretty formatting" member functions in the same class:

string MyDoc::PrintOne(thing, std::function<double (THING*)>)

You'll notice that the pretty-printer function takes a data-function - i.e. it is composable so that I can create various types of information about a target and produce a "pretty print" string for it.

In direct usage, this technique works beautifully.

However, what I really want for my current application is to compose multiple layers of such entities - i.e. effectively create a functor (function object) for the above composition as a whole, such that I can specify pretty-printer function, and it's data-acquisition function, and call that later. Pattern is z(x) -> f(x, g(x)):

auto Z = [&] (THING* thing) {
    return boost::bind(
        &MyDoc::PrintOne,
        this,
        _1,
        boost::bind(MyDoc::GetX, this, _1));
}

And here is where I run into problems. I am going in circles trying to get the syntax right, or maybe I'm getting confused with the boost::bind syntax versus the C++ lambda syntax, or maybe I'm just fundamentally misunderstanding something?

Basically, I want to compose a function Z which takes a THING* and another function X which also takes a THING* and, using logic of its own, produces a string output for a given THING*.

I have variations - some take two data-accessor type functions, or maybe a bool + data accessor. Doesn't really matter - the bottom line should be the same:

How do I compose Z where Z -> F(x, G(x))?

Thanks for any and all help!

Upvotes: 2

Views: 1923

Answers (1)

ildjarn
ildjarn

Reputation: 62995

boost::bind (and std::bind) eagerly evaluates nested bind expressions, so what you have would match a signature string MyDoc::PrintOne(THING*, double). To prevent eager evaluation and return the nested bind expression directly (suitable for constructing a std::function<>), use boost::protect:

boost::bind(
    &MyDoc::PrintOne,
    this,
    _1,
    boost::protect(boost::bind(&MyDoc::GetX, this, _1))
)

This is outlined in the section of the documentation titled "using nested binds for function composition".

Upvotes: 2

Related Questions