This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of C++17 status.
2900. The copy and move constructors ofoptional
are not constexpr
Section: 22.5.3 [optional.optional] Status: C++17 Submitter: United States Opened: 2017-02-03 Last modified: 2020-09-06
Priority: Not Prioritized
View all other issues in [optional.optional].
View all issues with C++17 status.
Discussion:
Addresses US 111The copy and move constructors of optional
are not constexpr
. However, the constructors taking a const T&
or T&&
are constexpr
, and there is a precedent for having a constexpr
copy constructor in 29.4.3 [complex]. The defaulted copy and move constructors of pair
and tuple
are also conditionally constexpr
(see 20.4.2 [pairs.pair] p2 and 20.5.2.1 [tuple.cnstr] p2).
A strong motivating use-case is constexpr
functions returning optional values. This issue was discovered while working on a library making heavy use of such.
Proposed change: Add constexpr to:
optional(const optional &); optional(optional &&) noexcept(see below);
[2017-02-23, Casey comments and suggests wording]
This issue corresponds to NB comment US 111, which requests that the move and copy constructors of std::optional
be declared constexpr
. The PR simply suggests adding the constexpr
specifier to the declarations of the constructors. The PR fails to specify the most important thing — and this has been a failing of Library in general — under what conditions is the thing that we've declared constexpr actually expected to be usable in constant expression context? (I think the proper standardese here is "under what conditions is the full expression of an initialization that would invoke these constructors a constant subexpression?")
optional<T>
must store a T
in a union to provide constexpr constructors that either do [optional(T const&)
] or do not [optional()
] initialize the contained T
. A general implementation of optional
's copy/move constructors must statically choose which union member, if any, to activate in each constructor. Since there is no way to change the active member of a union in a constant expression, and a constructor must statically choose a union member to activate (i.e., without being affected by the runtime state of the copy/move constructor's argument) it's not possible to implement a general constexpr copy/move constructor for optional
. It is, however, possible to copy/move construct a trivially copy constructible/trivially move constructible union in constexpr
context, which effectively copies the union's object representation, resulting in a union whose active member is the same as the source union's. Indeed, at least two major implementations of optional
(MSVC and libc++) already provide that behavior as a conforming optimization when T
is a trivially copyable type. If we are to declare optional<T>
's copy and move constructors constexpr
, we should additionally specify that those constructors are only required to have the "constexpr mojo" when T
is trivially copyable. (Note that I suggest "trivially copyable" here rather than "trivially copy constructible or trivially move constructible" since the simpler requirement is simpler to implement, and I don't believe the more complicated requirement provides any additional benefit: I've never seen a trivially copy constructible or trivially move constructible type outside of a test suite that was not also trivially copyable.)
Previous resolution [SUPERSEDED]:
This wording is relative to N4618.
Edit 22.5.3 [optional.optional] as indicated:
constexpr optional(const optional &);
constexpr optional(optional &&) noexcept(see below);
Edit 22.5.3.2 [optional.ctor] paragraph as indicated:
constexpr optional(const optional &);
and
constexpr optional(optional &&) noexcept(see below);
[2017-02-23, Marshall comments]
This is related to LWG 2745(i).
[2017-02-28, Kona, Casey comments and improves wording]
Amended PR per LWG discussion in Kona: replace the "is trivially copyable" requirement with the more specific is_trivially_copy/move_constructible<T>
. LWG was concerned that tuple
is a counter-example to the assumption that all three traits are equivalent for real-world types.
Previous resolution [SUPERSEDED]:
This wording is relative to N4640.
Change the synopsis of class template
optional
in 22.5.3 [optional.optional] as follows:[…] // 20.6.3.1, constructors constexpr optional() noexcept; constexpr optional(nullopt_t) noexcept; constexpr optional(const optional&); constexpr optional(optional&&) noexcept(see below); […]Modify 22.5.3.2 [optional.ctor] as indicated:
constexpr optional(const optional& rhs);[…]
-6- Remarks: This constructor shall be defined as deleted unlessis_copy_constructible_v<T>
istrue
. IfT
is a trivially copyable type, this constructor shall be aconstexpr
constructor.constexpr optional(optional&& rhs) noexcept(see below);[…]
-10- Remarks: The expression insidenoexcept
is equivalent tois_nothrow_move_constructible_v<T>
. This constructor shall not participate in overload resolution unlessis_move_constructible_v<T>
istrue
. IfT
is a trivially copyable type, this constructor shall be aconstexpr
constructor.
[Kona 2017-02-27]
Accepted as Immediate to resolve NB comment.
Proposed resolution:
This wording is relative to N4640.
Change the synopsis of class template optional
in 22.5.3 [optional.optional] as follows:
[…] // 20.6.3.1, constructors constexpr optional() noexcept; constexpr optional(nullopt_t) noexcept; constexpr optional(const optional&); constexpr optional(optional&&) noexcept(see below); […]
Modify 22.5.3.2 [optional.ctor] as indicated:
constexpr optional(const optional& rhs);[…]
-6- Remarks: This constructor shall be defined as deleted unlessis_copy_constructible_v<T>
istrue
. Ifis_trivially_copy_constructible_v<T>
istrue
, this constructor shall be aconstexpr
constructor.constexpr optional(optional&& rhs) noexcept(see below);[…]
-10- Remarks: The expression insidenoexcept
is equivalent tois_nothrow_move_constructible_v<T>
. This constructor shall not participate in overload resolution unlessis_move_constructible_v<T>
istrue
. Ifis_trivially_move_constructible_v<T>
istrue
, this constructor shall be aconstexpr
constructor.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4