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

4626. move_iterator should not define iterator_category

Section: 24.5.4.2 [move.iterator] Status: New Submitter: Jay Ghiron Opened: 2026-09-23 Last modified: 2026-09-26

Priority: Not Prioritized

View all other issues in [move.iterator].

View all issues with New status.

Discussion:

Consider the following program:

#include<iostream>
#include<iterator>

struct S
{
  void m() & 
  {
    std::cout << "&\n";
  }
  
  void m() && 
  {
    std::cout << "&&\n";
  }
};

int main()
{
  S x[1];
  std::move_iterator<S*>a{x};
  a->m();
  (*a).m();
}

According to 24.3.5.3 [input.iterators] the expressions a->m and (*a).m should always be equivalent for the requirements of Cpp17InputIterator to be satisfied. However, move_iterator fails to meet that requirement here when it promises to do so by defining iterator_category to a type derived from input_iterator_tag. That is, iterator_category in this example should not be defined. Note that a removal of the deprecated operator-> would not make it satisfy the requirements. It may be possible to allow move_iterator to have iterator_category if it can be proven that a->m would never be valid or if the difference is unobservable. However, it seems simplest to just delete iterator_category.

Proposed resolution:

This wording is relative to N5054.

  1. Modify 24.5.4.2 [move.iterator] as indicated:

    namespace std {
      template<class Iterator>
      class move_iterator {
      public:
        using iterator_type = Iterator;
        using iterator_concept = see below ;
        using iterator_category = see below ; // not always present
        using value_type = iter_value_t<Iterator>;
        using difference_type = iter_difference_t<Iterator>;
        using pointer = Iterator;
        using reference = iter_rvalue_reference_t<Iterator>;
        
        […]
    
      private:
        Iterator current = Iterator(); // exposition only
      };
    }
    

    -1- The member typedef-name iterator_concept is defined as follows: […]

    -2- The member typedef-name iterator_category is declared if and only if the qualified-id iterator_traits<Iterator>::iterator_category is valid and denotes a type. In that case, iterator_category denotes

    1. (2.1) — random_access_iterator_tag if the type iterator_traits<Iterator>::iterator_category models derived_from<random_access_iterator_tag>, and

    2. (2.2) — iterator_traits<Iterator>::iterator_category otherwise.