nullopt_t
's requirement to not be DefaultConstructibleSection: 22.5.4 [optional.nullopt] Status: NAD Submitter: David Friberg Opened: 2021-06-04 Last modified: 2021-06-14
Priority: Not Prioritized
View all other issues in [optional.nullopt].
View all issues with NAD status.
Discussion:
22.5.4 [optional.nullopt] p2 requires that nullopt_t
shall not have a default constructor
([…] or an initializer-list constructor, and shall not be an aggregate). However, after the final
resolution of LWG issue 2510 and CWG 1518 it seems
as if the following synopsis would suffice:
struct nullopt_t { explicit nullopt_t() = default; };
Which would also be consistent with other tag types.
22.5.4 [optional.nullopt] p2 in its current form was written prior to the final resolution of LWG issue 2510 and CWG 1518, and is arguably based on using an earlier proposed approach for tag types which was later superseded. Details: P0032R3 was part of introducingoptional
and contained a discussion around the
nullopt_t
type, tag types in general, and the DefaultConstructible requirement. Particularly,
from section 'Not assignable from {}
':
To re-enforce this design, there is an pending issue 2510-Tag types should not be DefaultConstructible Core issue 2510.
At the time of P0032R3, the resolution of LWG issue 2510 was indeed for all tag types to not be DefaultConstructible, but this resolution was later superseded as part of the resolution of CWG issue CWG 1518, which in turn reverted parts of the resolution of CWG issue CWG 1630 (which "went too far in allowing use of explicit constructors for default initialization").
The final resolution for CWG 1518 (P0398R0) lead to the requirement for aggregate classes to not have any explicit [user-declared] constructors, and LWG 2510 was resolved accordingly by making all tag types have explicit user-declared (constexpr) default constructors. However, the spec ofnullopt_t
never changed after these events or as part of updating other tag types,
and it is still explicitly required to not be DefaultConstructible (nor have a initialization-list constructor)
and to not be an aggregate, whereas the implementation of it is otherwise unspecified.
We may note that we still see some compiler variance on the topic of CWG issues 1518 & 1630, see this
godbolt link.
[2021-06-14 Reflector poll:
Current wording prevents an implicit conversion sequence from {}
.
Status changed: New → NAD.]
Proposed resolution:
This wording is relative to N4885.
Modify 22.5.2 [optional.syn], header <optional>
synopsis, as indicated:
[…] // 22.5.4 [optional.nullopt], no-value state indicator struct nullopt_t{see belowexplicit nullopt_t() = default; }; inline constexpr nullopt_t nullopt{}(unspecified); […]
Modify 22.5.4 [optional.nullopt] as indicated:
struct nullopt_t{see belowexplicit nullopt_t() = default; }; inline constexpr nullopt_t nullopt{}(unspecified);-1- The struct
nullopt_t
is an empty class type used as a unique type to indicate the state of not containing a value foroptional
objects. In particular,optional<T>
has a constructor withnullopt_t
as a single argument; this indicates that an optional object not containing a value shall be constructed.-2- Typenullopt_t
shall not have a default constructor or an initializer-list constructor, and shall not be an aggregate.