https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94354
Bug ID: 94354 Summary: std::reverse_iterator comparison operators defined incorrectly Product: gcc Version: 10.0 Status: UNCONFIRMED Keywords: rejects-valid Severity: normal Priority: P3 Component: libstdc++ Assignee: unassigned at gcc dot gnu.org Reporter: redi at gcc dot gnu.org Target Milestone: --- We define the comparison operators for reverse_iterator slightly differently to how the standard specifies them, which means we incorrectly reject this: #include <iterator> struct Iter { using iterator_category = std::random_access_iterator_tag; using value_type = int; using pointer = int*; using reference = int&; using difference_type = std::ptrdiff_t; Iter(); Iter& operator++(); Iter operator++(int); Iter& operator--(); Iter operator--(int); int& operator*() const; int* operator->() const; int& operator[](difference_type) const; Iter& operator+=(difference_type); Iter& operator-=(difference_type); friend Iter operator+(Iter, difference_type); friend Iter operator+(difference_type, Iter); friend Iter operator-(Iter, difference_type); friend difference_type operator-(Iter, Iter); friend bool operator==(Iter, Iter); friend bool operator!=(Iter, Iter); friend bool operator<(Iter, Iter); friend bool operator>(Iter, Iter); friend bool operator<=(Iter, Iter); friend bool operator>=(Iter, Iter); }; bool operator!=(Iter, long*); std::reverse_iterator<Iter> l{Iter()}; std::reverse_iterator<long*> r{nullptr}; #if __cplusplus > 201703L static_assert( std::random_access_iterator<Iter> ); static_assert( std::random_access_iterator<long*> ); #endif bool b1 = l.base() != r.base(); // OK bool b2 = l != r; reviter.cc:50:13: in 'constexpr' expansion of 'std::operator!=<Iter, long int*>(l, r)' /home/jwakely/gcc/10/include/c++/10.0.1/bits/stl_iterator.h:375:25: error: no match for 'operator==' (operand types are 'std::reverse_iterator<Iter>::iterator_type' {aka 'Iter'} and 'std::reverse_iterator<long int*>::iterator_type' {aka 'long int*'}) 375 | { return __x.base() == __y.base(); } | ~~~~~~~~~~~^~~~~~~~~~~~~ The reverse_iterator's preconditions are met (both Iter and long* are random access iterators) and so is the constraint for operator!= Constraints: x.base() != y.base() is well-formed and convertible to bool. But it fails because we define operator!= as !(l == r) which uses == on the base iterator types, and they only support != I think the testcase should be valid for C++11 and later, as per https://cplusplus.github.io/LWG/lwg-defects.html#280 (and also C++98 if we treat that as a DR).