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