[libcxx-commits] [libcxx] d8f3cdf - [libcxx] Implement three-way comparison for std::reverse_iterator
Mikhail Maltsev via libcxx-commits
libcxx-commits at lists.llvm.org
Fri Nov 26 02:12:42 PST 2021
Author: Mikhail Maltsev
Date: 2021-11-26T10:12:19Z
New Revision: d8f3cdfed03fe73c152d7fbf509f34f4b502f384
URL: https://github.com/llvm/llvm-project/commit/d8f3cdfed03fe73c152d7fbf509f34f4b502f384
DIFF: https://github.com/llvm/llvm-project/commit/d8f3cdfed03fe73c152d7fbf509f34f4b502f384.diff
LOG: [libcxx] Implement three-way comparison for std::reverse_iterator
This patch implements operator<=> for std::reverse_iterator and
also adds a test that checks that three-way comparison of different
instantiations of std::reverse_iterator works as expected (related to
D113417).
Reviewed By: ldionne, Quuxplusone, #libc
Differential Revision: https://reviews.llvm.org/D113695
Added:
libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cmp/three-way.pass.cpp
Modified:
libcxx/include/__iterator/reverse_iterator.h
Removed:
################################################################################
diff --git a/libcxx/include/__iterator/reverse_iterator.h b/libcxx/include/__iterator/reverse_iterator.h
index f7a948950df20..d06859ee5f390 100644
--- a/libcxx/include/__iterator/reverse_iterator.h
+++ b/libcxx/include/__iterator/reverse_iterator.h
@@ -11,6 +11,8 @@
#define _LIBCPP___ITERATOR_REVERSE_ITERATOR_H
#include <__config>
+#include <__compare/compare_three_way_result.h>
+#include <__compare/three_way_comparable.h>
#include <__iterator/iterator.h>
#include <__iterator/iterator_traits.h>
#include <__memory/addressof.h>
@@ -193,6 +195,16 @@ operator<=(const reverse_iterator<_Iter1>& __x, const reverse_iterator<_Iter2>&
return __x.base() >= __y.base();
}
+#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_CONCEPTS)
+template <class _Iter1, three_way_comparable_with<_Iter1> _Iter2>
+_LIBCPP_HIDE_FROM_ABI constexpr
+compare_three_way_result_t<_Iter1, _Iter2>
+operator<=>(const reverse_iterator<_Iter1>& __x, const reverse_iterator<_Iter2>& __y)
+{
+ return __y.base() <=> __x.base();
+}
+#endif
+
#ifndef _LIBCPP_CXX03_LANG
template <class _Iter1, class _Iter2>
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
diff --git a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cmp/three-way.pass.cpp b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cmp/three-way.pass.cpp
new file mode 100644
index 0000000000000..e8379e24cffae
--- /dev/null
+++ b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.cmp/three-way.pass.cpp
@@ -0,0 +1,100 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-no-concepts
+
+// <iterator>
+
+// reverse_iterator
+
+// template<class Iterator1, three_way_comparable_with<Iterator1> Iterator2>
+// constexpr compare_three_way_result_t<Iterator1, Iterator2>
+// operator<=>(const reverse_iterator<Iterator1>& x,
+// const reverse_iterator<Iterator2>& y);
+
+#include <iterator>
+#include <limits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "test_iterators.h"
+
+template <class ItL, class ItR, class Ord>
+constexpr void test(ItL l, ItR r, Ord x) {
+ const std::reverse_iterator<ItL> l1(l);
+ const std::reverse_iterator<ItR> r1(r);
+ ASSERT_SAME_TYPE(decltype(l1 <=> r1), Ord);
+ assert((l1 <=> r1) == x);
+}
+
+struct Iter {
+ using iterator_category = std::bidirectional_iterator_tag;
+ using pointer = char*;
+ using reference = char&;
+ using value_type = char;
+ using
diff erence_type = double;
+
+ constexpr Iter(double value): m_value(value) {}
+ double m_value;
+private:
+ friend constexpr bool operator==(const Iter& l, const Iter& r) = default;
+ friend constexpr std::partial_ordering operator<=>(const Iter& l, const Iter& r) = default;
+};
+
+struct ConstIter {
+ using iterator_category = std::bidirectional_iterator_tag;
+ using pointer = const char*;
+ using reference = const char&;
+ using value_type = const char;
+ using
diff erence_type = double;
+
+ constexpr ConstIter(double value): m_value(value) {}
+ constexpr ConstIter(Iter it): m_value(it.m_value) {}
+ double m_value;
+private:
+ friend constexpr bool operator==(const ConstIter& l, const ConstIter& r) = default;
+ friend constexpr std::partial_ordering operator<=>(const ConstIter& l, const ConstIter& r) = default;
+};
+
+constexpr bool tests() {
+ char s[] = "1234567890";
+ test(three_way_contiguous_iterator<const char*>(s),
+ three_way_contiguous_iterator<const char*>(s),
+ std::strong_ordering::equal);
+ test(three_way_contiguous_iterator<const char*>(s),
+ three_way_contiguous_iterator<const char*>(s+1),
+ std::strong_ordering::greater);
+ test(three_way_contiguous_iterator<const char*>(s+1),
+ three_way_contiguous_iterator<const char*>(s),
+ std::strong_ordering::less);
+
+ test(s, s, std::strong_ordering::equal);
+ test(s, s+1, std::strong_ordering::greater);
+ test(s+1, s, std::strong_ordering::less);
+
+ const char* cs = s;
+ test(cs, s, std::strong_ordering::equal);
+ test(cs, s+1, std::strong_ordering::greater);
+ test(cs+1, s, std::strong_ordering::less);
+
+ constexpr double nan = std::numeric_limits<double>::quiet_NaN();
+ test(Iter(0), ConstIter(nan), std::partial_ordering::unordered);
+ test(Iter(nan), Iter(nan), std::partial_ordering::unordered);
+ test(ConstIter(0), Iter(1), std::partial_ordering::greater);
+ test(ConstIter(3), Iter(2), std::partial_ordering::less);
+ test(ConstIter(7), Iter(7), std::partial_ordering::equivalent);
+
+ return true;
+}
+
+int main(int, char**) {
+ tests();
+ static_assert(tests());
+ return 0;
+}
More information about the libcxx-commits
mailing list