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