blob: 76e019da438ce0dea29fd527793ce65089002ae4 [file] [log] [blame]
Eric Fiselier601f7632020-04-08 18:00:13 -04001//===----------------------------------------------------------------------===//
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++98, c++03, c++11, c++14, c++17
Eric Fiselierbf90b8f2020-04-08 18:25:01 -040010// UNSUPPORTED: libcpp-no-concepts
Eric Fiselier601f7632020-04-08 18:00:13 -040011
12// template<class T, class U>
13// concept same_as;
14
15#include <concepts>
16#include <type_traits>
17
18struct S1 {};
19struct S2 {
20 int i;
21
22 int& f();
23 double g(int x) const;
24};
25struct S3 {
26 int& r;
27};
28struct S4 {
29 int&& r;
30};
31struct S5 {
32 int* p;
33};
34
35class C1 {};
36class C2 {
37 [[maybe_unused]] int i;
38};
39
40class C3 {
41public:
42 int i;
43};
44
45template <class T1, class T2 = T1>
46class C4 {
47 int t1;
48 int t2;
49};
50
51template <class T1, class T2 = T1>
52class C5 {
53 [[maybe_unused]] T1 t1;
54
55public:
56 T2 t2;
57};
58
59template <class T1, class T2 = T1>
60class C6 {
61public:
62 [[maybe_unused]] T1 t1;
63 [[maybe_unused]] T2 t2;
64};
65
66template <class T>
67struct identity {
68 using type = T;
69};
70
71template <template <typename> class Modifier = identity>
72void CheckSameAs() {
73 static_assert(
74 std::same_as<typename Modifier<int>::type, typename Modifier<int>::type>);
75 static_assert(
76 std::same_as<typename Modifier<S1>::type, typename Modifier<S1>::type>);
77 static_assert(
78 std::same_as<typename Modifier<S2>::type, typename Modifier<S2>::type>);
79 static_assert(
80 std::same_as<typename Modifier<S3>::type, typename Modifier<S3>::type>);
81 static_assert(
82 std::same_as<typename Modifier<S4>::type, typename Modifier<S4>::type>);
83 static_assert(
84 std::same_as<typename Modifier<S5>::type, typename Modifier<S5>::type>);
85 static_assert(
86 std::same_as<typename Modifier<C1>::type, typename Modifier<C1>::type>);
87 static_assert(
88 std::same_as<typename Modifier<C2>::type, typename Modifier<C2>::type>);
89 static_assert(
90 std::same_as<typename Modifier<C3>::type, typename Modifier<C3>::type>);
91 static_assert(std::same_as<typename Modifier<C4<int> >::type,
92 typename Modifier<C4<int> >::type>);
93 static_assert(std::same_as<typename Modifier<C4<int&> >::type,
94 typename Modifier<C4<int&> >::type>);
95 static_assert(std::same_as<typename Modifier<C4<int&&> >::type,
96 typename Modifier<C4<int&&> >::type>);
97 static_assert(std::same_as<typename Modifier<C5<int> >::type,
98 typename Modifier<C5<int> >::type>);
99 static_assert(std::same_as<typename Modifier<C5<int&> >::type,
100 typename Modifier<C5<int&> >::type>);
101 static_assert(std::same_as<typename Modifier<C5<int&&> >::type,
102 typename Modifier<C5<int&&> >::type>);
103 static_assert(std::same_as<typename Modifier<C6<int> >::type,
104 typename Modifier<C6<int> >::type>);
105 static_assert(std::same_as<typename Modifier<C6<int&> >::type,
106 typename Modifier<C6<int&> >::type>);
107 static_assert(std::same_as<typename Modifier<C6<int&&> >::type,
108 typename Modifier<C6<int&&> >::type>);
109
110 static_assert(std::same_as<typename Modifier<void>::type,
111 typename Modifier<void>::type>);
112}
113
114template <template <typename> class Modifier1,
115 template <typename> class Modifier2>
116void CheckNotSameAs() {
117 static_assert(!std::same_as<typename Modifier1<int>::type,
118 typename Modifier2<int>::type>);
119 static_assert(!std::same_as<typename Modifier1<S1>::type,
120 typename Modifier2<S1>::type>);
121 static_assert(!std::same_as<typename Modifier1<S2>::type,
122 typename Modifier2<S2>::type>);
123 static_assert(!std::same_as<typename Modifier1<S3>::type,
124 typename Modifier2<S3>::type>);
125 static_assert(!std::same_as<typename Modifier1<S4>::type,
126 typename Modifier2<S4>::type>);
127 static_assert(!std::same_as<typename Modifier1<S5>::type,
128 typename Modifier2<S5>::type>);
129 static_assert(!std::same_as<typename Modifier1<C1>::type,
130 typename Modifier2<C1>::type>);
131 static_assert(!std::same_as<typename Modifier1<C2>::type,
132 typename Modifier2<C2>::type>);
133 static_assert(!std::same_as<typename Modifier1<C3>::type,
134 typename Modifier2<C3>::type>);
135 static_assert(!std::same_as<typename Modifier1<C4<int> >::type,
136 typename Modifier2<C4<int> >::type>);
137 static_assert(!std::same_as<typename Modifier1<C4<int&> >::type,
138 typename Modifier2<C4<int&> >::type>);
139 static_assert(!std::same_as<typename Modifier1<C4<int&&> >::type,
140 typename Modifier2<C4<int&&> >::type>);
141 static_assert(!std::same_as<typename Modifier1<C5<int> >::type,
142 typename Modifier2<C5<int> >::type>);
143 static_assert(!std::same_as<typename Modifier1<C5<int&> >::type,
144 typename Modifier2<C5<int&> >::type>);
145 static_assert(!std::same_as<typename Modifier1<C5<int&&> >::type,
146 typename Modifier2<C5<int&&> >::type>);
147 static_assert(!std::same_as<typename Modifier1<C6<int> >::type,
148 typename Modifier2<C6<int> >::type>);
149 static_assert(!std::same_as<typename Modifier1<C6<int&> >::type,
150 typename Modifier2<C6<int&> >::type>);
151 static_assert(!std::same_as<typename Modifier1<C6<int&&> >::type,
152 typename Modifier2<C6<int&&> >::type>);
153}
154
155// Checks subsumption works as intended
156template <class T, class U>
157requires std::same_as<T, U> void SubsumptionTest();
158
159// clang-format off
160template <class T, class U>
161requires std::same_as<U, T> && true // NOLINT(readability-simplify-boolean-expr)
162int SubsumptionTest();
163// clang-format on
164
165static_assert(std::same_as<int, decltype(SubsumptionTest<int, int>())>);
166static_assert(std::same_as<int, decltype(SubsumptionTest<void, void>())>);
167static_assert(
168 std::same_as<int, decltype(SubsumptionTest<int (*)(), int (*)()>())>);
169static_assert(
170 std::same_as<
171 int, decltype(SubsumptionTest<double (&)(int), double (&)(int)>())>);
172static_assert(
173 std::same_as<int, decltype(SubsumptionTest<int S2::*, int S2::*>())>);
174static_assert(
175 std::same_as<int,
176 decltype(SubsumptionTest<int& (S2::*)(), int& (S2::*)()>())>);
177
178int main(int, char**) {
179 { // Checks std::same_as<T, T> is true
180 CheckSameAs();
181
182 // Checks std::same_as<T&, T&> is true
183 CheckSameAs<std::add_lvalue_reference>();
184
185 // Checks std::same_as<T&&, T&&> is true
186 CheckSameAs<std::add_rvalue_reference>();
187
188 // Checks std::same_as<const T, const T> is true
189 CheckSameAs<std::add_const>();
190
191 // Checks std::same_as<volatile T, volatile T> is true
192 CheckSameAs<std::add_volatile>();
193
194 // Checks std::same_as<const volatile T, const volatile T> is true
195 CheckSameAs<std::add_cv>();
196
197 // Checks std::same_as<T*, T*> is true
198 CheckSameAs<std::add_pointer>();
199
200 // Checks concrete types are identical
201 static_assert(std::same_as<void, void>);
202
203 using Void = void;
204 static_assert(std::same_as<void, Void>);
205
206 static_assert(std::same_as<int[1], int[1]>);
207 static_assert(std::same_as<int[2], int[2]>);
208
209 static_assert(std::same_as<int (*)(), int (*)()>);
210 static_assert(std::same_as<void (&)(), void (&)()>);
211 static_assert(std::same_as<S1& (*)(S1), S1& (*)(S1)>);
212 static_assert(std::same_as<C1& (&)(S1, int), C1& (&)(S1, int)>);
213
214 static_assert(std::same_as<int S2::*, int S2::*>);
215 static_assert(std::same_as<double S2::*, double S2::*>);
216
217 static_assert(std::same_as<int& (S2::*)(), int& (S2::*)()>);
218 static_assert(std::same_as<double& (S2::*)(int), double& (S2::*)(int)>);
219 }
220
221 { // Checks that `T` and `T&` are distinct types
222 CheckNotSameAs<identity, std::add_lvalue_reference>();
223 CheckNotSameAs<std::add_lvalue_reference, identity>();
224
225 // Checks that `T` and `T&&` are distinct types
226 CheckNotSameAs<identity, std::add_rvalue_reference>();
227 CheckNotSameAs<std::add_rvalue_reference, identity>();
228
229 // Checks that `T` and `const T` are distinct types
230 CheckNotSameAs<identity, std::add_const>();
231 CheckNotSameAs<std::add_const, identity>();
232
233 // Checks that `T` and `volatile T` are distinct types
234 CheckNotSameAs<identity, std::add_volatile>();
235 CheckNotSameAs<std::add_volatile, identity>();
236
237 // Checks that `T` and `const volatile T` are distinct types
238 CheckNotSameAs<identity, std::add_cv>();
239 CheckNotSameAs<std::add_cv, identity>();
240
241 // Checks that `const T` and `volatile T` are distinct types
242 CheckNotSameAs<std::add_const, std::add_volatile>();
243 CheckNotSameAs<std::add_volatile, std::add_const>();
244
245 // Checks that `const T` and `const volatile T` are distinct types
246 CheckNotSameAs<std::add_const, std::add_cv>();
247 CheckNotSameAs<std::add_cv, std::add_const>();
248
249 // Checks that `volatile T` and `const volatile T` are distinct types
250 CheckNotSameAs<std::add_volatile, std::add_cv>();
251 CheckNotSameAs<std::add_cv, std::add_volatile>();
252
253 // Checks `T&` and `T&&` are distinct types
254 CheckNotSameAs<std::add_lvalue_reference, std::add_rvalue_reference>();
255 CheckNotSameAs<std::add_rvalue_reference, std::add_lvalue_reference>();
256 }
257
258 { // Checks different type names are distinct types
259 static_assert(!std::same_as<S1, C1>);
260 static_assert(!std::same_as<C4<int>, C5<int> >);
261 static_assert(!std::same_as<C4<int>, C5<int> >);
262 static_assert(!std::same_as<C5<int, double>, C5<double, int> >);
263
264 static_assert(!std::same_as<int&, const int&>);
265 static_assert(!std::same_as<int&, volatile int&>);
266 static_assert(!std::same_as<int&, const volatile int&>);
267
268 static_assert(!std::same_as<int&&, const int&>);
269 static_assert(!std::same_as<int&&, volatile int&>);
270 static_assert(!std::same_as<int&&, const volatile int&>);
271
272 static_assert(!std::same_as<int&, const int&&>);
273 static_assert(!std::same_as<int&, volatile int&&>);
274 static_assert(!std::same_as<int&, const volatile int&&>);
275
276 static_assert(!std::same_as<int&&, const int&&>);
277 static_assert(!std::same_as<int&&, volatile int&&>);
278 static_assert(!std::same_as<int&&, const volatile int&&>);
279
280 static_assert(!std::same_as<void, int>);
281
282 static_assert(!std::same_as<int[1], int[2]>);
283 static_assert(!std::same_as<double[1], int[2]>);
284
285 static_assert(!std::same_as<int* (*)(), const int* (*)()>);
286 static_assert(!std::same_as<void (&)(), void (&)(S1)>);
287 static_assert(!std::same_as<S1 (*)(S1), S1& (*)(S1)>);
288 static_assert(!std::same_as<C3 (&)(int), C1& (&)(S1, int)>);
289
290 static_assert(!std::same_as<int S2::*, double S2::*>);
291
292 static_assert(!std::same_as<int& (S2::*)(), double& (S2::*)(int)>);
293 }
294
295 return 0;
296}