3853. basic_const_iterator<volatile int*>::operator-> is ill-formed

Section: 25.5.3 [const.iterators] Status: WP Submitter: Hewill Kang Opened: 2023-01-06 Last modified: 2023-02-13 10:17:57 UTC

Priority: Not Prioritized

View other active issues in [const.iterators].

View all other issues in [const.iterators].

View all issues with WP status.

Discussion:

Currently, basic_const_iterator::operator-> constrains the value type of the underlying iterator to be only the cv-unqualified type of its reference type, which is true for raw pointers.

However, since it also explicitly specifies returning a pointer to a const value type, this will cause a hard error when the value type is actually volatile-qualified:

std::basic_const_iterator<volatile int*> it;
auto* p = it.operator->(); // invalid conversion from 'volatile int*' to 'const int*'

The proposed resolution changes the return type from const value_type* to const auto*, which makes it deduce the correct type in the above example, i.e. const volatile int*.

[2023-02-01; Reflector poll]

Set status to Tentatively Ready after six votes in favour during reflector poll.

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

Proposed resolution:

This wording is relative to N4917.

  1. Modify 25.5.3 [const.iterators] as indicated:

    namespace std {
      template<class I>
        concept not-a-const-iterator = see below;
    
      template<input_iterator Iterator>
      class basic_const_iterator {
        Iterator current_ = Iterator();                             // exposition only
        using reference = iter_const_reference_t<Iterator>;         // exposition only
      
      public:
        […]
        constexpr reference operator*() const;
        constexpr const autovalue_type* operator->() const
           requires is_lvalue_reference_v<iter_reference_t<Iterator>> &&
                    same_as<remove_cvref_t<iter_reference_t<Iterator>>, value_type>;
        […]
      };
    }
    
    […]
    constexpr const autovalue_type* operator->() const
      requires is_lvalue_reference_v<iter_reference_t<Iterator>> &&
               same_as<remove_cvref_t<iter_reference_t<Iterator>>, value_type>;
    

    -7- Returns: If Iterator models contiguous_iterator, to_address(current_); otherwise, addressof(*current_).