boost.lamda problems. want to increment a var inside an expression. is it possible?

Started by
9 comments, last by Zahlman 17 years, 6 months ago
aloha, I'm currently toying with boost.lamda and I'm trying to get something to work which I can't seem to do... First of all, not using lambda, let me show you wnat I'm trying to do:

void a( std::string& v ) {
  static int x = 0;
  v = boost::lexical_cast(x++);
}

void b( std::string v ) {
  std::cout << v << std::endl;
}

int main() {
  std::vector<std::string> v(5);
  std::for_each( v.being, v.end(), a );
  std::for_each( v.being, v.end(), b );
}
So just assign a string representing a number that is incrememnted each time it is assigned to the objects in the vector of strings. Now with boost.lambda I need to get the "a" function working, but can't seem to do so, so far I've tried the following but keep on getting errors, either they don't compile or the variable x is not incremented. I've defined x as an int in the code

// assume for_all is defined as 
// #define for_all( o, x ) for_each( o.begin(), o.end(), x )
int x = 0;
for_all( v, (_1 = lexical_cast<std::string>(_2++)(_1, x) ) );
for_all( v, (_1 = bind( lexical_cast<std::string>(), x++ ) ) );
for_all( v, (_1 = lexical_cast<std::string>(x), (_1 += 1)(x) ) );
for_all( v, (_1 = lexical_cast<std::string>(x), (*_1 += 1)(&x) ) );
for_all( v, (_1 = lexical_cast<std::string>(x), boost::lambda::var(x) += 1 ) );
for_all( v, (_1 = lexical_cast<std::string>(x), bind(x,_1) += 1 ) );
for_all( v, _1 = lexical_cast<std::string(x), bind(std::plus<int>(), x) );
for_all( v, _1 = lexical_cast<std::string>(x++) );
Can anyone help me out? Is something like what I'm trying to do even possible with lambda? Thank you.
Advertisement
std::for_each( v.begin(), v.end(),                _1 = bind( &boost::lexical_cast<std::string,int>, var(x)++ )              );


You can't just use a function inside a lambda expression - you were on the right track to use bind, only you didn't instantiate with both template arguments.

Also, boost::lexical_cast is not a functor, so you don't specify () as when passing a function object - just plain function address.
I'm all about using the STL algorithms like for_each, however, I would think about what you are doing. I don't know how large your list is, but you are looping over your list 8 times just so you can use for_each inline functor creation via lambda.

I would probably just make a regular old-fashion functor that applies all the steps so you only have to do a single for_each loop.
<a href="http://www.slimcalcs.com>www.slimcalcs.com
Thanks deffer! That bind stuff really twsited my head around...

scottdewald: You could probably do that with one for_each as well: something like:

std::for_each( v.begin(), v.end(),                  ( _1 = bind( &boost::lexical_cast<std::string,int>, var(x)++ ),                  std::cout << _1 << '\n' )                 );


And no need for a functor

And plus, I was just doingthis for experimental reasons... learning how to use lambda that's all.

Why don't you have a vector of integers?

int main(){  std::vector<int> v(5);  //...  std::for_each( v.begin(), v.end(), std::cout << _1++ << '\n' );}
Quote:Original post by scottdewald
I'm all about using the STL algorithms like for_each, however, I would think about what you are doing. I don't know how large your list is, but you are looping over your list 8 times just so you can use for_each inline functor creation via lambda.

I would probably just make a regular old-fashion functor that applies all the steps so you only have to do a single for_each loop.


I think he just wrote 8 different ways he tried to write the loop, none of which compiled for him...
Quote:Original post by scottdewald
I'm all about using the STL algorithms like for_each, however, I would think about what you are doing. I don't know how large your list is, but you are looping over your list 8 times just so you can use for_each inline functor creation via lambda.


I think the 8 loops he posted were just separate attempts to get it right. You are however entirely justified in your admonition. Just because boost::lambda is available doesn't mean all your functors should be replaced by boost::lambda constructs. In my opinion, anything more complex than a single expression should probably be written as a standalone function object.

Quote:I would probably just make a regular old-fashion functor that applies all the steps so you only have to do a single for_each loop.


boost::lambda can create function objects that are composed of multiple statements, but I personally cringe at having to learn and make extensive use of a not-quite-C++ syntax when an equivalent block of real C++ code would be just as simple to write. boost::lambda is very good when you have functors flying around that you want to combine, producing more fuctores. But I find it suboptimal from both the implementor and maintainer's points of view when it comes down to just writing a simple block of code.

Since the OP is just experimenting, there's no harm done, but you need to remain aware of the risk of overcomplicated nested expressions and write-only code in general. The risk was already there with the standard binders (std::bind1st, std::bind2nd, std::mem_fun...); boost::lambda increases it tenfold.

Quote:Original post by RDragon1
Why don't you have a vector of integers?


Why bother when you could use a iota functor. [grin]
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
Quote:Original post by Fruny
Quote:Original post by RDragon1
Why don't you have a vector of integers?


Why bother when you could use a iota functor. [grin]


Why would I need itoa? cout can output an integer just fine.
std::iota is an SGI STL extension.

template <typename iterator, typename T>void iota(iterator first, iterator last, T value){   while (first != last) *first++ = value++;}
Oops, I read it as 'itoa'

This topic is closed to new replies.

Advertisement