I was exploring a cppreference page about value categories and found some strange syntax in an example (the second extended content):
#include <iostream>
struct S
{
S() : m{42} {}
S(int a) : m{a} {}
int m;
};
int main()
{
S s;
// Expression `S{}` is prvalue
// May appear on the right-hand side of an assignment expression
s = S{};
std::cout << s.m << '\n';
// Expression `S{}` is prvalue
// Can be used on the left-hand side too
std::cout << (S{} = S{7}).m << '\n';
}
Look at the last line of main()
. There is an assignment S{} = S{7}
that is very awkward. We can do this even simpler:
#include <iostream>
struct S {
int m = 1;
};
int main()
{
std::cout << (S{} = S{}).m << '\n';
}
Compiler shows no warning or errors and everything is completely fine. That could be okay, but I think the documentation says it must be impossible. Quoting the same page:
An rvalue can’t be used as the left-hand operand of the built-in assignment or compound assignment operators.
I guess S{}
is a prvalue, and all other conditions are met also. So, how does C++ converts this prvalue into an lvalue?