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