Section: 16.4.4.2 [utility.arg.requirements] Status: NAD Concepts Submitter: Alberto Ganesh Barbati Opened: 2008-09-29 Last modified: 2016-01-28
Priority: Not Prioritized
View all other issues in [utility.arg.requirements].
View all issues with NAD Concepts status.
Discussion:
Addresses UK 150
The description of the effect of operator=
in the MoveAssignable
concept, given in paragraph 7 is:
result_type T::operator=(T&& rv); // inherited from HasAssign<T, T&&>Postconditions: the constructed
T
object is equivalent to the value ofrv
before the assignment. [Note: there is no requirement on the value ofrv
after the assignment. --end note]
The sentence contains a typo (what is the "constructed T
object"?)
probably due to a cut&paste from MoveConstructible
. Moreover, the
discussion of LWG issue 675 shows that the postcondition is too generic
and might not reflect the user expectations. An implementation of the
move assignment that just calls swap()
would always fulfill the
postcondition as stated, but might have surprising side-effects in case
the source rvalue refers to an object that is not going to be
immediately destroyed. See LWG issue 900 for another example. Due to
the sometimes intangible nature of the "user expectation", it seems
difficult to have precise normative wording that could cover all cases
without introducing unnecessary restrictions. However a non-normative
clarification could be a very helpful warning sign that swapping is not
always the correct thing to do.
[ 2009-05-09 Alisdair adds: ]
Issue 910 is exactly the reason BSI advanced the Editorial comment UK-150.
The post-conditions after assignment are at a minimum that the object referenced by rv must be safely destructible, and the transaction should not leak resources. Ideally it should be possible to simply assign rv a new valid state after the call without invoking undefined behaviour, but any other use of the referenced object would depend upon additional guarantees made by that type.
[ 2009-05-09 Howard adds: ]
The intent of the rvalue reference work is that the moved from
rv
is a valid object. Not one in a singular state. If, for example, the moved from object is avector
, one should be able to do anything on that moved-fromvector
that you can do with any othervector
. However you would first have to query it to find out what its current state is. E.g. it might havecapacity
, it might not. It might have a non-zerosize
, it might not. But regardless, you canpush_back
on to it if you want.That being said, most standard code is now conceptized. That is, the concepts list the only operations that can be done with templated types - whether or not the values have been moved from.
Here is user-written code which must be allowed to be legal:
#include <vector> #include <cstdio> template <class Allocator> void inspect(std::vector<double, Allocator>&& v) { std::vector<double, Allocator> result(move(v)); std::printf("moved from vector has %u size and %u capacity\n", v.size(), v.capacity()); std::printf("The contents of the vector are:\n"); typedef typename std::vector<double, Allocator>::iterator I; for (I i = v.begin(), e = v.end(); i != e; ++i) printf("%f\n", *i); } int main() { std::vector<double> v1(100, 5.5); inspect(move(v1)); }The above program does not treat the moved-from
vector
as singular. It only treats it as avector
with an unknown value.I believe the current proposed wording is consistent with my view on this.
[ Batavia (2009-05): ]
We agree that the proposed resolution is an improvement over the current wording.
[ 2009-07 Frankfurt: ]
Need to look at again without concepts.
[ 2009-07 Frankfurt: ]
Walter will consult with Dave and Doug.
[ 2009-10 Santa Cruz: ]
We believe this is handled by the resolution to issue 1204, but there is to much going on in this area to be sure. Defer for now.
[ 2010-01-23 Moved to Tentatively NAD Concepts after 5 positive votes on c++std-lib. Rationale added below. ]
Rationale:
The current MoveAssignable
requirements say everything that can be said
in general. Each std-defined type has a more detailed specification of move
assignment.
Proposed resolution:
In [concept.copymove], replace the postcondition in paragraph 7 with:
Postconditions:
*this
is equivalent to the value ofrv
before the assignment. [Note: there is no requirement on the value ofrv
after the assignment, but the effect should be unsurprising to the user even in caserv
is not immediately destroyed. This may require that resources previously owned by*this
are released instead of transferred torv
. -- end note]