You are misinterpreting GCC's error message:
<source>:5:8: error: lvalue required as increment operand
++i++;
^
Note where the error message is pointing: the postfix++ part.
The token sequence ++i++
will, by C/C++'s operator precedence rules, be interpreted as ++(i++)
. So the postfix++ happens first.
The postfix++ operator does two things. It returns the current value of the operand and it increments the operand... in that order (conceptually). This means that, when i++
returns something, what it returns is not i
. It has no relationship to i
. It's not a variable; it's just an int
.
The ++prefix operator is defined to do two things: increment the operand it is given and return the operand... in that order (again, conceptually).
Here's the thing though: incrementing an operand requires that the operand is a variable (or a reference in C++). That is, the operand must be a thing that is assignable, that can go on the lefthand side of an assignment. Thus, such a thing is called a "lvalue".
You cannot call either increment operator on something that isn't an lvalue. It simply doesn't make sense. It's about as reasonable as wanting to do 5 += 3
; you cannot change the value of 5. You can compute 5 + 3
, but you're not changing the value of 5 or 3. You are computing a new value, which is neither 5 nor 3. Such values cannot appear on the lefthand side of an assignment; they can only appear on the righthand side. Thus, they are called "rvalues".
Postfix++ returns an rvalue. It must return an rvalue, because that is the nature of the operation. Remember: by the time postfix++ is done, the lvalue has been changed. But the result of the expression is the previous value. Therefore, that value must be a new value, divorced from the variable that was used to generate it. There is no variable which holds this value; therefore, what postfix++ generates is an rvalue.
And you cannot increment an rvalue expression. This is why ++5
does not work. And ++(i++)
does not work for the same reason.
This is all necessary by the nature of what postfix++ means. The only way to change this would be to make postfix++ return an lvalue. But the only lvalue it has is its operand. And by the time an expression that consumes postfix++ sees the resulting lvalue, that variable will have been changed.
And that would make postfix++ behave exactly like ++prefix. So there would be no reason to have both.
There's no way around it. If you want postfix++ to actually do what postfix++ does, then ++i++
must be nonsensical code.
Now, could you redefine the meaning of assignment-like operations, so that you could make 5 += 3
simply become the equivalent of 5 + 3
? That is, assignment to rvalues simply computes a new value (5 = 3
evaluates to the expression 3
). In theory, yes.
However, if a user writes something like ++(i++)
, you need to ask yourself a question: what did they intend to have happen?
If I pretend not to know much about C++, when I see that expression, I would expect the value of i
to be incremented twice, and that the result of the expression will be the current value of i
. But that's not what would happen under those rules. The i++
part would return the original value of i
(which again, is why postfix++ exists to begin with). So the ++prefix will increment this value, resulting in i
only being incremented once. And the result would be the original value incremented once.
Similarly, 5 += 3
becoming 5 + 3
seems weird. That looks like a case of the compiler saying, "What you said doesn't make sense, so I'm going to guess at what you meant to say." And that's always a dangerous road to walk.
++i
would evaluate before being sent.++i++
is an error by the current definition of C. The language could easily be changed to have an explicit rule for this expression (produce the value((i+=2),i-1)
), but given how often it would be used, it's hardly worth the effort.