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

    <tr>
        <th>Summary</th>
        <td>
            `<algorithm>`: `ranges::ends_with`'s constraint check for bidirectional case is not quite right
        </td>
    </tr>

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

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

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

<pre>
    `ranges::ends_with` only checks whether the two sentinel types satisfy `bidirectional_iterator` then unconditionally warps all iterators and sentinels into `reverse_iterator`s.

https://github.com/llvm/llvm-project/blob/19a62fbe00930d7eaa9f948c8dd26d58f5422c00/libcxx/include/__algorithm/ranges_ends_with.h#L67-L69

There are two implicit issues here. First, theoretically, the iterator can still not satisfy `bidirectional_iterator` in such case, which makes the construction of `reverse_iterator` ill-formed. Second, the reference of sentinels and iterators may not be the same, which makes the predicate and projection functions not necessarily applicable to the `reverse_iterator`.

The following demos the issue:

```cpp
#include <algorithm>
#include <list>

struct Proj {
  int operator()(auto&);
  int operator()(const auto&) = delete;
};

int main() {
  std::list<int> l;
 std::ranges::subrange s{l.begin(), l.cend()};
  return std::ranges::ends_with(s, s, {}, Proj{}, Proj{}); // hard error in libc++
}
```
https://godbolt.org/z/xrMdreWEv
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJyUVV2P4yYU_TXk5WosjGM7fvDDfKyftlKlVurjCMN1YIeAC3gy6a-vwJkku0pXXcnCfB4u51wOPAS9t4g9qZ9I_bLhS1TO9wqP2pi3zejkqScN9dzuMZDqkVSPaGV4PeqoSEPBWXMCoVC8BTgqjAo9RIUQjw4C2qgtGoinGQMEHnWYTkAaOmqpPYqoneXmVUf0PDqf8KJCC4sVzkq9DpsTHLmfA3Bj4HNqAG7lZYMA2kaXgD2-ow94CxkKQl8IfVxLFeOcz8EGwoa9jmoZC-EOhA3GvH_-HmbvvqGIhA2jcSNhQ9nxhk0jUtpVVLbIeTd1253YSckaWe-mesuYoDQB6FF8fBA2aCvMIpGw4fWVm73zOqq0w0rm64XHQhFWfW3ah69Ndxvrnwo9Avcrm_owGy10BB3CggHSYAGD9iES9pyIcx6jFomxc8eFLhDcQojaGLAu_j8ltIWwCAWCB0x4R6WFggN_w5CxhbMh-iUvBTf9B_ugjXmYnD-gLOAPTLp-BudxQo9WYFp9lTIJe5X5wE855BHzmsAPd4OZPUoteMS8_KxeCmxabK6EjGJRYAjca3MCPic--WgQossg909Q_CAJTM4Yd9R2DxIPbt0_a5LS6mYuaej6iXk-97DqnBNAqudrSlRf7o0bHeJ1KJcr4fC7d9-AtE9rJ6TsBzefI2Y7wjrCdnyJjrAmNaqfz8xKwnU-kOoFJBqMeFlK2pdrPZcJ6sC1XWFuwwlRrk6xnuBZ23QOMNc4LjNufSUsY25CIO2TKUbcf4InxU0hMOVObt8EA-AxLt7ex7x6FduFBJOLFGv7kmqJyfutxBqsLgGKewnovfPpVqT7TdhT-i7UfC_4XatxcnQmFs7vCRv-IWz48L9Jj399ed_IvpJd1fEN9mVb1g1lXVduVI-Mcqxr0WEtprGluCulbMZmos1UCTFudM8o29K6rErGqpIWZYXTlu24xEZ0skWypXjg2hTJ1dLem5ypfVd2NdsYPqIJ2foZs3g8pzFj6SXwfXbCcdkHsqVJynBFiToaTA_Dj3mceh7hJy8GYW04ewdPKZTfDpich--sKNsO6PXa_r3oiOD1XsXN4k3_yya-WiZhQz73vwEAAP__3_s4yw">