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 // template<class T>
13 // struct indirectly_readable_traits;
14
15 #include <iterator>
16
17 #include <concepts>
18 #include <memory>
19 #include <optional>
20 #include <string>
21 #include <vector>
22
23 template <class T>
24 concept has_no_value_type = !requires {
25 typename std::indirectly_readable_traits<T>::value_type;
26 };
27
28 template <class T, class Expected>
29 concept value_type_matches =
30 std::same_as<typename std::indirectly_readable_traits<T>::value_type, Expected>;
31
32 template <class T>
check_pointer()33 constexpr bool check_pointer() {
34 constexpr bool result = value_type_matches<T*, T>;
35 static_assert(value_type_matches<T const*, T> == result);
36 static_assert(value_type_matches<T volatile*, T> == result);
37 static_assert(value_type_matches<T const volatile*, T> == result);
38
39 static_assert(value_type_matches<T* const, T> == result);
40 static_assert(value_type_matches<T const* const, T> == result);
41 static_assert(value_type_matches<T volatile* const, T> == result);
42 static_assert(value_type_matches<T const volatile* const, T> == result);
43
44 return result;
45 }
46
47 template <class T>
check_array()48 constexpr bool check_array() {
49 static_assert(value_type_matches<T[], T>);
50 static_assert(value_type_matches<T const[], T>);
51 static_assert(value_type_matches<T volatile[], T>);
52 static_assert(value_type_matches<T const volatile[], T>);
53 static_assert(value_type_matches<T[10], T>);
54 static_assert(value_type_matches<T const[10], T>);
55 static_assert(value_type_matches<T volatile[10], T>);
56 static_assert(value_type_matches<T const volatile[10], T>);
57 return true;
58 }
59
60 template <class T, class Expected>
check_member()61 constexpr bool check_member() {
62 static_assert(value_type_matches<T, Expected>);
63 static_assert(value_type_matches<T const, Expected>);
64 static_assert(value_type_matches<T volatile, Expected>);
65 return true;
66 }
67
68 static_assert(check_pointer<int>());
69 static_assert(check_pointer<int*>());
70 static_assert(check_pointer<int[10]>());
71 static_assert(!check_pointer<void>());
72 static_assert(!check_pointer<int()>());
73
74 static_assert(check_array<int>());
75 static_assert(check_array<int*>());
76 static_assert(check_array<int[10]>());
77
78 template<class T>
79 struct ValueOf {
80 using value_type = T;
81 };
82
83 template<class U>
84 struct ElementOf {
85 using element_type = U;
86 };
87
88 template<class T, class U>
89 struct TwoTypes {
90 using value_type = T;
91 using element_type = U;
92 };
93
94 static_assert(check_member<ValueOf<int>, int>());
95 static_assert(check_member<ValueOf<int[10]>, int[10]>());
96 static_assert(check_member<ValueOf<int[]>, int[]>());
97 static_assert(has_no_value_type<ValueOf<void>>);
98 static_assert(has_no_value_type<ValueOf<int()>>);
99 static_assert(has_no_value_type<ValueOf<int&>>);
100 static_assert(has_no_value_type<ValueOf<int&&>>);
101
102 static_assert(check_member<ElementOf<int>, int>());
103 static_assert(check_member<ElementOf<int[10]>, int[10]>());
104 static_assert(check_member<ElementOf<int[]>, int[]>());
105 static_assert(has_no_value_type<ElementOf<void>>);
106 static_assert(has_no_value_type<ElementOf<int()>>);
107 static_assert(has_no_value_type<ElementOf<int&>>);
108 static_assert(has_no_value_type<ElementOf<int&&>>);
109
110 static_assert(check_member<TwoTypes<int, int>, int>());
111 static_assert(check_member<TwoTypes<int, int const>, int>());
112 static_assert(check_member<TwoTypes<int, int volatile>, int>());
113 static_assert(check_member<TwoTypes<int, int const volatile>, int>());
114 static_assert(check_member<TwoTypes<int const, int>, int>());
115 static_assert(check_member<TwoTypes<int const, int const>, int>());
116 static_assert(check_member<TwoTypes<int const, int volatile>, int>());
117 static_assert(check_member<TwoTypes<int const, int const volatile>, int>());
118 static_assert(check_member<TwoTypes<int volatile, int>, int>());
119 static_assert(check_member<TwoTypes<int volatile, int const>, int>());
120 static_assert(check_member<TwoTypes<int volatile, int volatile>, int>());
121 static_assert(check_member<TwoTypes<int volatile, int const volatile>, int>());
122 static_assert(check_member<TwoTypes<int const volatile, int>, int>());
123 static_assert(check_member<TwoTypes<int const volatile, int const>, int>());
124 static_assert(check_member<TwoTypes<int const volatile, int volatile>, int>());
125 static_assert(check_member<TwoTypes<int const volatile, int const volatile>, int>());
126 static_assert(has_no_value_type<TwoTypes<int, long>>);
127 static_assert(has_no_value_type<TwoTypes<int, int&>>);
128 static_assert(has_no_value_type<TwoTypes<int&, int>>);
129
130 struct S2 {};
131 template <>
132 struct std::indirectly_readable_traits<S2> {
133 using value_type = int;
134 };
135 static_assert(value_type_matches<S2, int>);
136 static_assert(value_type_matches<const S2, int>);
137 static_assert(has_no_value_type<volatile S2>);
138 static_assert(has_no_value_type<const volatile S2>);
139 static_assert(has_no_value_type<S2&>);
140 static_assert(has_no_value_type<const S2&>);
141
142 static_assert(check_member<std::vector<int>, int>());
143 static_assert(check_member<std::vector<int>::iterator, int>());
144 static_assert(check_member<std::vector<int>::const_iterator, int>());
145 static_assert(check_member<std::istream_iterator<int>, int>());
146 static_assert(check_member<std::istreambuf_iterator<char>, char>());
147 static_assert(check_member<std::optional<int>, int>());
148 static_assert(check_member<std::shared_ptr<long>, long>());
149 static_assert(check_member<std::shared_ptr<const long>, long>());
150 static_assert(has_no_value_type<void>);
151 static_assert(has_no_value_type<int>);
152 static_assert(has_no_value_type<std::nullptr_t>);
153