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