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: gcc-10
12 
13 // constexpr decltype(auto) operator*();
14 // constexpr decltype(auto) operator*() const
15 //   requires dereferenceable<const I>;
16 
17 #include <iterator>
18 
19 #include "test_macros.h"
20 #include "test_iterators.h"
21 
22 struct InputOrOutputArchetype {
23   using difference_type = int;
24 
25   int *ptr;
26 
27   constexpr int operator*() const { return *ptr; }
28   constexpr void operator++(int) { ++ptr; }
29   constexpr InputOrOutputArchetype& operator++() { ++ptr; return *this; }
30 };
31 
32 struct NonConstDeref {
33   using difference_type = int;
34 
35   int *ptr;
36 
37   constexpr int operator*() { return *ptr; }
38   constexpr void operator++(int) { ++ptr; }
39   constexpr NonConstDeref& operator++() { ++ptr; return *this; }
40 };
41 
42 template<class T>
43 concept IsDereferenceable = requires(T& i) {
44   *i;
45 };
46 
47 constexpr bool test() {
48   int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8};
49 
50   {
51     static_assert( IsDereferenceable<std::counted_iterator<InputOrOutputArchetype>>);
52     static_assert( IsDereferenceable<const std::counted_iterator<InputOrOutputArchetype>>);
53     static_assert( IsDereferenceable<std::counted_iterator<NonConstDeref>>);
54     static_assert(!IsDereferenceable<const std::counted_iterator<NonConstDeref>>);
55   }
56 
57   {
58     std::counted_iterator iter(cpp20_input_iterator<int*>{buffer}, 8);
59     for (int i = 1; i < 9; ++i, ++iter)
60       assert(*iter == i);
61   }
62 
63   {
64     std::counted_iterator iter(forward_iterator<int*>{buffer}, 8);
65     for (int i = 1; i < 9; ++i, ++iter)
66       assert(*iter == i);
67   }
68 
69   {
70     std::counted_iterator iter(contiguous_iterator<int*>{buffer}, 8);
71     for (int i = 1; i < 9; ++i, ++iter)
72       assert(*iter == i);
73   }
74 
75   {
76     std::counted_iterator iter(InputOrOutputArchetype{buffer}, 8);
77     for (int i = 1; i < 9; ++i, ++iter)
78       assert(*iter == i);
79   }
80 
81   {
82     const std::counted_iterator iter(cpp20_input_iterator<int*>{buffer}, 8);
83     assert(*iter == 1);
84   }
85 
86   {
87     const std::counted_iterator iter(forward_iterator<int*>{buffer + 1}, 7);
88     assert(*iter == 2);
89   }
90 
91   {
92     const std::counted_iterator iter(contiguous_iterator<int*>{buffer + 2}, 6);
93     assert(*iter == 3);
94   }
95 
96   {
97     const std::counted_iterator iter(InputOrOutputArchetype{buffer + 2}, 6);
98     assert(*iter == 3);
99   }
100 
101   return true;
102 }
103 
104 int main(int, char**) {
105   test();
106   static_assert(test());
107 
108   return 0;
109 }
110