Section: 16.4.6.15 [lib.types.movedfrom], 16.4.5.9 [res.on.arguments], 23.2.2 [container.requirements.general] Status: C++23 Submitter: Tim Song Opened: 2016-12-09 Last modified: 2023-11-22
Priority: 2
View all issues with C++23 status.
Discussion:
LWG 2468's resolution added to MoveAssignable
the requirement to tolerate self-move-assignment,
but that does nothing for library types that aren't explicitly specified to meet MoveAssignable
other than make
those types not meet MoveAssignable
any longer.
[2017-01-27 Telecon]
Priority 2
[2018-1-26 issues processing telecon]
Status to 'Open'; Howard to reword using 'MoveAssignable'.
Previous resolution [SUPERSEDED]:
This wording is relative to N4618.
Add a new paragraph at the end of 16.4.6.15 [lib.types.movedfrom]:
-1- Objects of types defined in the C++ standard library may be moved from (12.8). Move operations may be explicitly specified or implicitly generated. Unless otherwise specified, such moved-from objects shall be placed in a valid but unspecified state.
-?- An object of a type defined in the C++ standard library may be move-assigned (11.4.6 [class.copy.assign]) to itself. Such an assignment places the object in a valid but unspecified state unless otherwise specified.Add a note at the end of 16.4.5.9 [res.on.arguments]/1, bullet 3, as indicated:
-1- Each of the following applies to all arguments to functions defined in the C++ standard library, unless explicitly stated otherwise.
(1.1) — […]
(1.2) — […]
(1.3) — If a function argument binds to an rvalue reference parameter, the implementation may assume that this parameter is a unique reference to this argument. [Note: If the parameter is a generic parameter of the form
T&&
and an lvalue of typeA
is bound, the argument binds to an lvalue reference (14.8.2.1) and thus is not covered by the previous sentence. — end note] [Note: If a program casts an lvalue to an xvalue while passing that lvalue to a library function (e.g. by calling the function with the argumentstd::move(x)
), the program is effectively asking that function to treat that lvalue as a temporary. The implementation is free to optimize away aliasing checks which might be needed if the argument was an lvalue. — end note] [Note: This does not apply to the argument passed to a move assignment operator (16.4.6.15 [lib.types.movedfrom]). — end note]Edit Table 83 "Container requirements" in 23.2.2 [container.requirements.general] as indicated:
Table 83 — Container requirements Expression Return type Operational
semanticsAssertion/note
pre-/post-conditionComplexity …
a = rv
T&
All existing elements of a
are either move
assigned to or
destroyedpost: If a
andrv
do not refer to the same object,
a
shall be equal to the value that
rv
had before this assignmentlinear …
Edit Table 86 "Allocator-aware container requirements" in 23.2.2 [container.requirements.general] as indicated:
Table 86 — Allocator-aware container requirements Expression Return type Assertion/note
pre-/post-conditionComplexity …
a = rv
T&
Requires: If allocator_traits<allocator_type
>::propagate_on_container_move_assignment::value
isfalse
,T
isMoveInsertable
intoX
andMoveAssignable
.
All existing elements ofa
are either
move assigned to or destroyed.
post: Ifa
andrv
do not refer
to the same object,a
shall be equal
to the value thatrv
had before this assignmentlinear …
[2018-08-16, Howard comments and provides updated wording]
I agreed to provide proposed wording for LWG 2839 that was reworded to use MoveAssignable
. The advantage of
this is that MoveAssignable
specifies the self-assignment case, thus we do not need to repeat ourselves.
[2018-08-23 Batavia Issues processing]
Howard and Tim to discuss a revised P/R.
Previous resolution [SUPERSEDED]:
This wording is relative to N4762.
Add a new subsection to 16.4.6 [conforming] after 16.4.6.5 [member.functions]:
Special members [conforming.special]
Class types defined by the C++ standard library and specified to be default constructible, move constructible, copy constructible, move assignable, copy assignable, or destructible, shall meet the associated requirements Cpp17DefaultConstructible, Cpp17MoveConstructible, Cpp17CopyConstructible, Cpp17MoveAssignable, Cpp17CopyAssignable, and Cpp17Destructible, respectively (16.4.4.2 [utility.arg.requirements]).
[2020-06-06 Tim restores and updates P/R following 2020-05-29 telecon discussion]
The standard doesn't define phrases like "default constructible" used in the
previous P/R. Moreover, the library provides a variety of wrapper types, and
whether these types meet the semantic requirements of Cpp17Meowable
(and maybe even syntactic, depending on how "copy constructible" is interpreted)
depends on the property of their underlying wrapped types, which might not even
be an object type (e.g., tuple
or pair
of references). This is
a large can of worms (see LWG 2146) that we don't want to get into.
assignable_from
(18.4.8 [concept.assignable])
contains a note alluding to these cases and suggesting that they should be
considered to be outside the domain of =
entirely.
[2020-07-17; issue processing telecon]
LWG reviewed the latest proposed resolution. Unanimous consent to move to Ready.
[2020-11-09 Approved In November virtual meeting. Status changed: Ready → WP.]
Proposed resolution:
This wording is relative to N4861.
Add a new paragraph at the end of 16.4.6.15 [lib.types.movedfrom]:
-1- Objects of types defined in the C++ standard library may be moved from ( [clss.copy.ctor]). Move operations may be explicitly specified or implicitly generated. Unless otherwise specified, such moved-from objects shall be placed in a valid but unspecified state.
-?- An object of a type defined in the C++ standard library may be move-assigned (11.4.6 [class.copy.assign]) to itself. Unless otherwise specified, such an assignment places the object in a valid but unspecified state.
Edit 16.4.5.9 [res.on.arguments]/1, bullet 3, as indicated:
-1- Each of the following applies to all arguments to functions defined in the C++ standard library, unless explicitly stated otherwise.
(1.1) — […]
(1.2) — […]
(1.3) — If a function argument binds to an rvalue reference parameter, the implementation may assume that this parameter is a unique reference to this argument, except that the argument passed to a move-assignment operator may be a reference to
*this
(16.4.6.15 [lib.types.movedfrom]). [Note: If the type of a parameter is ageneric parameter of the formforwarding reference (13.10.3.2 [temp.deduct.call]) that is deduced to an lvalue reference type, then the argument is not bound to an rvalue reference. — end note] [Note: If a program casts an lvalue to an xvalue while passing that lvalue to a library function (e.g. by calling the function with the argumentT&&
and an lvalue of typeA
is bound, the argument binds to an lvalue reference (13.10.3.2 [temp.deduct.call]) and thus is not covered by the previous sentence.std::move(x)
), the program is effectively asking that function to treat that lvalue as a temporary. The implementation is free to optimize away aliasing checks which might be needed if the argument was an lvalue. — end note]
Edit Table 73 "Container requirements" in 23.2.2 [container.requirements.general] as indicated:
Table 73 — Container requirements Expression Return type Operational
semanticsAssertion/note
pre-/post-conditionComplexity …
a = rv
T&
All existing elements of a
are either move assigned to or destroyedPostconditions: If a
andrv
do not refer to the same object,a
is equal to the value thatrv
had before this assignment.linear …
Edit Table 76 "Allocator-aware container requirements" in 23.2.2 [container.requirements.general] as indicated:
Table 86 — Allocator-aware container requirements Expression Return type Assertion/note
pre-/post-conditionComplexity …
a = rv
T&
Preconditions: If allocator_traits<allocator_type>
is
::propagate_on_container_move_assignment::valuefalse
,
T
is Cpp17MoveInsertable intoX
and Cpp17MoveAssignable.
Effects: All existing elements ofa
are either move assigned to or destroyed.
Postconditions: Ifa
andrv
do not refer to the same object,a
is equal to the value thatrv
had before this assignment.linear …