Click to enlarge lambda for_each / transform puzzle

Does anyone know why

vector<int> test(10); int a=0; for_each(test.begin(),test.end(),(_1+=var(a),++var(a))); for_each(test.begin(),test.end(),(cout << _1 << " ")); cout << "\n" 

Gives: "0 1 2 3 4 5 6 7 8 9"

but

  transform(test.begin(),test.end(),test.begin(), (_1+=var(a),++var(a))); ...(as before) 

Gives: "1 2 3 4 5 6 7 8 9 10"

?

+4
source share
3 answers

The comma operator evaluates from left to right, so the result

 _1+=var(a), ++var(a) 

is ++ var (a), which you will store with the conversion version.

  • for_each:

    _1 + = var (a) is evaluated by updating your sequence (via lambda _1), then ++ var (a) is evaluated, but this does not affect your sequence.

  • conversion:

    _1 + = var (a) is evaluated, updating your sequence (as before), then ++ var (a) is evaluated, this also gives the result of the whole expression, and then is used to update your sequence again (via conversion)

+9
source

Essentially, in for_each you provide a function with a side effect, while transform uses the returnvalue value for the function.

In your case, you reuse the same function. Since operator += has a return value, this is the one that is used as a result of the conversion.

+2
source

conversion (test.begin (), test.end (), test.begin (), (-1 + = Var (a), ++ Var (a)));

This will translate to

 int doit(int & elem) { elem += a; return ++a; } for each elem : elem = doit(elem); 

Starting with a = 0, the result will be 1 in the first run. We increase 10 times, so in the last run we get 10.


for_each (test.begin (), test.end (), (_ 1 + = Var (a), ++ Var (a)));

This will translate to

 void doit(int & elem) { elem += a; ++a; } for each elem : doit(elem); 

Starting at a = 0, we get 0 in the first run. We increase 10 times, but assign it immediately before the increment. So the last number is 9.

Hopefully it’s now clear that the translation into the usual functions is what these two do.

+2
source

All Articles