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