Title
std::optional<NonReturnable&> is ill-formed due to `value_or`
Status
wp
Section
[optional.ref.observe]
Submitter
Jiang An

Created on 2025-07-25.00:00:00 last changed 5 days ago

Messages

Date: 2025-11-11.10:48:55

Proposed resolution:

This wording is relative to N5014.

  1. Modify [optional.ref.observe] as indicated:

    template<class U = remove_cv_t<T>> constexpr remove_cv_t<T> value_or(U&& u) const;
    

    -?- Constraints: `T` is a non-array object type.

    -8- Let `X` be remove_cv_t<T>.

    -9- Mandates: is_constructible_v<X, T&> && is_convertible_v<U, X> is `true`.

    -10- Effects: Equivalent to:

    return has_value() ? *val : static_cast<X>(std::forward<U>(u));
    

    -?- Remarks: The return type is unspecified if `T` is an array type or a non-object type. [Note ?: This is to avoid the declaration being ill-formed. — end note]

Date: 2025-11-11.10:48:55

[ Kona 2025-11-08; Status changed: Immediate → WP. ]

Date: 2025-11-04.01:26:11

[ Kona 2025-11-03; approved by LWG. Status changed: New → Immediate. ]

Date: 2025-10-15.00:00:00

[ 2025-10-16; Jonathan provides new wording ]

Date: 2025-10-15.00:00:00

[ 2025-10-16; Reflector poll ]

Set priority to 1 after reflector poll.

Why not just add Constraints: and use decay_t<T> for the return type, instead of "not always present" which is currently only used for member types, not member functions.

This wording is relative to N5014.

  1. Modify [optional.optional.ref.general], header <iterator> synopsis, as indicated:

    namespace std {
      template<class T>
      class optional<T&> {
        […]
        constexpr T& value() const; // freestanding-deleted
        template<class U = remove_cv_t<T>>
          constexpr remove_cv_t<T> value_or(U&& u) const; // not always present
        […]
      };
    }
    
  2. Modify [optional.ref.observe] as indicated:

    template<class U = remove_cv_t<T>> constexpr remove_cv_t<T> value_or(U&& u) const;
    

    -8- Let `X` be remove_cv_t<T>.

    -9- Mandates: is_constructible_v<X, T&> && is_convertible_v<U, X> is `true`.

    -10- Effects: Equivalent to:

    return has_value() ? *val : static_cast<X>(std::forward<U>(u));
    

    -?- Remarks: This function template is present if and only if `T` is a non-array object type.

Date: 2025-07-25.00:00:00

Currently, if `T` is an array type or a function type, instantiation of std::optional<T&> is still ill-formed, because the return type of its `value_or` member function is specified as remove_cv_t<T>, which is invalid as a return type.

However, we don't exclude such T& from valid contained types. Given only `value_or` is problematic here, perhaps we can avoid providing it if `T` is not returnable.

History
Date User Action Args
2025-11-11 10:48:55adminsetmessages: + msg15670
2025-11-11 10:48:55adminsetstatus: immediate -> wp
2025-11-04 01:26:11adminsetmessages: + msg15487
2025-11-04 01:26:11adminsetstatus: new -> immediate
2025-10-16 15:05:30adminsetmessages: + msg15189
2025-10-16 15:05:30adminsetmessages: + msg15188
2025-07-27 09:18:00adminsetmessages: + msg14916
2025-07-25 00:00:00admincreate