This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of New status.
expected<int, int>
isn't specified to be trivially assignableSection: 22.8.6.4 [expected.object.assign], 22.8.7.4 [expected.void.assign] Status: New Submitter: Barry Revzin Opened: 2025-01-21 Last modified: 2025-02-07
Priority: 2
View other active issues in [expected.object.assign].
View all other issues in [expected.object.assign].
View all issues with New status.
Discussion:
Currently, we specify that the copy constructor, move constructor, and destructor expected<int, int>
are trivial operations. But we do not specify that the copy assignment operator or move assignment operator are.
There is implementation divergence — MSVC's implementation is trivially copyable, but libstdc++'s and libc++'s
are not (although, they are trivial for the purposes of calls, which is important for being able to return such a
type in a register).
I'm not sure there is any reason the assignment operators should not be trivial here. We should add the same kind
of remarks in both cases: that the copy assignment operator is trivial if T
and E
are trivially
copy assignable and the move assignment operator is trivial if T
and E
are trivially move assignable.
[2025-02-07; Reflector poll]
Set priority to 2 after reflector poll.
"Needs to consider trivial constructors as well as assignment."
"This is an ABI break for something that shipped in C++23, NAD."
Proposed resolution:
This wording is relative to N5001.
Modify 22.8.6.4 [expected.object.assign] as indicated:
constexpr expected& operator=(const expected& rhs);-2- Effects: […]
-3- Returns:
*this
.-4- Remarks: This operator is defined as deleted unless:
(4.1) — […]
(4.2) — […]
(4.3) — […]
(4.4) — […]
-?- This operator is trivial if
(?.1) —
is_trivially_copy_assignable_v<T>
istrue
and(?.2) —
is_trivially_copy_assignable_v<E>
istrue
.constexpr expected& operator=(expected&& rhs) noexcept(see below);-5- Constraints: […]
-6- Effects: […]
-7- Returns:
*this
.-8- Remarks: The exception specification is equivalent to:
is_nothrow_move_assignable_v<T> && is_nothrow_move_constructible_v<T> && is_nothrow_move_assignable_v<E> && is_nothrow_move_constructible_v<E>-?- This operator is trivial if
(?.1) —
is_trivially_move_assignable_v<T>
istrue
and(?.2) —
is_trivially_move_assignable_v<E>
istrue
.
Modify 22.8.7.4 [expected.void.assign] as indicated:
constexpr expected& operator=(const expected& rhs);-1- Effects: […]
-2- Returns:
*this
.-3- Remarks: This operator is defined as deleted unless
is_copy_assignable_v<E>
istrue
andis_copy_constructible_v<E>
istrue
.-?- This operator is trivial if
is_trivially_copy_assignable_v<E>
istrue
.constexpr expected& operator=(expected&& rhs) noexcept(see below);-4- Constraints: […]
-5- Effects: […]
-6- Returns:
*this
.-7- Remarks: The exception specification is equivalent to
is_nothrow_move_constructible_v<E> && is_nothrow_move_assignable_v<E>
.-?- This operator is trivial if
is_trivially_move_assignable_v<E>
istrue
.