Boost logo

Boost Users :

From: TP Diffenbach (tp_at_[hidden])
Date: 2004-07-21 13:51:59


I'm having some difficulties figuring out how to use boost::bind and
boost::lambda

Here's what I've trying to do: use transform to transform the values in one
container to another, looking up the new value as a function of the old.

What I'm trying to do is conceptually simple: call std::transform with a
predicate that takes the original value, does a std::find_if on that value
in another "container" using a bound std::greater< int > predicate, converts
the returned iterator to an integral distance, and inserts that integral
distance in the container that is the destination of the transform.

Doing this using a hand-coded functor is easy enough, but I'm not able to
figure out how to do it using boost::lambda.

If I understand lambda, this should make each element of c equal to four
times the corresponding element of o, and indeed this compiles as works as
expected.

std::transform( o.begin(), o.end(), std::back_inserter( c ), _1 = _1 * 4 ) ;

This bit of code will look up a value, the index of the first element in
partition with a value greater than v (or 3 if v is greater than all values
in partition:

int partition[] = { 10, 20, 30 } ;
offset = std::find_if( partition, partition + 3, boost::bind( std::greater<
int >(), _1, v ) ) - partition ;

This code wraps the lookup and the subtraction that turns the returned
pointer into an offset:
template< template< typename > class Pred, typename It, typename T >

int find_region_offset( It b, It e, T val ) {
  return std::find_if( b, e, std::bind2nd( Pred< T >(), val ) ) - b ;
}

and this code uses the wrapper, along with the transform:

std::transform( o.begin(), o.end(), std::back_inserter( c ),
    boost::bind( find_region_offset< std::greater, int*, int>, partition,
partition + 3, _1 ) ) ;

So far, so good.

What I don't know how to do is to dispense with the wrapper. As close as I
can come is to use this class:

struct identityPred {
  int operator()( int i ) {
    return i ;
  }
} ;

to do this:

  std::transform( o.begin(), o.end(), std::back_inserter( c ),
    boost::bind(
      std::less< int* >(), // to subtract the returned pointer from
partition
      boost::bind(
        std::find_if< int*, identityPred >,
        partition,
        partition + 3,
        identityPred()
      ),
      partition)
  ) ;

This compiles, but I don't want identityPred, I want boost::bind(
std::greater< int >(), _1, _1X ) where _1 is the value in the partition
array and _1X is the value read from container o.

Ideally I'd like to do this using boost::lambda, which I think would look
something like:

std::transform( o.begin(), o.end(), std::back_inserter( c ),
   _1 = find_if(partition, partition + 3, _1 > var( _1 )) - partition ) ;

where the first and last "_1"s are transform's (containers o and c's)
values, and middle one is partition's values.

Again, what I'm trying to do is conceptually simple: call transform with a
predicate that takes the original value, does a find_if on that value in
another "container" using a bound std::greater< int > predicate, converts
the returned iterator to an integral distance, and inserts that integral
distance in the container that is the destination of the transform.

So if someone could point out to me what I'm doing wrong, or point me to
more examples of using boost::lambda than are contained in the boost::lambda
documentation, or could just tell me that what I'm trying to do isn't
possible (and why it's not possible) I'd very much appreciate it.

Thanks.

PS And a technical trouble: if I include both boost::bind and boost::lambda,
and I am using namespace boost::lambda to save qualifying each _1, I get a
type redefinition for _1, with one definition in boost::bind, when using gcc
under cygwin:

b.cpp:49: error: use of `_1' is ambiguous
/usr/local/include/boost/lambda/core.hpp:74: error: first declared as
`const
   boost::lambda::placeholder1_type&boost::lambda::<unnamed>::_1' here
/usr/local/include/boost/bind/placeholders.hpp:55: error: also declared as
`
   boost::arg<1> <unnamed>::_1' here
b.cpp:57: error: use of `_1' is ambiguous
/usr/local/include/boost/lambda/core.hpp:74: error: first declared as
`const
   boost::lambda::placeholder1_type&boost::lambda::<unnamed>::_1' here
/usr/local/include/boost/bind/placeholders.hpp:55: error: also declared as
`
   boost::arg<1> <unnamed>::_1' here

Should this be happening?


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net