This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of WP status.

4308. std::optional<T&>::iterator can't be a contiguous iterator for some T

Section: 22.5.4.5 [optional.ref.iterators] Status: WP Submitter: Jiang An Opened: 2025-08-05 Last modified: 2025-11-11

Priority: 1

View all issues with WP status.

Discussion:

This is related to LWG 4304(i). When T is function type or an incomplete array type, it is impossible to implement all requirements in 22.5.4.5 [optional.ref.iterators]/1.

When T is an incomplete object type, we may want to support std::optional<T&> as it's sometimes a replacement of T*. Perhaps we can require that the iterator type is always a random access iterator, and additional models contiguous_iterator when T is complete.

When T is a function type, the possibly intended iterator would be not even an actual iterator. But it seems that range-for loop over such an std::optional<T&> can work.

[2025-08-29; Reflector poll]

Set priority to 1 after reflector poll.

"How can end() work for a pointer to incomplete type? begin/end should be constrained on object types, and Mandate complete object types. The aliases shouldn't be defined for non-object types, but probably harmless."

[Kona 2025-11-05; Should only be a range for an object type.]

optional<T&> doesn't currently allow incomplete types anyway.

Previous resolution [SUPERSEDED]:

This wording is relative to N5014.

  1. Modify 22.5.4.5 [optional.ref.iterators] as indicated:

    using iterator = implementation-defined; 
    

    -1- TIf T is an object type, this type models contiguous_iterator (24.3.4.14 [iterator.concept.contiguous])random_access_iterator (24.3.4.13 [iterator.concept.random.access]), meets the Cpp17RandomAccessIterator requirements (24.3.5.7 [random.access.iterators]), and meets the requirements for constexpr iterators (24.3.1 [iterator.requirements.general]), with value type remove_cv_t<T>. The reference type is T& for iterator. When T is a complete object type, iterator additionally models contiguous_iterator (24.3.4.14 [iterator.concept.contiguous]).
    -2- All requirements on container iterators (23.2.2.2 [container.reqmts]) apply to optional::iterator.

    -?- If T is a function type, iterator supports all operators required by the random_access_iterator concept (24.3.4.13 [iterator.concept.random.access]) along with the <=> operator as specified for container iterators (23.2.2.2 [container.reqmts]). iterator dereferences to a T lvalue. These operators behave as if iterator were an actual iterator iterating over a range of T, and result in constant subexpressions whenever the behavior is well-defined. [Note ?: Such an optional::iterator does not need to declare any member type because it is not an actual iterator type. — end note]

[Kona 2025-11-06, Tomasz provides updated wording]

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

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

Proposed resolution:

  1. Modify 22.5.4.1 [optional.optional.ref.general] as indicated:

    namespace std {
      template<class T>
      class optional<T&> {
      public:
        using value_type     = T;
        using iterator       = implementation-defined;  // present only if T is an object type other than an array of unknown bound; see [optional.ref.iterators]
      public:
        […]
    
        // [optional.ref.iterators], iterator support
        constexpr iteratorauto begin() const noexcept;
        constexpr iteratorauto end() const noexcept;
    
        […]
      };
    }
    
  2. Modify 22.5.4.5 [optional.ref.iterators] as indicated:

    using iterator = implementation-defined; // present only if T is an object type other than an array of unknown bound
    

    -1- This type models contiguous_iterator (24.3.4.14 [iterator.concept.contiguous]), meets the Cpp17RandomAccessIterator requirements (24.3.5.7 [random.access.iterators]), and meets the requirements for constexpr iterators (24.3.1 [iterator.requirements.general]), with value type remove_cv_t<T>. The reference type is T& for iterator.

    -2- All requirements on container iterators (23.2.2.2 [container.reqmts]) apply to optional::iterator.

    constexpr iteratorauto begin() const noexcept;
    

    -?- Constraints: T is an object type other than an array of unknown bound.

    -3- Returns: An object i of type iterator, such that If has_value() is true, i is an iterator referring to *val if has_value() is true, and Otherwise, a past-the-end iterator value otherwise.

    constexpr iteratorauto end() const noexcept;
    

    -?- Constraints: T is an object type other than an array of unknown bound.

    -4- Returns: begin() + has_value().