498 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9// UNSUPPORTED: c++03, c++11, c++14, c++1710 11// template<class Derived, class Base>12// concept derived_from;13 14#include <concepts>15#include <type_traits>16 17struct Base1 {};18struct Derived1 : Base1 {};19struct Derived2 : Base1 {};20 21struct DerivedPrivate : private Base1 {};22struct Derived3 : DerivedPrivate {};23 24struct DerivedProtected : protected DerivedPrivate {};25struct Derived4 : DerivedProtected {};26struct Derived5 : Derived4 {};27 28template <typename From, typename To>29constexpr void CheckNotDerivedFromPointer() {30 { // From as pointer31 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 pointer81 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 pointers131 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-function153 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-function159 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-function165 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-member170 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-functions179 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 189template <typename From, typename To>190constexpr 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 references216 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 references259 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-function303 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-function308 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-function313 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 319template <typename From, typename To>320constexpr 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 343template <typename From, typename To>344constexpr 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 367enum Enumeration { Yes, No };368enum class ScopedEnumeration : int { No, Yes };369 370int main(int, char**) {371 { // Fundamentals shouldn't be derived from anything372 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 type383 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 derivations392 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