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