[libcxx-commits] [PATCH] D128864: [libc++] Fix algorithms which use reverse_iterator

Nikolas Klauser via Phabricator via libcxx-commits libcxx-commits at lists.llvm.org
Thu Jul 21 02:30:24 PDT 2022


philnik added a comment.

In D128864#3667664 <https://reviews.llvm.org/D128864#3667664>, @var-const wrote:

> @philnik My initial impression is that we shouldn't try to solve this at the library level. This looks like a legitimate issue with the core language.

I agree that this is a core issue, but not fixing it is also not an option IMO.

> If I understand it correctly (and please point out if I'm wrong), the issue is that there is no perfect match for `operator==`, and the only `operator==` available has essentially this form:
>
>   bool operator==(const BaseIter&, const DerivedIter&);
>
> Which would work except that the C++20 rewriting rules also generate the same function with reversed arguments:
>
>   bool operator==(const DerivedIter&, const BaseIter&);
>
> Which then becomes ambiguous.

Yes.

> I think it would be easier to rewrite our existing algorithms to avoid using `reverse_iterator`. We can add a TODO to revisit the implementation when (and if) the core language issue gets fixed.

I don't think that it would be easier two rewrite existing algorithms. This would lead to a lot of complicated duplicated code. That is always a recipe for chaos and divergence. Effectively duplicating `reverse_iterator` isn't perfect either, but the code really isn't complicated. Most member functions are a single line.



================
Comment at: libcxx/include/__iterator/reverse_iterator.h:211
 #if _LIBCPP_STD_VER > 17
     requires requires {
       { __x.base() == __y.base() } -> convertible_to<bool>;
----------------
var-const wrote:
> If we're doing essentially a workaround, would it be possible/easier to instead define an internal comparator for reverse iterators and use it in the affected algorithms?
> ```
> bool __reverse_iter_eq(const reverse_iterator<_Iter1>& __x, const reverse_iterator<_Iter2>& __y) {
>   return __x.base() == __y.base();
> }
> // In the algorithm
> for (; !std::__reverse_iter_eq(__first, __last); ++__first) {
> ```
Not really. There would be no easy way to distinguish between an internal `reverse_iterator` and an external one.


================
Comment at: libcxx/include/__iterator/reverse_iterator.h:429
+  _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const _AlgRevIter& __lhs, const _AlgRevIter& __rhs) {
+    return __lhs.base() == __rhs.base();
+  }
----------------
var-const wrote:
> Hmm, so this expression is not ambiguous, but when it's used as a constraint in a `requires` clause, it is considered ambiguous? Am I missing something?
No, that's exactly the case.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D128864/new/

https://reviews.llvm.org/D128864



More information about the libcxx-commits mailing list