Title
The standard library iterator adaptor does not handle iterator_category correctly
Status
new
Section
[const.iterators.iterator][range.adaptors]
Submitter
Hewill Kang

Created on 2025-03-27.00:00:00 last changed 1 month ago

Messages

Date: 2025-03-27.00:00:00

Currently, basic_const_iterator, and several range adaptors such as filter_view's iterators provide iterator_category only when the underlying iterator models forward_iterator, implying that they expect those iterators should have a valid iterator_category.

However, this is incorrect because being a forward_iterator does not necessarily mean it is a Cpp17InputIterator, it just means that it probably meets the syntactic requirements of Cpp17InputIterator.

Any iterator that specializes iterator_traits and provides only iterator_concept without iterator_category is not a Cpp17InputIterator, for example, common_iterator with a difference_type of integer-class type.

In this case, instantiating these iterator adaptors will result in a hard error because the iterator_category they expect does not exist. The following illustrates the problem (demo):

#include <iterator>
#include <ranges>

int main() {
  auto r = std::views::iota(0ULL)
         | std::views::take(5)
         | std::views::common;

  static_assert(std::ranges::forward_range<decltype(r)>);
  
  std::basic_const_iterator ci(r.begin()); // 'iterator_category': is not a member of 'std::iterator_traits'

  auto f = r | std::views::filter([](auto) { return true; });
  auto b = f.begin();                      // 'iterator_category': is not a member of 'std::iterator_traits'
}

I believe that checking if the underlying iterator is a forward_iterator is not an appropriate mechanism to provide iterator_category, but rather checking if its iterator_traits specialization provides iterator_category.

This issue is somewhat related to LWG 3763, which is a further consideration after LWG 3749 has been resolved.

History
Date User Action Args
2025-03-27 00:00:00admincreate