Partial binding with boost::bind

226 Views Asked by At

so what I have is:

Two ranges of elements:

std::vector<int> v1;
std::vector<string> v2;

Function that accept elements from theese ranges:

void bar( int x, std::string str );

And what I wanna do is to apply handler to each pair from product of v1 and v2. So I got something like this:

using namespace boost;
for_each( v1, [&]( int x )
    { for_each( v2, bind( bar, x, _1 ) ); } 
);

That's OK, but I got to replace lambdas with smth else since they are part of C++11 standart and some of potential users of this code are still on C++98. I've replaced lambda with functor, but then I wondered if it is possible to rewrite it in oneline style, without additional objects and/or functions. Functor variant is just fine, but I wanted to complete exploration here :)

So what I wanted is something like that:

for_each( v1, for_each( v2, bind( bar, ???, _1 ) ) );

My first thought was to bind inner for_each to recieve function with signature like void(int) , but it got hard to me since for_each have only two parameters - string range and functor that accepts one argument - string. That means for me that I got to use bind composition here to expand for_each signature so it will recieve int element from first range. After some work with taking address from boost::for_each, I came to this code:

typedef boost::function<void(std::string)> StrFunc;
typedef std::vector<std::string> StrRange;

StrFunc maker(int i) {
    return bind( bar, i, _1);
}

for_each(
    v1,
    bind(
        static_cast< StrFunc (*) (const StrRange&, StrFunc)>( 
            for_each<StrRange, StrFunc> ),
        v2,
        bind( maker, _1 )
    )
);

This code works too - unary callable object is made by maker() function and its argument is binding composively to inner for_each. But I still have helper function. When I tried to get rid of it, I have faced problem, that seems insoluble to me:

for_each(
    v1,
    bind(
        static_cast< StrFunc (*) (const StrRange&, StrFunc)>( 
            for_each<StrRange, StrFunc> ),
        v2,
        bind( bar, _1, _1 ) //wat?
    )
);

So, first binding argument of bar() needs to be _1 for composing with outer bind. But second argument of bar() also needs to be _1 for inner for_each to use binded function in cycle. So, now I need to somehow bind first argument composively, and protect second argument from evaluating in bind-time.

Most relevant question that I found is here, but seems like it won't help either.

Any ideas guys?

1

There are 1 best solutions below

1
On

Why can't you just do something as simple as:

BOOST_FOREACH(int v, v1 ) { BOOST_FOREACH(string &s, v2) { bar(v, s); } }