SUMMARY
I stumbled upon the implementation of std::transform and I could not figure out why it works in the case where we transform a container in-place. In particular, I found this expression confusing *d_first++ = unary_op(*first1++);.
CODE
Using the first implementation of std::transform found here https://en.cppreference.com/w/cpp/algorithm/transform, I wrote this sample code:
#include <iostream> template< class InputIt, class OutputIt, class UnaryOperation > OutputIt transform( InputIt first1, InputIt last1, OutputIt d_first, UnaryOperation unary_op ) { while (first1 != last1) { *d_first++ = unary_op(*first1++); } return d_first; } int main() { int arr[5] {1,2,3,4,5}; transform(std::begin(arr),std::end(arr), std::begin(arr), [](auto i){return i*i;}); for (auto& elem : arr) std::cout << elem << std::endl; return 0; } ATTEMPT FOR AN EXPLANATION
After doing some reading in the C++ standard, Cpp reference, and SO, I think I might be able to explain what happens in that confusing (for me) statement. Let's decompose this expression:
*d_first++ = unary_op(*first1++); // same as A = B; - First resolve what is happening on
B, which is,unary_op(*first1++) - Now resolve the parentheses
*first1++which means*(first1++)which means a) make a copy of the dereferencedfirst1and b) pass it to the function, then c) increment the iterator. - The copied dereferenced
first1is multiplied by itself inside theunary_op. - Now
Bis evaluated, time to deal with the assignment. - Assign
Bto the dereferenced value ofd_first. - When this assignment is complete, and before we go to the next statement (whatever that may be) increment the
d_firstiterator.
This way, the two iterators are "on the same page", meaning at the same position of the arrays which they iterate.
QUESTIONS
My questions are:
A) Is the above explanation correct?
B) Which operations in that expression are evaluations and which computations?
C) Since *first1++ translates to *(first1++) but the dereferencing happens before the incrementation, isn't that confusing to remember? However, (*first1)++ would mean something totally different, i.e. dereference first1 and pass it to the function and then increment this value by one; not the iterator! Any hints to remember how to untangle myself in such expressions?
++. It's that copy that gets dereferenced.first1++which is the one before the incrementation.