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