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 Derived, class Base> 13 // concept derived_from; 14 15 #include <concepts> 16 #include <type_traits> 17 18 struct Base1 {}; 19 struct Derived1 : Base1 {}; 20 struct Derived2 : Base1 {}; 21 22 struct DerivedPrivate : private Base1 {}; 23 struct Derived3 : DerivedPrivate {}; 24 25 struct DerivedProtected : protected DerivedPrivate {}; 26 struct Derived4 : DerivedProtected {}; 27 struct Derived5 : Derived4 {}; 28 29 template <typename From, typename To> 30 constexpr void CheckNotDerivedFromPointer() { 31 { // From as pointer 32 static_assert(!std::derived_from<From*, To>); 33 static_assert(!std::derived_from<From*, const To>); 34 static_assert(!std::derived_from<From*, volatile To>); 35 static_assert(!std::derived_from<From*, const volatile To>); 36 37 if constexpr (!std::same_as<To, void>) { 38 static_assert(!std::derived_from<From*, To&>); 39 static_assert(!std::derived_from<From*, const To&>); 40 static_assert(!std::derived_from<From*, volatile To&>); 41 static_assert(!std::derived_from<From*, const volatile To&>); 42 43 static_assert(!std::derived_from<From*, To&&>); 44 static_assert(!std::derived_from<From*, const To&&>); 45 static_assert(!std::derived_from<From*, volatile To&&>); 46 static_assert(!std::derived_from<From*, const volatile To&&>); 47 48 static_assert(!std::derived_from<const From*, To&>); 49 static_assert(!std::derived_from<const From*, const To&>); 50 static_assert(!std::derived_from<const From*, volatile To&>); 51 static_assert(!std::derived_from<const From*, const volatile To&>); 52 53 static_assert(!std::derived_from<const From*, To&&>); 54 static_assert(!std::derived_from<const From*, const To&&>); 55 static_assert(!std::derived_from<const From*, volatile To&&>); 56 static_assert(!std::derived_from<const From*, const volatile To&&>); 57 58 static_assert(!std::derived_from<volatile From*, To&>); 59 static_assert(!std::derived_from<volatile From*, const To&>); 60 static_assert(!std::derived_from<volatile From*, volatile To&>); 61 static_assert(!std::derived_from<volatile From*, const volatile To&>); 62 63 static_assert(!std::derived_from<volatile From*, To&&>); 64 static_assert(!std::derived_from<volatile From*, const To&&>); 65 static_assert(!std::derived_from<volatile From*, volatile To&&>); 66 static_assert(!std::derived_from<volatile From*, const volatile To&&>); 67 68 static_assert(!std::derived_from<const volatile From*, To&>); 69 static_assert(!std::derived_from<const volatile From*, const To&>); 70 static_assert(!std::derived_from<const volatile From*, volatile To&>); 71 static_assert( 72 !std::derived_from<const volatile From*, const volatile To&>); 73 74 static_assert(!std::derived_from<const volatile From*, To&&>); 75 static_assert(!std::derived_from<const volatile From*, const To&&>); 76 static_assert(!std::derived_from<const volatile From*, volatile To&&>); 77 static_assert( 78 !std::derived_from<const volatile From*, const volatile To&&>); 79 } 80 } 81 { // To as pointer 82 static_assert(!std::derived_from<From, To*>); 83 static_assert(!std::derived_from<From, const To*>); 84 static_assert(!std::derived_from<From, volatile To*>); 85 static_assert(!std::derived_from<From, const volatile To*>); 86 87 if constexpr (!std::same_as<From, void>) { 88 static_assert(!std::derived_from<From&, To*>); 89 static_assert(!std::derived_from<From&, const To*>); 90 static_assert(!std::derived_from<From&, volatile To*>); 91 static_assert(!std::derived_from<From&, const volatile To*>); 92 93 static_assert(!std::derived_from<From&&, To*>); 94 static_assert(!std::derived_from<From&&, const To*>); 95 static_assert(!std::derived_from<From&&, volatile To*>); 96 static_assert(!std::derived_from<From&&, const volatile To*>); 97 98 static_assert(!std::derived_from<const From&, To*>); 99 static_assert(!std::derived_from<const From&, const To*>); 100 static_assert(!std::derived_from<const From&, volatile To*>); 101 static_assert(!std::derived_from<const From&, const volatile To*>); 102 103 static_assert(!std::derived_from<const From&&, To*>); 104 static_assert(!std::derived_from<const From&&, const To*>); 105 static_assert(!std::derived_from<const From&&, volatile To*>); 106 static_assert(!std::derived_from<const From&&, const volatile To*>); 107 108 static_assert(!std::derived_from<volatile From&, To*>); 109 static_assert(!std::derived_from<volatile From&, const To*>); 110 static_assert(!std::derived_from<volatile From&, volatile To*>); 111 static_assert(!std::derived_from<volatile From&, const volatile To*>); 112 113 static_assert(!std::derived_from<volatile From&&, To*>); 114 static_assert(!std::derived_from<volatile From&&, const To*>); 115 static_assert(!std::derived_from<volatile From&&, volatile To*>); 116 static_assert(!std::derived_from<volatile From&&, const volatile To*>); 117 118 static_assert(!std::derived_from<const volatile From&, To*>); 119 static_assert(!std::derived_from<const volatile From&, const To*>); 120 static_assert(!std::derived_from<const volatile From&, volatile To*>); 121 static_assert( 122 !std::derived_from<const volatile From&, const volatile To*>); 123 124 static_assert(!std::derived_from<const volatile From&&, To*>); 125 static_assert(!std::derived_from<const volatile From&&, const To*>); 126 static_assert(!std::derived_from<const volatile From&&, volatile To*>); 127 static_assert( 128 !std::derived_from<const volatile From&&, const volatile To*>); 129 } 130 } 131 { // Both as pointers 132 static_assert(!std::derived_from<From*, To*>); 133 static_assert(!std::derived_from<From*, const To*>); 134 static_assert(!std::derived_from<From*, volatile To*>); 135 static_assert(!std::derived_from<From*, const volatile To*>); 136 137 static_assert(!std::derived_from<const From*, To*>); 138 static_assert(!std::derived_from<const From*, const To*>); 139 static_assert(!std::derived_from<const From*, volatile To*>); 140 static_assert(!std::derived_from<const From*, const volatile To*>); 141 142 static_assert(!std::derived_from<volatile From*, To*>); 143 static_assert(!std::derived_from<volatile From*, const To*>); 144 static_assert(!std::derived_from<volatile From*, volatile To*>); 145 static_assert(!std::derived_from<volatile From*, const volatile To*>); 146 147 static_assert(!std::derived_from<const volatile From*, To*>); 148 static_assert(!std::derived_from<const volatile From*, const To*>); 149 static_assert(!std::derived_from<const volatile From*, volatile To*>); 150 static_assert(!std::derived_from<const volatile From*, const volatile To*>); 151 } 152 153 // From as the return type of a pointer-to-function 154 if constexpr (!std::is_array_v<From>) { 155 static_assert(!std::derived_from<From (*)(), To>); 156 static_assert(!std::derived_from<From (*)(int), To>); 157 } 158 159 // To as the return type of a pointer-to-function 160 if constexpr (!std::is_array_v<To>) { 161 static_assert(!std::derived_from<From, To (*)()>); 162 static_assert(!std::derived_from<From, To (*)(double)>); 163 } 164 165 // Both as the return type of a pointer-to-function 166 if constexpr (!std::is_array_v<From> && !std::is_array_v<To>) { 167 static_assert(!std::derived_from<From (*)(), To (*)()>); 168 static_assert(!std::derived_from<From (*)(int), To (*)(double)>); 169 } 170 { // pointer-to-member 171 if constexpr (std::is_class_v<From> && !std::same_as<To, void>) { 172 static_assert(!std::derived_from<To From::*, To>); 173 } 174 175 if constexpr (std::is_class_v<To> && !std::same_as<From, void>) { 176 static_assert(!std::derived_from<From To::*, From>); 177 } 178 } 179 { // pointer-to-member-functions 180 if constexpr (std::is_class_v<From>) { 181 static_assert(!std::derived_from<From (From::*)(), To>); 182 } 183 184 if constexpr (std::is_class_v<To>) { 185 static_assert(!std::derived_from<To (To::*)(), From>); 186 } 187 } 188 } 189 190 template <typename From, typename To> 191 constexpr void CheckNotDerivedFromReference() { 192 if constexpr (!std::same_as<To, void>) { 193 static_assert(!std::derived_from<From, To&>); 194 static_assert(!std::derived_from<From, const To&>); 195 static_assert(!std::derived_from<From, volatile To&>); 196 static_assert(!std::derived_from<From, const volatile To&>); 197 198 static_assert(!std::derived_from<From, To&&>); 199 static_assert(!std::derived_from<From, const To&&>); 200 static_assert(!std::derived_from<From, volatile To&&>); 201 static_assert(!std::derived_from<From, const volatile To&&>); 202 } 203 204 if constexpr (!std::same_as<From, void>) { 205 static_assert(!std::derived_from<From&, To>); 206 static_assert(!std::derived_from<From&, To>); 207 static_assert(!std::derived_from<From&, To>); 208 static_assert(!std::derived_from<From&, To>); 209 210 static_assert(!std::derived_from<From&&, To>); 211 static_assert(!std::derived_from<From&&, To>); 212 static_assert(!std::derived_from<From&&, To>); 213 static_assert(!std::derived_from<From&&, To>); 214 } 215 216 // From as lvalue references 217 if constexpr (!std::same_as<From, void> && !std::same_as<To, void>) { 218 static_assert(!std::derived_from<From&, To&>); 219 static_assert(!std::derived_from<From&, const To&>); 220 static_assert(!std::derived_from<From&, volatile To&>); 221 static_assert(!std::derived_from<From&, const volatile To&>); 222 223 static_assert(!std::derived_from<From&, To&&>); 224 static_assert(!std::derived_from<From&, const To&&>); 225 static_assert(!std::derived_from<From&, volatile To&&>); 226 static_assert(!std::derived_from<From&, const volatile To&&>); 227 228 static_assert(!std::derived_from<const From&, To&>); 229 static_assert(!std::derived_from<const From&, const To&>); 230 static_assert(!std::derived_from<const From&, volatile To&>); 231 static_assert(!std::derived_from<const From&, const volatile To&>); 232 233 static_assert(!std::derived_from<const From&, To&&>); 234 static_assert(!std::derived_from<const From&, const To&&>); 235 static_assert(!std::derived_from<const From&, volatile To&&>); 236 static_assert(!std::derived_from<const From&, const volatile To&&>); 237 238 static_assert(!std::derived_from<volatile From&, To&>); 239 static_assert(!std::derived_from<volatile From&, const To&>); 240 static_assert(!std::derived_from<volatile From&, volatile To&>); 241 static_assert(!std::derived_from<volatile From&, const volatile To&>); 242 243 static_assert(!std::derived_from<volatile From&, To&&>); 244 static_assert(!std::derived_from<volatile From&, const To&&>); 245 static_assert(!std::derived_from<volatile From&, volatile To&&>); 246 static_assert(!std::derived_from<volatile From&, const volatile To&&>); 247 248 static_assert(!std::derived_from<const volatile From&, To&>); 249 static_assert(!std::derived_from<const volatile From&, const To&>); 250 static_assert(!std::derived_from<const volatile From&, volatile To&>); 251 static_assert(!std::derived_from<const volatile From&, const volatile To&>); 252 253 static_assert(!std::derived_from<const volatile From&, To&&>); 254 static_assert(!std::derived_from<const volatile From&, const To&&>); 255 static_assert(!std::derived_from<const volatile From&, volatile To&&>); 256 static_assert( 257 !std::derived_from<const volatile From&, const volatile To&&>); 258 259 // From as rvalue references 260 static_assert(!std::derived_from<From&&, To&>); 261 static_assert(!std::derived_from<From&&, const To&>); 262 static_assert(!std::derived_from<From&&, volatile To&>); 263 static_assert(!std::derived_from<From&&, const volatile To&>); 264 265 static_assert(!std::derived_from<From&&, To&&>); 266 static_assert(!std::derived_from<From&&, const To&&>); 267 static_assert(!std::derived_from<From&&, volatile To&&>); 268 static_assert(!std::derived_from<From&&, const volatile To&&>); 269 270 static_assert(!std::derived_from<const From&&, To&>); 271 static_assert(!std::derived_from<const From&&, const To&>); 272 static_assert(!std::derived_from<const From&&, volatile To&>); 273 static_assert(!std::derived_from<const From&&, const volatile To&>); 274 275 static_assert(!std::derived_from<const From&&, To&&>); 276 static_assert(!std::derived_from<const From&&, const To&&>); 277 static_assert(!std::derived_from<const From&&, volatile To&&>); 278 static_assert(!std::derived_from<const From&&, const volatile To&&>); 279 280 static_assert(!std::derived_from<volatile From&&, To&>); 281 static_assert(!std::derived_from<volatile From&&, const To&>); 282 static_assert(!std::derived_from<volatile From&&, volatile To&>); 283 static_assert(!std::derived_from<volatile From&&, const volatile To&>); 284 285 static_assert(!std::derived_from<volatile From&&, To&&>); 286 static_assert(!std::derived_from<volatile From&&, const To&&>); 287 static_assert(!std::derived_from<volatile From&&, volatile To&&>); 288 static_assert(!std::derived_from<volatile From&&, const volatile To&&>); 289 290 static_assert(!std::derived_from<const volatile From&&, To&>); 291 static_assert(!std::derived_from<const volatile From&&, const To&>); 292 static_assert(!std::derived_from<const volatile From&&, volatile To&>); 293 static_assert( 294 !std::derived_from<const volatile From&&, const volatile To&>); 295 296 static_assert(!std::derived_from<const volatile From&&, To&&>); 297 static_assert(!std::derived_from<const volatile From&&, const To&&>); 298 static_assert(!std::derived_from<const volatile From&&, volatile To&&>); 299 static_assert( 300 !std::derived_from<const volatile From&&, const volatile To&&>); 301 } 302 303 // From as the return type of a reference-to-function 304 if constexpr (!std::is_array_v<From>) { 305 static_assert(!std::derived_from<From (&)(), To>); 306 static_assert(!std::derived_from<From (&)(int), To>); 307 } 308 // To as the return type of a reference-to-function 309 if constexpr (!std::is_array_v<To>) { 310 static_assert(!std::derived_from<From, To (&)()>); 311 static_assert(!std::derived_from<From, To (&)(double)>); 312 } 313 // Both as the return type of a reference-to-function 314 if constexpr (!std::is_array_v<From> && !std::is_array_v<To>) { 315 static_assert(!std::derived_from<From (&)(), To (&)()>); 316 static_assert(!std::derived_from<From (&)(int), To (&)(double)>); 317 } 318 } 319 320 template <typename From, typename To> 321 constexpr void CheckDerivedFrom() { 322 static_assert(std::derived_from<From, To>); 323 324 static_assert(std::derived_from<From, const To>); 325 static_assert(std::derived_from<From, volatile To>); 326 static_assert(std::derived_from<From, const volatile To>); 327 328 static_assert(std::derived_from<const From, const To>); 329 static_assert(std::derived_from<const From, volatile To>); 330 static_assert(std::derived_from<const From, const volatile To>); 331 332 static_assert(std::derived_from<volatile From, const To>); 333 static_assert(std::derived_from<volatile From, volatile To>); 334 static_assert(std::derived_from<volatile From, const volatile To>); 335 336 static_assert(std::derived_from<const volatile From, const To>); 337 static_assert(std::derived_from<const volatile From, volatile To>); 338 static_assert(std::derived_from<const volatile From, const volatile To>); 339 340 CheckNotDerivedFromPointer<From, To>(); 341 CheckNotDerivedFromReference<From, To>(); 342 } 343 344 template <typename From, typename To> 345 constexpr void CheckNotDerivedFrom() { 346 static_assert(!std::derived_from<From, To>); 347 348 static_assert(!std::derived_from<From, const To>); 349 static_assert(!std::derived_from<From, volatile To>); 350 static_assert(!std::derived_from<From, const volatile To>); 351 352 static_assert(!std::derived_from<const From, const To>); 353 static_assert(!std::derived_from<const From, volatile To>); 354 static_assert(!std::derived_from<const From, const volatile To>); 355 356 static_assert(!std::derived_from<volatile From, const To>); 357 static_assert(!std::derived_from<volatile From, volatile To>); 358 static_assert(!std::derived_from<volatile From, const volatile To>); 359 360 static_assert(!std::derived_from<const volatile From, const To>); 361 static_assert(!std::derived_from<const volatile From, volatile To>); 362 static_assert(!std::derived_from<const volatile From, const volatile To>); 363 364 CheckNotDerivedFromPointer<From, To>(); 365 CheckNotDerivedFromReference<From, To>(); 366 } 367 368 enum Enumeration { Yes, No }; 369 enum class ScopedEnumeration : int { No, Yes }; 370 371 int main(int, char**) { 372 { // Fundamentals shouldn't be derived from anything 373 CheckNotDerivedFrom<int, long>(); 374 CheckNotDerivedFrom<signed char, char>(); 375 CheckNotDerivedFrom<double, Base1>(); 376 377 CheckNotDerivedFrom<int, Enumeration>(); 378 CheckNotDerivedFrom<int, ScopedEnumeration>(); 379 380 CheckNotDerivedFrom<void, void>(); 381 CheckNotDerivedFrom<int, int>(); 382 } 383 { // Nothing should be derived from a fundamental type 384 CheckNotDerivedFrom<Enumeration, int>(); 385 CheckNotDerivedFrom<ScopedEnumeration, int>(); 386 387 CheckNotDerivedFrom<Base1, int>(); 388 CheckNotDerivedFrom<Base1, double>(); 389 CheckNotDerivedFrom<Derived1, char>(); 390 CheckNotDerivedFrom<DerivedPrivate, long long>(); 391 } 392 { // Other built-in things shouldn't have derivations 393 CheckNotDerivedFrom<Enumeration, Enumeration>(); 394 CheckNotDerivedFrom<ScopedEnumeration, ScopedEnumeration>(); 395 396 CheckNotDerivedFrom<Enumeration, ScopedEnumeration>(); 397 CheckNotDerivedFrom<ScopedEnumeration, Enumeration>(); 398 399 CheckNotDerivedFrom<Base1[5], Base1>(); 400 CheckNotDerivedFrom<Derived1[5], Base1>(); 401 402 CheckNotDerivedFrom<Base1, Base1[5]>(); 403 CheckNotDerivedFrom<Derived1, Base1[5]>(); 404 } 405 406 { // Base1 is the subject. 407 CheckDerivedFrom<Base1, Base1>(); 408 409 CheckNotDerivedFrom<Base1, void>(); 410 CheckNotDerivedFrom<Base1, DerivedPrivate>(); 411 CheckNotDerivedFrom<Base1, DerivedProtected>(); 412 CheckNotDerivedFrom<Base1, Derived1>(); 413 CheckNotDerivedFrom<Base1, Derived2>(); 414 CheckNotDerivedFrom<Base1, Derived3>(); 415 CheckNotDerivedFrom<Base1, Derived4>(); 416 } 417 418 { // Derived1 is the subject. 419 CheckDerivedFrom<Derived1, Base1>(); 420 CheckDerivedFrom<Derived1, Derived1>(); 421 422 CheckNotDerivedFromPointer<Derived1, void>(); 423 CheckNotDerivedFrom<Derived1, DerivedPrivate>(); 424 CheckNotDerivedFrom<Derived1, DerivedProtected>(); 425 CheckNotDerivedFrom<Derived1, Derived2>(); 426 CheckNotDerivedFrom<Derived1, Derived3>(); 427 CheckNotDerivedFrom<Derived1, Derived4>(); 428 } 429 430 { // Derived2 is the subject. 431 CheckDerivedFrom<Derived2, Base1>(); 432 CheckDerivedFrom<Derived2, Derived2>(); 433 434 CheckNotDerivedFrom<Derived2, DerivedPrivate>(); 435 CheckNotDerivedFrom<Derived2, DerivedProtected>(); 436 CheckNotDerivedFrom<Derived2, Derived1>(); 437 CheckNotDerivedFrom<Derived2, Derived3>(); 438 CheckNotDerivedFrom<Derived2, Derived4>(); 439 } 440 441 { // DerivedPrivate is the subject. 442 CheckDerivedFrom<DerivedPrivate, DerivedPrivate>(); 443 444 CheckNotDerivedFrom<DerivedPrivate, Base1>(); 445 CheckNotDerivedFrom<DerivedPrivate, DerivedProtected>(); 446 CheckNotDerivedFrom<DerivedPrivate, Derived1>(); 447 CheckNotDerivedFrom<DerivedPrivate, Derived2>(); 448 CheckNotDerivedFrom<DerivedPrivate, Derived3>(); 449 CheckNotDerivedFrom<DerivedPrivate, Derived4>(); 450 } 451 452 { // Derived3 is the subject. 453 CheckDerivedFrom<Derived3, DerivedPrivate>(); 454 CheckDerivedFrom<Derived3, Derived3>(); 455 456 CheckNotDerivedFrom<Derived3, Base1>(); 457 CheckNotDerivedFrom<Derived3, DerivedProtected>(); 458 CheckNotDerivedFrom<Derived3, Derived1>(); 459 CheckNotDerivedFrom<Derived3, Derived2>(); 460 CheckNotDerivedFrom<Derived3, Derived4>(); 461 } 462 463 { // DerivedProtected is the subject. 464 CheckDerivedFrom<DerivedProtected, DerivedProtected>(); 465 466 CheckNotDerivedFromPointer<DerivedProtected, Base1>(); 467 CheckNotDerivedFromPointer<DerivedProtected, DerivedPrivate>(); 468 CheckNotDerivedFromPointer<DerivedProtected, Derived1>(); 469 CheckNotDerivedFromPointer<DerivedProtected, Derived2>(); 470 CheckNotDerivedFromPointer<DerivedProtected, Derived3>(); 471 CheckNotDerivedFromPointer<DerivedProtected, Derived4>(); 472 } 473 474 { // Derived4 is the subject. 475 CheckDerivedFrom<Derived4, DerivedProtected>(); 476 CheckDerivedFrom<Derived4, Derived4>(); 477 478 CheckNotDerivedFrom<Derived4, Base1>(); 479 CheckNotDerivedFrom<Derived4, DerivedPrivate>(); 480 CheckNotDerivedFrom<Derived4, Derived1>(); 481 CheckNotDerivedFrom<Derived4, Derived2>(); 482 CheckNotDerivedFrom<Derived4, Derived3>(); 483 } 484 485 { // Derived5 is the subject. 486 CheckDerivedFrom<Derived5, DerivedProtected>(); 487 CheckDerivedFrom<Derived5, Derived4>(); 488 CheckDerivedFrom<Derived5, Derived5>(); 489 490 CheckNotDerivedFrom<Derived5, Base1>(); 491 CheckNotDerivedFrom<Derived5, DerivedPrivate>(); 492 CheckNotDerivedFrom<Derived5, Derived1>(); 493 CheckNotDerivedFrom<Derived5, Derived2>(); 494 CheckNotDerivedFrom<Derived5, Derived3>(); 495 } 496 497 return 0; 498 } 499