I have been delving into the intricacies of C++ recently, and there's a specific behavior that has puzzled me: the rules and behaviors around temporaries, especially regarding taking their address and assigning to them.
Assignment to Temporaries: Furthermore, I observed that I can assign to non-const temporaries of UDTs:
Rational a(1, 2), b(3, 4), c(5, 6);
(a * b) = c; // This line compiles
However, attempting to assign to the result of a function returning by value (which is an r-value) with built-in types leads to a compile error:
int f(int x, int y) {
return x;
}
int main() {
f(10, 5) = 12; // This line won’t compile
}
My Questions: Assignment to Temporaries: How is it possible to assign to a non-const temporary of a UDT? Is this behavior consistent, and should it be used or avoided in practice? I've searched through various resources and haven't found a satisfactory explanation for these behaviors. Could someone please shed some light on these issues?
Thank you in advance!
The sole reason is that the built-in operators have certain requirements when it comes to the value category of the operand.
- [expr.ass] p1
- [expr.unary.op] p3
Fr example,
&4isn't valid because4is a prvalue.Operator overloads can bypass these rules because
&some_rationalsimply translates into a function call. IfRationalhas an overloaded&operator, you can do&Rational{}which would take the address of a prvalue. IfRationalhas an overloaded=operator (all class types do, actually), you can doRational{} = ...which assigns to a prvalue. These expression aren't possible for the built-in&and=operator.Note that you can disable this behavior using ref-qualifiers:
Since
const&can bind to temporary objects, it is not possible to achieve the same for a member function with aconstqualifier. The closest you could get is using C++23's explicit object parameters: