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, class U>
13 // concept same_as;
14
15 #include <concepts>
16 #include <type_traits>
17
18 struct S1 {};
19 struct S2 {
20 int i;
21
22 int& f();
23 double g(int x) const;
24 };
25 struct S3 {
26 int& r;
27 };
28 struct S4 {
29 int&& r;
30 };
31 struct S5 {
32 int* p;
33 };
34
35 class C1 {};
36 class C2 {
37 [[maybe_unused]] int i;
38 };
39
40 class C3 {
41 public:
42 int i;
43 };
44
45 template <class T1, class T2 = T1>
46 class C4 {
47 int t1;
48 int t2;
49 };
50
51 template <class T1, class T2 = T1>
52 class C5 {
53 [[maybe_unused]] T1 t1;
54
55 public:
56 T2 t2;
57 };
58
59 template <class T1, class T2 = T1>
60 class C6 {
61 public:
62 [[maybe_unused]] T1 t1;
63 [[maybe_unused]] T2 t2;
64 };
65
66 template <class T>
67 struct identity {
68 using type = T;
69 };
70
71 template <template <typename> class Modifier = identity>
CheckSameAs()72 void 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
114 template <template <typename> class Modifier1,
115 template <typename> class Modifier2>
CheckNotSameAs()116 void 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
156 template <class T, class U>
157 requires std::same_as<T, U> void SubsumptionTest();
158
159 // clang-format off
160 template <class T, class U>
161 requires std::same_as<U, T> && true // NOLINT(readability-simplify-boolean-expr)
162 int SubsumptionTest();
163 // clang-format on
164
165 static_assert(std::same_as<int, decltype(SubsumptionTest<int, int>())>);
166 static_assert(std::same_as<int, decltype(SubsumptionTest<void, void>())>);
167 static_assert(
168 std::same_as<int, decltype(SubsumptionTest<int (*)(), int (*)()>())>);
169 static_assert(
170 std::same_as<
171 int, decltype(SubsumptionTest<double (&)(int), double (&)(int)>())>);
172 static_assert(
173 std::same_as<int, decltype(SubsumptionTest<int S2::*, int S2::*>())>);
174 static_assert(
175 std::same_as<int,
176 decltype(SubsumptionTest<int& (S2::*)(), int& (S2::*)()>())>);
177
main(int,char **)178 int 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 }
297