Sign in to follow this  
transformation

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

Recommended Posts

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.

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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' );
}

Share this post


Link to post
Share on other sites
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...

Share this post


Link to post
Share on other sites
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]

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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++;
}

Share this post


Link to post
Share on other sites
I would argue that you shouldn't use std::for_each to *initialize* values anyway. Look at std::fill, std::iota (as mentioned, but not actually in the C++ standard library), std::generate, std::transform, etc. instead.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this