Reputation: 2724
There is very simple UB example:
int i = 1;
i = i++; // classic example of UB.
I recently saw, how to use Pascal style inc
operation. Eric Niebler github
// this structure little difference than original.
struct inc_t
{
template< typename T>
T operator()(T& t ) const { return t++; }
};
constexpr inc_t inc{};
//usage
int i = 1;
inc(i);
//or
int j = inc(i);
So, combine :
int i = 1;
i = inc(i); // Is there still UB ?
Thanks.
Upvotes: 2
Views: 128
Reputation: 119099
No.
i = i++
is UB because it's not specified when i
is incremented; it could be at any point after the value computation of i++
(i.e., lvalue-to-rvalue conversion of i
) and before the end of the full-expression. Therefore this write is unsequenced with respect to the assignment statement. Two unsequenced writes to the same int
is undefined behaviour.
But in i = inc(i)
the incrementation of i
occurs before the function returns, because the full-expression in which t++
occurs lies inside the function. In turn, the function has to return before the value computation of the right-hand side, and the assignment is sequenced after the value computation of both sides. Therefore the incrementation of i
is sequenced before the assignment, and there is no UB.
Relevant quotes from the C++11 standard:
§1.9/14
Every value computation and side effect associated with a full-expression is sequenced before every value computation and side effect associated with the next full-expression to be evaluated.
§5.17/1
In all cases, the assignment is sequenced after the value computation of the right and left operands, and before the value computation of the assignment expression.
Upvotes: 9