https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120415
Jonathan Wakely <redi at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Known to fail|14.3.0, 15.1.1 | --- Comment #9 from Jonathan Wakely <redi at gcc dot gnu.org> --- Their hash_set provides an iterator type which meets the C++17 forward iterator requirements: template<typename Value, typename Extractor = std::identity, typename Hasher = std::hash<hash_set_impl::ExtractedType<Value, Extractor>>, typename Equal = std::equal_to<>> class hash_set { protected: using PoolIndex = hash_set_impl::PoolIndex; static constexpr auto invalidIndex = hash_set_impl::invalidIndex; public: using value_type = Value; template<typename HashSet, typename IValue> class Iter { public: using value_type = IValue; using difference_type = int; using pointer = IValue*; using reference = IValue&; using iterator_category = std::forward_iterator_tag; And then they provide a TransformIterator adaptor to wrap other iterators and provide extra functionality. The problem is the TransformIterator adaptor which has all these completely unconstrained operators: constexpr TransformIterator& operator+=(difference_type n) { it += n; return *this; } constexpr TransformIterator& operator-=(difference_type n) { it -= n; return *this; } [[nodiscard]] constexpr friend TransformIterator operator+(TransformIterator x, difference_type n) { x += n; return x; } [[nodiscard]] constexpr friend TransformIterator operator+(difference_type n, TransformIterator x) { x += n; return x; } [[nodiscard]] constexpr friend TransformIterator operator-(TransformIterator x, difference_type n) { x -= n; return x; } [[nodiscard]] constexpr friend difference_type operator-(const TransformIterator& x, const TransformIterator& y) { return x.it - y.it; } [[nodiscard]] constexpr reference operator[](difference_type n) { return *(*this + n); } [[nodiscard]] constexpr auto operator<=>(const TransformIterator& other) const { return it <=> other.it; } The C++20 library sees these and thinks that it must be a random access iterator, because it provides all the operations that a random access iterator provides. But when it tries to use those operations on a TransformIterator<hash_set::Iter> they fail to compile. This code is not ready to be compiled as C++20. There are a few ways to fix it, they could add a requires-clause (or enable_if constraint) to each of those operators in TransformIterator, so they can only be used if the underlying iterator being adapted supports it. Or they could define TransformIterator::iterator_concept to stop the C++20 library trying to deduce that for itself. Or they could specialize std::sized_sentinel_for for TransformIterator. I'm testing those now ...