So I understand that re-usage of a variable that has been post incremented is undefined behavior in a function call. My understanding is this is not a problem in constructors. My question is about tie which is oddly halfway between each.
Given: pair<int, int> func() can I do:
tie(*it++, *it) = func();
Or is that undefined behavior?
Since C++17, this code has unspecified behavior. There are two possible outcomes:
the first argument is the result of dereferencing the original iterator, the second argument is the result of dereferencing the incremented iterator; or
the first argument and the second argument are both the result of dereferencing the original iterator.
Per [expr.call]/8:
So the second argument to
tiemay be either the result of dereferencing the incremented iterator or the original iterator.Prior to C++17, the situation was a bit complicated:
if both
++and*invoke a function (e.g., when the type ofitis a sophisticated class), then the behavior was unspecified, similar to the case since C++17;otherwise, the behavior was undefined.
Per N4140 (C++14 draft) [expr.call]/8:
Thus, the code was undefined behavior because the evaluation of one argument was unsequenced with the other. The evaluation of the two arguments may overlap, resulting in a data race. Unless it is specified otherwise ...
Per N4140 [intro.execution]/15:
Thus, if the operators are actually function calls, then the behavior is similarly unspecified.