Does anyone know why this code does not compile
int main() {
int i = 7;
int j = ++i++; // error: lvalue required as increment operand
}
while this code compiles perfectly?
int main() {
Int i{7};
Int j = ++i++; // OK!
}
The class Int is defined as follows:
struct Int {
int i;
Int(int i = 0) : i{i} {}
Int& operator++() {++i; return *this;}
Int operator++(int) {Int t{*this}; ++i; return t;}
};
When I compile the first code snippet it fails with error "lvalue required as increment operand." The other one compiles and works as expected.
It comes down to the differences between xvalues and prvalues. Both are rvalues but an xvalue is also a glvalue which means one can take it's address, assign to it, and otherwise operate on it. Class types, but not native types, will convert a prvalue to an xvalue when needed.
Let's start by looking at:
Since
i++has higher precedence than++ithe last line can be re-written:While
iis an lvalue,i++is a prvalue. In this example it has a value of 7 whileiis now 8.++8is invalid since you can't increment, decrement, or assign to a prvalue.Now let's look at:
Here,
i++returns an prvalue which is then converted to an xvalue through temporary materialization. It is temporarily materialized so the pre ++ operator can now operate on it thus setting the temporary object's value to 8 and assigning it toj.