3613. Specify that nullopt_t is copyable

Section: 22.5.4 [optional.nullopt] Status: New Submitter: Frank Birbacher Opened: 2021-10-01 Last modified: 2024-01-29

Priority: 3

View all other issues in [optional.nullopt].

View all issues with New status.

Discussion:

The Standard defines a number of types that are used to create overload disambiguators for constructors, like nullopt_t and allocator_tag_t. Values of such types are passed by value to such constructors to give it particular meaning. For pass-by-value these types need to be copy-constructible and for consistency should also be copy-assignable. Of those types the specification of nullopt_t doesn't clearly state that the type is copyable, 22.5.4 [optional.nullopt].

The reason that nullopt_t is defined differently from other such types is to avoid ambiguity in expressions that assign an empty brace initializer to an optional. The meaning of such assignment should be to engage the optional instead of taking the braces to create a temporary nullopt_t for assignment and thus reset the optional. The RHS of such assignment should be a temporary empty optional instead of a temporary nullopt_t.

Types that aren't affected: nullptr_t (fundamental type), allocator_tag_t, piecewise_construct_t, in_place_t, in_place_type_t, in_place_index_t (all basically defined as a class T { explicit T() = default; } which works fine for pass-by-value)

[2021-10-14; Reflector poll]

Set priority to 3 after reflector poll.

[Daniel commented:]

I would prefer to see the wording use is_trivially_copy_constructible_v and trivially_copy_assignable_v, which is consistent with similar usage of trivial-requirements in std::optional.

[Tim commented:]

We need to say that it models copyable and is trivially copyable (not sure if we need the latter but might as well - does anyone do it differently?). "has a copy constructor" isn't enough - T(T&) is a copy constructor.

Proposed resolution:

This wording is relative to N4892.

  1. Modify 22.5.4 [optional.nullopt] as indicated:

    struct nullopt_t{see below};
    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 for optional objects. In particular, optional<T> has a constructor with nullopt_t as a single argument; this indicates that an optional object not containing a value shall be constructed.

    -2- Type nullopt_t shall not have a default constructor or an initializer-list constructor, and shall not be an aggregate, and shall have a copy constructor and a copy assignment operator, both shall be public and trivial.