3988. Should as_const_view and basic_const_iterator provide base()?

Section: 24.5.3 [const.iterators], 25.7.22.2 [range.as.const.view] Status: Open Submitter: Hewill Kang Opened: 2023-08-28 Last modified: 2024-03-15

Priority: 3

View other active issues in [const.iterators].

View all other issues in [const.iterators].

View all issues with Open status.

Discussion:

Currently, both as_const_view and basic_const_iterator provide base() members to return the underlying range and iterator, which seems to expose vulnerabilities in modifying them:

#include <vector>
#include <ranges>

int main() {
  std::vector v{1, 2, 3};
  
  auto f = [](std::span<int>::const_iterator i) {
    *i.base() = 4;
  };
  f(std::span{v}.cbegin());

  auto g = [](const std::ranges::constant_range auto& r) {
    r.begin().base()[1] = 5;
    r.base()[2] = 6;
  };
  g(std::ranges::as_const_view(v));

  // v now becomes [4, 5, 6]
}

I don't think such a shortcut should be provided as it doesn't seem to be the intention and could be harmful.

[2023-10-30; Reflector poll]

Set priority to 3 after reflector poll. Send to SG9.

[Kona 2023-11-07; move to Ready]

[2024-03-15; move back to Open following LEWG feedback]

SG9 approved the proposed change but then LEWG had no consensus for change. LWG should revisit in Tokyo.

Proposed resolution:

This wording is relative to N4958.

  1. Modify 24.5.3.3 [const.iterators.iterator], class template basic_const_iterator synopsis, as indicated:

    namespace std {
      […]
    
      template<input_iterator Iterator>
      class basic_const_iterator {
        […]
        constexpr const Iterator& base() const & noexcept;
        constexpr Iterator base() &&;
        […]
      };
    }
    
  2. Modify 24.5.3.5 [const.iterators.ops] as indicated:

    constexpr const Iterator& base() const & noexcept;
    

    -4- Effects: Equivalent to: return current_;

    constexpr Iterator base() &&;
    

    -5- Effects: Equivalent to: return std::move(current_);

  3. Modify 25.7.22.2 [range.as.const.view] as indicated:

    namespace std::ranges {
      template<view V>
        requires input_range<V>
      class as_const_view : public view_interface<as_const_view<V>> {
        […]
        constexpr V base() const & requires copy_constructible<V> { return base_; }
        constexpr V base() && { return std::move(base_); }
        […]
      };
    }