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.

3862. basic_const_iterator's common_type specialization is underconstrained

Section: 25.2 [iterator.synopsis] Status: WP Submitter: Hewill Kang Opened: 2023-01-25 Last modified: 2023-02-13

Priority: Not Prioritized

View all other issues in [iterator.synopsis].

View all issues with WP status.

Discussion:

To make basic_const_iterator compatible with its unwrapped iterators, the standard defines the following common_type specialization:

template<class T, common_with<T> U>
struct common_type<basic_const_iterator<T>, U> {
  using type = basic_const_iterator<common_type_t<T, U>>;
};

For type U, when it shares a common type with the unwrapped type T of basic_const_iterator, the common type of both is basic_const_iterator of the common type of T and U.

However, since this specialization only constrains U and T to have a common type, this allows U to be any type that satisfies such requirement, such as optional<T>, in which case computing the common type of both would produce a hard error inside the specialization, because basic_const_iterator requires the template parameter to be input_iterator, while optional clearly isn't.

Previous resolution [SUPERSEDED]:

This wording is relative to N4928.

  1. Modify 25.2 [iterator.synopsis], header <iterator> synopsis, as indicated:

    #include <compare>              // see 17.11.1 [compare.syn]
    #include <concepts>             // see 18.3 [concepts.syn]
    
    namespace std {
      […]
      template<class T, common_with<T> U>
        requires input_iterator<U>
      struct common_type<basic_const_iterator<T>, U> {                                  // freestanding
        using type = basic_const_iterator<common_type_t<T, U>>;
      };
      template<class T, common_with<T> U>
        requires input_iterator<U>
      struct common_type<U, basic_const_iterator<T>> {                                  // freestanding
        using type = basic_const_iterator<common_type_t<T, U>>;
      };
      […]
    }
    

[2023-02-06; Jonathan provides improved wording based on Casey's suggestion during the prioritization poll.]

[Issaquah 2023-02-07; LWG]

Move to Immediate for C++23

[2023-02-13 Status changed: Immediate → WP.]

Proposed resolution:

This wording is relative to N4928.

  1. Modify 25.2 [iterator.synopsis], header <iterator> synopsis, as indicated:

    #include <compare>              // see 17.11.1 [compare.syn]
    #include <concepts>             // see 18.3 [concepts.syn]
    
    namespace std {
      […]
      template<class T, common_with<T> U>
        requires input_iterator<common_type_t<T, U>>
      struct common_type<basic_const_iterator<T>, U> {                                  // freestanding
        using type = basic_const_iterator<common_type_t<T, U>>;
      };
      template<class T, common_with<T> U>
        requires input_iterator<common_type_t<T, U>>
      struct common_type<U, basic_const_iterator<T>> {                                  // freestanding
        using type = basic_const_iterator<common_type_t<T, U>>;
      };
      template<class T, common_with<T> U>
        requires input_iterator<common_type_t<T, U>>
      struct common_type<basic_const_iterator<T>, basic_const_iterator<U>> {            // freestanding
        using type = basic_const_iterator<common_type_t<T, U>>;
      };
      […]
    }