STL and Lambda Expression

I don't understand why my commented lambda expression doesn't work as expected (when uncommented, of course :-)). The function returns a vector<int> of random numbers and the offending statement is supposed to scale each of the initial random values in the vector to the range (1, die).

Is it because the for_each is passing an iterator to the lambda?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
vector<int> RMRandom::Dice(unsigned quantity, unsigned die)
{
	vector<int> results(quantity, 0);
	
	generate(results.begin(), results.end(), rand);

	for_each(results.cbegin(), results.cend(),
		[](const int element) {cout << element << " / "; });
	cout << endl;

	// I don't understand why this lambda expression doesn't modify the vector
//	for_each(results.begin(), results.end(),
//		[](int& element)  {return element * 100 / RAND_MAX; });

	// instead I have to do it the old-fashioned way
	// Iterate through the vector and normalize the random numbers to (1, 100]
	for (auto element = 0; element != results.size(); element++)
	{
		results[element] = results[element] * 100 / RAND_MAX;
	}
//	for (auto element : results) 
//		results[element] = results[element] * 100 / RAND_MAX;

	return results;
}


I also believe that's the fundamental problem with the for-range statement at the end.

There certainly may be other problems and better implementations. I appreciate comments and advice but my first issue is understanding the use of lambda expressions in for_each statements with the STL.
Last edited on
// I don't understand why this lambda expression doesn't modify the vector
1
2
//	for_each(results.begin(), results.end(),
//		[](int& element)  {return element * 100 / RAND_MAX; }); 


You don't modify element inside the lambda and for_each doesn't care about a return value of the function it calls.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <iostream>
#include <vector>
#include <algorithm>
#include <iomanip>

int main()
{
    std::vector<int> results { 1, 2, 3, 4, 5, 6 } ;
    for( int v : results ) std::cout << std::setw(4) << v ;
    std::cout << '\n' ;

    // modify elements with a range based loop 
    for( int& v : results ) v *= 100 ;
    for( int v : results ) std::cout << std::setw(4) << v ;
    std::cout << '\n' ;

    // modify elements with std::for_each 
    std::for_each( results.begin(), results.end(), [] ( int& v ) { v /= 5 ; } ) ;
    for( int v : results ) std::cout << std::setw(4) << v ;
    std::cout << '\n' ;

    // modify elements with std::transform 
    std::transform( results.begin(), results.end(), results.begin(),
                    [] ( int v ) { return v / 5 ; } ) ;
    for( int v : results ) std::cout << std::setw(4) << v ;
    std::cout << '\n' ;
}

http://coliru.stacked-crooked.com/a/4f2894881e1105c9
http://rextester.com/UZGOKP91835
Thanks to you both.

You don't modify element inside the lambda and for_each doesn't care about a return value of the function it calls.

...but a std::transform does. Ok, it seems so clear now you put it that way :-). I think I understand how using for_each with a function object should work (because it would return void) but the lambda had me confused, although it, too, should return the equivalent of void (or whatever it does). So, for a for_each, it should be:

1
2
for_each(results.begin(), results.end(),
	[] (int& element) {element = element * 100 / RAND_MAX; });

But for std::transform it would be:

1
2
transform( results.begin(), results.end(), results.begin(),
        [] (int element) {return element *100 / RAND_MAX ;});

Am I understanding correctly?

yes, std::transform() wants you to return the new value so it can write it itself.

loops tend to give you a reference to write yourself.
Topic archived. No new replies allowed.