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 From, class To>
13 // concept common_reference_with;
14 
15 #include <concepts>
16 
17 template <class T, class U>
18 constexpr bool CheckCommonReferenceWith() noexcept {
19   static_assert(std::common_reference_with<T, U&>);
20   static_assert(std::common_reference_with<T, const U&>);
21   static_assert(std::common_reference_with<T, volatile U&>);
22   static_assert(std::common_reference_with<T, const volatile U&>);
23   static_assert(std::common_reference_with<T, U&&>);
24   static_assert(std::common_reference_with<T, const U&&>);
25   static_assert(std::common_reference_with<T, volatile U&&>);
26   static_assert(std::common_reference_with<T, const volatile U&&>);
27   static_assert(std::common_reference_with<T&, U&&>);
28   static_assert(std::common_reference_with<T&, const U&&>);
29   static_assert(std::common_reference_with<T&, volatile U&&>);
30   static_assert(std::common_reference_with<T&, const volatile U&&>);
31   static_assert(std::common_reference_with<const T&, U&&>);
32   static_assert(std::common_reference_with<const T&, const U&&>);
33   static_assert(std::common_reference_with<const T&, volatile U&&>);
34   static_assert(std::common_reference_with<const T&, const volatile U&&>);
35   static_assert(std::common_reference_with<volatile T&, U&&>);
36   static_assert(std::common_reference_with<volatile T&, const U&&>);
37   static_assert(std::common_reference_with<volatile T&, volatile U&&>);
38   static_assert(std::common_reference_with<volatile T&, const volatile U&&>);
39   static_assert(std::common_reference_with<const volatile T&, U&&>);
40   static_assert(std::common_reference_with<const volatile T&, const U&&>);
41   static_assert(std::common_reference_with<const volatile T&, volatile U&&>);
42   static_assert(
43       std::common_reference_with<const volatile T&, const volatile U&&>);
44 
45   return std::common_reference_with<T, U>;
46 }
47 
48 namespace BuiltinTypes {
49 // fundamental types
50 static_assert(std::common_reference_with<void, void>);
51 static_assert(CheckCommonReferenceWith<int, int>());
52 static_assert(CheckCommonReferenceWith<int, long>());
53 static_assert(CheckCommonReferenceWith<int, unsigned char>());
54 #ifndef _LIBCPP_HAS_NO_INT128
55 static_assert(CheckCommonReferenceWith<int, __int128_t>());
56 #endif
57 static_assert(CheckCommonReferenceWith<int, double>());
58 
59 // arrays
60 static_assert(CheckCommonReferenceWith<int[5], int[5]>());
61 
62 // pointers (common with void*)
63 static_assert(CheckCommonReferenceWith<int*, void*>());
64 static_assert(CheckCommonReferenceWith<int*, const void*>());
65 static_assert(CheckCommonReferenceWith<int*, volatile void*>());
66 static_assert(CheckCommonReferenceWith<int*, const volatile void*>());
67 static_assert(CheckCommonReferenceWith<const int*, void*>());
68 static_assert(CheckCommonReferenceWith<const int*, const void*>());
69 static_assert(CheckCommonReferenceWith<const int*, volatile void*>());
70 static_assert(CheckCommonReferenceWith<const int*, const volatile void*>());
71 static_assert(CheckCommonReferenceWith<volatile int*, void*>());
72 static_assert(CheckCommonReferenceWith<volatile int*, const void*>());
73 static_assert(CheckCommonReferenceWith<volatile int*, volatile void*>());
74 static_assert(CheckCommonReferenceWith<volatile int*, const volatile void*>());
75 static_assert(CheckCommonReferenceWith<const volatile int*, void*>());
76 static_assert(CheckCommonReferenceWith<const volatile int*, const void*>());
77 static_assert(CheckCommonReferenceWith<const volatile int*, volatile void*>());
78 static_assert(
79     CheckCommonReferenceWith<const volatile int*, const volatile void*>());
80 
81 static_assert(CheckCommonReferenceWith<int (*)(), int (*)()>());
82 static_assert(CheckCommonReferenceWith<int (*)(), int (*)() noexcept>());
83 struct S {};
84 static_assert(CheckCommonReferenceWith<int S::*, int S::*>());
85 static_assert(CheckCommonReferenceWith<int S::*, const int S::*>());
86 static_assert(CheckCommonReferenceWith<int (S::*)(), int (S::*)()>());
87 static_assert(CheckCommonReferenceWith<int (S::*)(), int (S::*)() noexcept>());
88 static_assert(
89     CheckCommonReferenceWith<int (S::*)() const, int (S::*)() const>());
90 static_assert(CheckCommonReferenceWith<int (S::*)() const,
91                                        int (S::*)() const noexcept>());
92 static_assert(
93     CheckCommonReferenceWith<int (S::*)() volatile, int (S::*)() volatile>());
94 static_assert(CheckCommonReferenceWith<int (S::*)() volatile,
95                                        int (S::*)() volatile noexcept>());
96 static_assert(CheckCommonReferenceWith<int (S::*)() const volatile,
97                                        int (S::*)() const volatile>());
98 static_assert(CheckCommonReferenceWith<int (S::*)() const volatile,
99                                        int (S::*)() const volatile noexcept>());
100 
101 // nonsense
102 static_assert(!std::common_reference_with<double, float*>);
103 static_assert(!std::common_reference_with<int, int[5]>);
104 static_assert(!std::common_reference_with<int*, long*>);
105 static_assert(!std::common_reference_with<int*, unsigned int*>);
106 static_assert(!std::common_reference_with<int (*)(), int (*)(int)>);
107 static_assert(!std::common_reference_with<int S::*, float S::*>);
108 static_assert(!std::common_reference_with<int (S::*)(), int (S::*)() const>);
109 static_assert(!std::common_reference_with<int (S::*)(), int (S::*)() volatile>);
110 static_assert(
111     !std::common_reference_with<int (S::*)(), int (S::*)() const volatile>);
112 static_assert(
113     !std::common_reference_with<int (S::*)() const, int (S::*)() volatile>);
114 static_assert(!std::common_reference_with<int (S::*)() const,
115                                           int (S::*)() const volatile>);
116 static_assert(!std::common_reference_with<int (S::*)() volatile,
117                                           int (S::*)() const volatile>);
118 } // namespace BuiltinTypes
119 
120 namespace NoDefaultCommonReference {
121 class T {};
122 
123 static_assert(!std::common_reference_with<T, int>);
124 static_assert(!std::common_reference_with<int, T>);
125 static_assert(!std::common_reference_with<T, int[10]>);
126 static_assert(!std::common_reference_with<T[10], int>);
127 static_assert(!std::common_reference_with<T*, int*>);
128 static_assert(!std::common_reference_with<T*, const int*>);
129 static_assert(!std::common_reference_with<T*, volatile int*>);
130 static_assert(!std::common_reference_with<T*, const volatile int*>);
131 static_assert(!std::common_reference_with<const T*, int*>);
132 static_assert(!std::common_reference_with<volatile T*, int*>);
133 static_assert(!std::common_reference_with<const volatile T*, int*>);
134 static_assert(!std::common_reference_with<const T*, const int*>);
135 static_assert(!std::common_reference_with<const T*, volatile int*>);
136 static_assert(!std::common_reference_with<const T*, const volatile int*>);
137 static_assert(!std::common_reference_with<const T*, const int*>);
138 static_assert(!std::common_reference_with<volatile T*, const int*>);
139 static_assert(!std::common_reference_with<const volatile T*, const int*>);
140 static_assert(!std::common_reference_with<volatile T*, const int*>);
141 static_assert(!std::common_reference_with<volatile T*, volatile int*>);
142 static_assert(!std::common_reference_with<volatile T*, const volatile int*>);
143 static_assert(!std::common_reference_with<const T*, volatile int*>);
144 static_assert(!std::common_reference_with<volatile T*, volatile int*>);
145 static_assert(!std::common_reference_with<const volatile T*, volatile int*>);
146 static_assert(!std::common_reference_with<const volatile T*, const int*>);
147 static_assert(!std::common_reference_with<const volatile T*, volatile int*>);
148 static_assert(
149     !std::common_reference_with<const volatile T*, const volatile int*>);
150 static_assert(!std::common_reference_with<const T*, const volatile int*>);
151 static_assert(!std::common_reference_with<volatile T*, const volatile int*>);
152 static_assert(
153     !std::common_reference_with<const volatile T*, const volatile int*>);
154 static_assert(!std::common_reference_with<T&, int&>);
155 static_assert(!std::common_reference_with<T&, const int&>);
156 static_assert(!std::common_reference_with<T&, volatile int&>);
157 static_assert(!std::common_reference_with<T&, const volatile int&>);
158 static_assert(!std::common_reference_with<const T&, int&>);
159 static_assert(!std::common_reference_with<volatile T&, int&>);
160 static_assert(!std::common_reference_with<const volatile T&, int&>);
161 static_assert(!std::common_reference_with<const T&, const int&>);
162 static_assert(!std::common_reference_with<const T&, volatile int&>);
163 static_assert(!std::common_reference_with<const T&, const volatile int&>);
164 static_assert(!std::common_reference_with<const T&, const int&>);
165 static_assert(!std::common_reference_with<volatile T&, const int&>);
166 static_assert(!std::common_reference_with<const volatile T&, const int&>);
167 static_assert(!std::common_reference_with<volatile T&, const int&>);
168 static_assert(!std::common_reference_with<volatile T&, volatile int&>);
169 static_assert(!std::common_reference_with<volatile T&, const volatile int&>);
170 static_assert(!std::common_reference_with<const T&, volatile int&>);
171 static_assert(!std::common_reference_with<volatile T&, volatile int&>);
172 static_assert(!std::common_reference_with<const volatile T&, volatile int&>);
173 static_assert(!std::common_reference_with<const volatile T&, const int&>);
174 static_assert(!std::common_reference_with<const volatile T&, volatile int&>);
175 static_assert(
176     !std::common_reference_with<const volatile T&, const volatile int&>);
177 static_assert(!std::common_reference_with<const T&, const volatile int&>);
178 static_assert(!std::common_reference_with<volatile T&, const volatile int&>);
179 static_assert(
180     !std::common_reference_with<const volatile T&, const volatile int&>);
181 static_assert(!std::common_reference_with<T&, int&&>);
182 static_assert(!std::common_reference_with<T&, const int&&>);
183 static_assert(!std::common_reference_with<T&, volatile int&&>);
184 static_assert(!std::common_reference_with<T&, const volatile int&&>);
185 static_assert(!std::common_reference_with<const T&, int&&>);
186 static_assert(!std::common_reference_with<volatile T&, int&&>);
187 static_assert(!std::common_reference_with<const volatile T&, int&&>);
188 static_assert(!std::common_reference_with<const T&, const int&&>);
189 static_assert(!std::common_reference_with<const T&, volatile int&&>);
190 static_assert(!std::common_reference_with<const T&, const volatile int&&>);
191 static_assert(!std::common_reference_with<const T&, const int&&>);
192 static_assert(!std::common_reference_with<volatile T&, const int&&>);
193 static_assert(!std::common_reference_with<const volatile T&, const int&&>);
194 static_assert(!std::common_reference_with<volatile T&, const int&&>);
195 static_assert(!std::common_reference_with<volatile T&, volatile int&&>);
196 static_assert(!std::common_reference_with<volatile T&, const volatile int&&>);
197 static_assert(!std::common_reference_with<const T&, volatile int&&>);
198 static_assert(!std::common_reference_with<volatile T&, volatile int&&>);
199 static_assert(!std::common_reference_with<const volatile T&, volatile int&&>);
200 static_assert(!std::common_reference_with<const volatile T&, const int&&>);
201 static_assert(!std::common_reference_with<const volatile T&, volatile int&&>);
202 static_assert(
203     !std::common_reference_with<const volatile T&, const volatile int&&>);
204 static_assert(!std::common_reference_with<const T&, const volatile int&&>);
205 static_assert(!std::common_reference_with<volatile T&, const volatile int&&>);
206 static_assert(
207     !std::common_reference_with<const volatile T&, const volatile int&&>);
208 static_assert(!std::common_reference_with<T&&, int&>);
209 static_assert(!std::common_reference_with<T&&, const int&>);
210 static_assert(!std::common_reference_with<T&&, volatile int&>);
211 static_assert(!std::common_reference_with<T&&, const volatile int&>);
212 static_assert(!std::common_reference_with<const T&&, int&>);
213 static_assert(!std::common_reference_with<volatile T&&, int&>);
214 static_assert(!std::common_reference_with<const volatile T&&, int&>);
215 static_assert(!std::common_reference_with<const T&&, const int&>);
216 static_assert(!std::common_reference_with<const T&&, volatile int&>);
217 static_assert(!std::common_reference_with<const T&&, const volatile int&>);
218 static_assert(!std::common_reference_with<const T&&, const int&>);
219 static_assert(!std::common_reference_with<volatile T&&, const int&>);
220 static_assert(!std::common_reference_with<const volatile T&&, const int&>);
221 static_assert(!std::common_reference_with<volatile T&&, const int&>);
222 static_assert(!std::common_reference_with<volatile T&&, volatile int&>);
223 static_assert(!std::common_reference_with<volatile T&&, const volatile int&>);
224 static_assert(!std::common_reference_with<const T&&, volatile int&>);
225 static_assert(!std::common_reference_with<volatile T&&, volatile int&>);
226 static_assert(!std::common_reference_with<const volatile T&&, volatile int&>);
227 static_assert(!std::common_reference_with<const volatile T&&, const int&>);
228 static_assert(!std::common_reference_with<const volatile T&&, volatile int&>);
229 static_assert(
230     !std::common_reference_with<const volatile T&&, const volatile int&>);
231 static_assert(!std::common_reference_with<const T&&, const volatile int&>);
232 static_assert(!std::common_reference_with<volatile T&&, const volatile int&>);
233 static_assert(
234     !std::common_reference_with<const volatile T&&, const volatile int&>);
235 static_assert(!std::common_reference_with<T&&, int&&>);
236 static_assert(!std::common_reference_with<T&&, const int&&>);
237 static_assert(!std::common_reference_with<T&&, volatile int&&>);
238 static_assert(!std::common_reference_with<T&&, const volatile int&&>);
239 static_assert(!std::common_reference_with<const T&&, int&&>);
240 static_assert(!std::common_reference_with<volatile T&&, int&&>);
241 static_assert(!std::common_reference_with<const volatile T&&, int&&>);
242 static_assert(!std::common_reference_with<const T&&, const int&&>);
243 static_assert(!std::common_reference_with<const T&&, volatile int&&>);
244 static_assert(!std::common_reference_with<const T&&, const volatile int&&>);
245 static_assert(!std::common_reference_with<const T&&, const int&&>);
246 static_assert(!std::common_reference_with<volatile T&&, const int&&>);
247 static_assert(!std::common_reference_with<const volatile T&&, const int&&>);
248 static_assert(!std::common_reference_with<volatile T&&, const int&&>);
249 static_assert(!std::common_reference_with<volatile T&&, volatile int&&>);
250 static_assert(!std::common_reference_with<volatile T&&, const volatile int&&>);
251 static_assert(!std::common_reference_with<const T&&, volatile int&&>);
252 static_assert(!std::common_reference_with<volatile T&&, volatile int&&>);
253 static_assert(!std::common_reference_with<const volatile T&&, volatile int&&>);
254 static_assert(!std::common_reference_with<const volatile T&&, const int&&>);
255 static_assert(!std::common_reference_with<const volatile T&&, volatile int&&>);
256 static_assert(
257     !std::common_reference_with<const volatile T&&, const volatile int&&>);
258 static_assert(!std::common_reference_with<const T&&, const volatile int&&>);
259 static_assert(!std::common_reference_with<volatile T&&, const volatile int&&>);
260 static_assert(
261     !std::common_reference_with<const volatile T&&, const volatile int&&>);
262 } // namespace NoDefaultCommonReference
263 
264 struct BadBasicCommonReference {
265   // This test is ill-formed, NDR. If it ever blows up in our faces: that's a good thing.
266   // In the meantime, the test should be included. If compiler support is added, then an include guard
267   // should be placed so the test doesn't get deleted.
268   operator int() const;
269   operator int&();
270 };
271 static_assert(std::convertible_to<BadBasicCommonReference, int>);
272 static_assert(std::convertible_to<BadBasicCommonReference, int&>);
273 
274 namespace std {
275 template <template <class> class X, template <class> class Y>
276 struct basic_common_reference<BadBasicCommonReference, int, X, Y> {
277   using type = BadBasicCommonReference&;
278 };
279 
280 template <template <class> class X, template <class> class Y>
281 struct basic_common_reference<int, BadBasicCommonReference, X, Y> {
282   using type = int&;
283 };
284 } // namespace std
285 static_assert(!std::common_reference_with<BadBasicCommonReference, int>);
286 
287 struct StructNotConvertibleToCommonReference {
288   explicit(false) StructNotConvertibleToCommonReference(int);
289 };
290 static_assert(std::convertible_to<int, StructNotConvertibleToCommonReference>);
291 
292 namespace std {
293 template <template <class> class X, template <class> class Y>
294 struct basic_common_reference<StructNotConvertibleToCommonReference, int, X,
295                               Y> {
296   using type = int&;
297 };
298 
299 template <template <class> class X, template <class> class Y>
300 struct basic_common_reference<int, StructNotConvertibleToCommonReference, X,
301                               Y> {
302   using type = int&;
303 };
304 } // namespace std
305 static_assert(
306     !std::common_reference_with<StructNotConvertibleToCommonReference, int>);
307 
308 struct IntNotConvertibleToCommonReference {
309   operator int&() const;
310 };
311 
312 namespace std {
313 template <template <class> class X, template <class> class Y>
314 struct basic_common_reference<IntNotConvertibleToCommonReference, int, X, Y> {
315   using type = int&;
316 };
317 
318 template <template <class> class X, template <class> class Y>
319 struct basic_common_reference<int, IntNotConvertibleToCommonReference, X, Y> {
320   using type = int&;
321 };
322 } // namespace std
323 static_assert(
324     !std::common_reference_with<StructNotConvertibleToCommonReference, int>);
325 
326 struct HasCommonReference {
327   explicit(false) HasCommonReference(int);
328   operator int&() const;
329 };
330 
331 namespace std {
332 template <template <class> class X, template <class> class Y>
333 struct basic_common_reference<HasCommonReference, int, X, Y> {
334   using type = int&;
335 };
336 
337 template <template <class> class X, template <class> class Y>
338 struct basic_common_reference<int, HasCommonReference, X, Y> {
339   using type = int&;
340 };
341 } // namespace std
342 static_assert(!std::common_reference_with<HasCommonReference, int>);
343 static_assert(std::common_reference_with<HasCommonReference, int&>);
344 
345 int main(int, char**) { return 0; }
346