Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does it improve safety to mark assignment operators as lvalue-only?

If T is a class type with the default signature for assignment operator, then we can write:

T const &ref = ( T{} = something ); 

which creates a dangling reference. However, with the signature:

T &operator=(T t) &

the above code with dangling reference will fail to compile. This would prevent some situations where we return an lvalue that designates a temporary object -- undesirable situations because they can lead to dangling references.

Is there any reason not to do this; would we be disabling any valid use cases for the assignment operators?

I think the same comments can apply to the compound assignment operators too, += etc. A more realistic case might be:

std::string const &s = std::string("Hello, ") += "world!";

where the typo would go unnoticed until runtime UB.

like image 214
M.M Avatar asked Feb 19 '15 04:02

M.M


People also ask

What are the advantages of assignment operator?

Advantages: Left-hand side operator need not repeated. Easy to Read. More Efficient.

Why is copy assignment operator needed?

The copy assignment operator lets you create a new object from an existing one by initialization. A copy assignment operator of a class A is a nonstatic non-template member function that has one of the following forms: A::operator=(A) A::operator=(A&)


1 Answers

In my experience in the rare case you do want to assign to an rvalue, writing

template<class T>
std::remove_reference_t<T>& as_lvalue(T&&t){return t;}

and doing as_lvalue( tmp() ) = foo instead of tmp()=foo is not a huge barrier. It does mean that the occasional bit of code that did assign to an rvalue is now going to break; I personally would suspect most such cases are actually uncaught bugs.


Restricting every type in std to be lvalue-restricted on operator= was considered during C++11 standardization in Frankfurt (2009/07). The resolution reasoning recorded in the minutes was:

N2819, "N2819 Ref-Qualifiers for assignment operators of the Standard Library" was initially considered by the LWG. This proposal sought to change 350 copy-assignment operators in the C++ standard library to prevent assignment operations in which the left operand is an rvalue. Due to the large number of changes required, the proposal was sent to EWG, with the request that the default behavior for implicit copy-assignment operators be reconsidered, so that assignment to an rvalue is not permitted. The EWG resolved to maintain the status quo, because of concerns about backwards compatibility.

I read that as saying "350 changes? How about a language change?". EWG said "no, that language change could break compatibility". And possibly the proposal died on the vine.

In 2009, C++11 (then C++0x) was already behind schedule. As the proposition involved 300 changes to the library that (in theory) could cause regressions. No other reason was cited in the minutes. It being declined for not being worth the pain of regressions (or even checking for the frequency of regressions!) is understandable. So I wouldn't presume prejudice on the idea just because C++ rejected it in std.

like image 112
Yakk - Adam Nevraumont Avatar answered Oct 26 '22 04:10

Yakk - Adam Nevraumont