Let there be some code in which the user-defined type S is defined by the class, in which the addition and postfix increment operations are implemented:
#include <iostream> class S { public: S(int v = 0) : val(v) {} int GetVal() { return val; } S operator++(int) { S temp = *this; ++val; return temp; } S operator+(const S& obj) { return S(val+obj.val); } private: int val; }; Further, there are several overloaded variants of the f() function that output to the stream information about which of them was called.
void f(S&) { std::cout << "f(S&)\n"; } void f(S&&) { std::cout << "f(S&&)\n"; } void f(int&) { std::cout << "f(int&)\n"; } void f(int&&) { std::cout << "f(int&&)\n"; } Code in which all this is used:
int main() { S s(0); int i(0); f(s); // ОК: выведет "f(S&)" f(i); // ОК: выведет "f(int&)" f(S(0)); // ОК: выведет "f(S&&)" f(int(0)); // ОК: выведет "f(int&&)" f(S(1) + S(1)); // ОК: выведет "f(S&&)" f(int(1) + int(1)); // ОК: выведет "f(int&&)" s++++; // OK i++++; // ошибка: lvalue required as increment operand S(0)++; // OK int(0)++; // ошибка: lvalue required as increment operand S(1) + S(1) = s; //OK int(1) + int(1) = i; // ошибка: lvalue required as left operand of assignment return 0; } The places of interest in the code are commented.
Question: why for the fundamental types (in this case,
int) such operations as assignment and increment are not allowed for temporary objects of r-value type, and for user objects, for example, classSare allowed?Indeed, as a result of adding two objects (or after a postfix increment) we get a temporary rvalue-object, which does not exist outside the expression in which it appears. Where exactly can you find clarification on this?
What are some ways to prohibit this behavior for custom types? Use in the method declaration reference qualifiers & and &&, such as:
S operator++(int) & ?