<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/57233>57233</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            [libc++] Automatic `iterator_category` detection misbehaves when `::reference` is an rvalue reference, refuses to accept a forward iterator
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            new issue
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          HolyBlackCat
      </td>
    </tr>
</table>

<pre>
    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 libc++ only accepts lvalue references here.

Example:
```cpp
#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 [`[forward.iterators]/1.3`](https://eel.is/c++draft/iterators#forward.iterators-1.3). Also see [LWG issue 1211](https://cplusplus.github.io/LWG/issue1211) (from 2009), which was resolved by [N3066](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

[libstdc++](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106676) and MSVC's standard library share the exact same bug.

This was tested on Clang 14.0.0 and on trunk (16.0.0).
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJy1VkuT4jYQ_jXmohqXLPMwBw7ADMlWJdnDTG2OlCzLtnaE5ZVkGPLr0y0DHh5zSygBttTq_vrxtZSb4rh4VY2QZB2xFQxGI7Ym0ZQ6X0TpEoby0nJv7NZbrryDJSJ4Q3jnzVMhvRQexW9kBfeyMvaIK6BPlcTXkpyXSWGkayI288RJD9NxRJ8juux_N8YeuC0u0o5Y-atTVg52rCyllQAb0UQs4-88GLDSd7Yh_thKYkqUN22vJGLLgGVOvCG5JJxcdAQFzXGYACkEnXeeaJWLPjDENPpIuBCy9Y7oPdedHLY4UsPDlRsvH3zXaomA-1kwH4Zo29MMSyH0uisAQro-uxulL4-W0adzCi4S4ddLsAPxPks1fCfJ20XIedtBjs4oZqv-gcCnc6qpSHBlG2IWpc_kkngrd2Yvt2IPXm49KA8607v9hSpPURiUqMZfSb6Rz4lgGSZCmMZdSy0hFdNBcBUGyt5I3YmguRup3Bg9CKbPOFgWbPZ27iFEs-fh-ZSCDQzy_T0-x5J7JbbcOWnBYjaQxG0dhH27hzB9yZx0vcQ8Nz6Yx1i-fEUbKL-LmrLnw3ZQxyvc-snhE87X2nS6IC3gC9VbcqUd6kJunHUT5a753bSdv1Y-pf-Dv_-1y2c6fc7XN5JrrH5fg5OmIUC1T6xek0OtRA1lKwtsA8AuYy00MCC240fYxX1P83t6c2g_XGtzwK2B6-SbJwfuSKk-YM6FJgorzVUTeJXAh8kKYU5WJ6_iS2OLJlCTmyROwzrWZ-196zAGIaFS6lhBAjenHlRYXkIaNoMClt4pfUJ9bB6TpXYG-msA8Mffv0HeHfiUsCR5ZEu0unP4jSvl6y6PlYFZ2If2cGfYCJyBnaU1O8IonZ86ZR9WDIaVzug9xCM_otm_UjqdPrJ2OBxiIGfzBCmPja1g6qcXoH_jBGMoUDF8K4xA_1sORMYHRhNo4psG9ca13-kTItWQfml-Ff43rAPEVSgnOod5h6p4_Q44yDUgqHTxDu3OlpDjWJgdzP2C7yxNJ2kyYVddYbKCcwGQn9LyyMFKiLhqupNveVf9o7TmaKg2hy28x6JSUbpRUPHPCXgzCw2JNwX58_UHHMYzB3SAVzwJwZrlwFxXYxkimeUHh56OFCSo66HPXjrfO7zWHPp0Mo5pTIMJmINToXnH0CVTnMbIjeQimU5pNqHzZDwqFmkxT-d85JXXctE7PXhMlnAB2GF7wG7y6OAn_e1AgbGdcrms-R6IdACKfHGQA264WNgb7mGBwQuQ1iFp-xMYzu_y5pow6qxe3CShr-Q-m1rvz39PrTU_Adq5tLGyJjOWpqN6MeOFZCWdUsqEzHhBqcjLmaDFmM45LecjzXOpHcYjYqyRh55X8AxBGakFo4zRLMmSOcvScTzOZiXLKZukE1Zm43k0pnIHbTlGHFgdI7sIkCCNDha1ct4Ni9B5VdXIEH7UD7eu2tjF70YfVxoqds39KNhfBPz_Ar6CCTs">