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 // UNSUPPORTED: libcpp-no-concepts
11 // UNSUPPORTED: libcpp-has-no-incomplete-ranges
12 
13 // template<common_with<I> I2>
14 //   friend constexpr bool operator==(
15 //     const counted_iterator& x, const counted_iterator<I2>& y);
16 // friend constexpr bool operator==(
17 //   const counted_iterator& x, default_sentinel_t);
18 
19 #include <iterator>
20 
21 #include "test_macros.h"
22 #include "test_iterators.h"
23 
24 // This iterator is common_with forward_iterator but NOT comparable with it.
25 template <class It>
26 class CommonWithForwardIter
27 {
28     It it_;
29 
30 public:
31     typedef          std::input_iterator_tag                   iterator_category;
32     typedef typename std::iterator_traits<It>::value_type      value_type;
33     typedef typename std::iterator_traits<It>::difference_type difference_type;
34     typedef It                                                 pointer;
35     typedef typename std::iterator_traits<It>::reference       reference;
36 
37     constexpr It base() const {return it_;}
38 
39     CommonWithForwardIter() = default;
40     explicit constexpr CommonWithForwardIter(It it) : it_(it) {}
41     constexpr CommonWithForwardIter(const forward_iterator<It>& it) : it_(it.base()) {}
42 
43     constexpr reference operator*() const {return *it_;}
44 
45     constexpr CommonWithForwardIter& operator++() {++it_; return *this;}
46     constexpr CommonWithForwardIter operator++(int)
47         {CommonWithForwardIter tmp(*this); ++(*this); return tmp;}
48 };
49 
50 struct InputOrOutputArchetype {
51   using difference_type = int;
52 
53   int *ptr;
54 
55   constexpr int operator*() { return *ptr; }
56   constexpr void operator++(int) { ++ptr; }
57   constexpr InputOrOutputArchetype& operator++() { ++ptr; return *this; }
58 };
59 
60 constexpr bool test() {
61   int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8};
62 
63   {
64     {
65       std::counted_iterator iter1(forward_iterator<int*>(buffer), 8);
66       std::counted_iterator iter2(CommonWithForwardIter<int*>(buffer), 8);
67 
68       assert(iter1 == iter2);
69       assert(iter2 == iter1);
70       ++iter1;
71       assert(iter1 != iter2);
72       assert(iter2 != iter1);
73     }
74   }
75 
76   {
77     {
78       std::counted_iterator iter(cpp20_input_iterator<int*>(buffer), 8);
79 
80       assert(iter != std::default_sentinel);
81       assert(std::default_sentinel == std::ranges::next(std::move(iter), 8));
82     }
83     {
84       std::counted_iterator iter(forward_iterator<int*>(buffer), 8);
85 
86       assert(iter != std::default_sentinel);
87       assert(std::default_sentinel == std::ranges::next(iter, 8));
88     }
89     {
90       std::counted_iterator iter(random_access_iterator<int*>(buffer), 8);
91 
92       assert(iter != std::default_sentinel);
93       assert(std::default_sentinel == std::ranges::next(iter, 8));
94     }
95     {
96       std::counted_iterator iter(InputOrOutputArchetype{buffer}, 8);
97 
98       assert(iter != std::default_sentinel);
99       assert(std::default_sentinel == std::ranges::next(iter, 8));
100     }
101   }
102 
103 
104   return true;
105 }
106 
107 int main(int, char**) {
108   test();
109   static_assert(test());
110 
111   return 0;
112 }
113