1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 // UNSUPPORTED: c++03, c++11, c++14, c++17
10 
11 // <iterator>
12 
13 // reverse_iterator
14 
15 // template<class Iterator1, three_way_comparable_with<Iterator1> Iterator2>
16 //   constexpr compare_three_way_result_t<Iterator1, Iterator2>
17 //    operator<=>(const reverse_iterator<Iterator1>& x,
18 //                const reverse_iterator<Iterator2>& y);
19 
20 #include <iterator>
21 #include <limits>
22 #include <cassert>
23 
24 #include "test_macros.h"
25 #include "test_iterators.h"
26 
27 template <class ItL, class ItR, class Ord>
test(ItL l,ItR r,Ord x)28 constexpr void test(ItL l, ItR r, Ord x) {
29     const std::reverse_iterator<ItL> l1(l);
30     const std::reverse_iterator<ItR> r1(r);
31     ASSERT_SAME_TYPE(decltype(l1 <=> r1), Ord);
32     assert((l1 <=> r1) == x);
33 }
34 
35 struct Iter {
36     using iterator_category = std::bidirectional_iterator_tag;
37     using pointer = char*;
38     using reference = char&;
39     using value_type = char;
40     using difference_type = double;
41 
IterIter42     constexpr Iter(double value): m_value(value) {}
43     double m_value;
44 
45     reference operator*() const;
46 private:
47     friend constexpr bool operator==(const Iter& l, const Iter& r) = default;
48     friend constexpr std::partial_ordering operator<=>(const Iter& l, const Iter& r) = default;
49 };
50 
51 struct ConstIter {
52     using iterator_category = std::bidirectional_iterator_tag;
53     using pointer = const char*;
54     using reference = const char&;
55     using value_type = const char;
56     using difference_type = double;
57 
ConstIterConstIter58     constexpr ConstIter(double value): m_value(value) {}
ConstIterConstIter59     constexpr ConstIter(Iter it): m_value(it.m_value) {}
60     double m_value;
61 
62     reference operator*() const;
63 private:
64     friend constexpr bool operator==(const ConstIter& l, const ConstIter& r) = default;
65     friend constexpr std::partial_ordering operator<=>(const ConstIter& l, const ConstIter& r) = default;
66 };
67 
tests()68 constexpr bool tests() {
69     char s[] = "1234567890";
70     test(three_way_contiguous_iterator<const char*>(s),
71          three_way_contiguous_iterator<const char*>(s),
72          std::strong_ordering::equal);
73     test(three_way_contiguous_iterator<const char*>(s),
74          three_way_contiguous_iterator<const char*>(s+1),
75          std::strong_ordering::greater);
76     test(three_way_contiguous_iterator<const char*>(s+1),
77          three_way_contiguous_iterator<const char*>(s),
78          std::strong_ordering::less);
79 
80     test(s, s, std::strong_ordering::equal);
81     test(s, s+1, std::strong_ordering::greater);
82     test(s+1, s, std::strong_ordering::less);
83 
84     const char* cs = s;
85     test(cs, s, std::strong_ordering::equal);
86     test(cs, s+1, std::strong_ordering::greater);
87     test(cs+1, s, std::strong_ordering::less);
88 
89     constexpr double nan = std::numeric_limits<double>::quiet_NaN();
90     test(Iter(0), ConstIter(nan), std::partial_ordering::unordered);
91     test(Iter(nan), Iter(nan), std::partial_ordering::unordered);
92     test(ConstIter(0), Iter(1), std::partial_ordering::greater);
93     test(ConstIter(3), Iter(2), std::partial_ordering::less);
94     test(ConstIter(7), Iter(7), std::partial_ordering::equivalent);
95 
96     return true;
97 }
98 
main(int,char **)99 int main(int, char**) {
100     tests();
101     static_assert(tests());
102     return 0;
103 }
104