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