https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106676
Bug ID: 106676 Summary: [C++20] Automatic iterator_category detection misbehaves when `::reference` is an rvalue reference, refuses to accept a forward iterator Product: gcc Version: 12.1.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: libstdc++ Assignee: unassigned at gcc dot gnu.org Reporter: iamsupermouse at mail dot ru Target Milestone: --- Since C++20, `std::iterator_traits` can auto-detect `::iterator_category`, if the iterator doesn't set it. Forward iterators require `::reference` (aka the return type of `operator*`) to be a reference (any reference), but libstdc++ only accepts lvalue references here. Example: #include <iterator> #include <type_traits> template <typename T> struct A { using value_type = std::remove_cvref_t<T>; using difference_type = int; T operator*() const; A &operator++(); A operator++(int); bool operator==(const A &) const; }; // Ok. static_assert(std::is_same_v<std::iterator_traits<A<int &>>::iterator_category, std::forward_iterator_tag>); // Should pass but fails, the category is `std::input_iterator_tag`. static_assert(std::is_same_v<std::iterator_traits<A<int &&>>::iterator_category, std::forward_iterator_tag>); I blame this on cppreference, which used to incorrectly say that only lvalue references are allowed there. It was fixed since then. See https://eel.is/c++draft/iterators#forward.iterators-1.3. Also see https://cplusplus.github.io/LWG/issue1211 (from 2009), which was resolved by https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3066.html (in 2010). This was discussed on SO: https://stackoverflow.com/q/73353152 libc++ and MSVC's standard library share the exact same bug. This was tested on GCC 12.1 and on trunk (13.0.0).