Section: 16.4.5.9 [res.on.arguments] Status: C++11 Submitter: Howard Hinnant Opened: 2009-09-12 Last modified: 2016-01-28
Priority: Not Prioritized
View all other issues in [res.on.arguments].
View all issues with C++11 status.
Discussion:
When a library function binds an rvalue reference parameter to an argument, the library must be able to assume that the bound argument is a temporary, and not a moved-from lvalue. The reason for this is that the library function must be able to modify that argument without concern that such modifications will corrupt the logic of the calling code. For example:
template <class T, class A> void vector<T, A>::push_back(value_type&& v) { // This function should move from v, potentially modifying // the object v is bound to. }
If v
is truly bound to a temporary, then push_back
has the
only reference to this temporary in the entire program. Thus any
modifications will be invisible to the rest of the program.
If the client supplies std::move(x)
to push_back
, the onus is
on the client to ensure that the value of x
is no longer important to
the logic of his program after this statement. I.e. the client is making a statement
that push_back
may treat x
as a temporary.
The above statement is the very foundation upon which move semantics is based.
The standard is currently lacking a global statement to this effect. I propose the following addition to 16.4.5.9 [res.on.arguments]:
Each of the following statements applies to all arguments to functions defined in the C++ standard library, unless explicitly stated otherwise.
- If an argument to a function has an invalid value (such as a value outside the domain of the function, or a pointer invalid for its intended use), the behavior is undefined.
- If a function argument is described as being an array, the pointer actually passed to the function shall have a value such that all address computations and accesses to objects (that would be valid if the pointer did point to the first element of such an array) are in fact valid.
- If a function argument binds to an rvalue reference parameter, the C++ standard library may assume that this parameter is a unique reference to this argument. If the parameter is a generic parameter of the form
T&&
, and an lvalue of typeA
is bound, then the binding is considered to be to an lvalue reference (13.10.3.2 [temp.deduct.call]) and thus not covered by this clause. [Note: If a program casts an lvalue to an rvalue while passing that lvalue to a library function (e.g.move(x)
), then the program is effectively asking the library to treat that lvalue as a temporary. The library is at liberty to optimize away aliasing checks which might be needed if the argument were an lvalue. — end note]
Such a global statement will eliminate the need for piecemeal statements such as 23.2.2 [container.requirements.general]/13:
An object bound to an rvalue reference parameter of a member function of a container shall not be an element of that container; no diagnostic required.
Additionally this clarifies that move assignment operators need not perform the
traditional if (this != &rhs)
test commonly found (and needed) in
copy assignment operators.
[ 2009-09-13 Niels adds: ]
Note: This resolution supports the change of 31.10.3.3 [filebuf.assign]/1, proposed by LWG 900.
[ 2009 Santa Cruz: ]
Move to Ready.
Proposed resolution:
Add a bullet to 16.4.5.9 [res.on.arguments]:
Each of the following statements applies to all arguments to functions defined in the C++ standard library, unless explicitly stated otherwise.
- If an argument to a function has an invalid value (such as a value outside the domain of the function, or a pointer invalid for its intended use), the behavior is undefined.
- If a function argument is described as being an array, the pointer actually passed to the function shall have a value such that all address computations and accesses to objects (that would be valid if the pointer did point to the first element of such an array) are in fact valid.
- If a function argument binds to an rvalue reference parameter, the C++ standard library may assume that this parameter is a unique reference to this argument. If the parameter is a generic parameter of the form
T&&
, and an lvalue of typeA
is bound, then the binding is considered to be to an lvalue reference (13.10.3.2 [temp.deduct.call]) and thus not covered by this clause. [Note: If a program casts an lvalue to an rvalue while passing that lvalue to a library function (e.g.move(x)
), then the program is effectively asking the library to treat that lvalue as a temporary. The library is at liberty to optimize away aliasing checks which might be needed if the argument were an lvalue. — end note]
Delete 23.2.2 [container.requirements.general]/13:
An object bound to an rvalue reference parameter of a member function of a container shall not be an element of that container; no diagnostic required.