//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // UNSUPPORTED: c++03, c++11, c++14, c++17 // template // concept derived_from; #include #include struct Base1 {}; struct Derived1 : Base1 {}; struct Derived2 : Base1 {}; struct DerivedPrivate : private Base1 {}; struct Derived3 : DerivedPrivate {}; struct DerivedProtected : protected DerivedPrivate {}; struct Derived4 : DerivedProtected {}; struct Derived5 : Derived4 {}; template constexpr void CheckNotDerivedFromPointer() { { // From as pointer static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); if constexpr (!std::same_as) { static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert( !std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert( !std::derived_from); } } { // To as pointer static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); if constexpr (!std::same_as) { static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert( !std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert( !std::derived_from); } } { // Both as pointers static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); } // From as the return type of a pointer-to-function if constexpr (!std::is_array_v) { static_assert(!std::derived_from); static_assert(!std::derived_from); } // To as the return type of a pointer-to-function if constexpr (!std::is_array_v) { static_assert(!std::derived_from); static_assert(!std::derived_from); } // Both as the return type of a pointer-to-function if constexpr (!std::is_array_v && !std::is_array_v) { static_assert(!std::derived_from); static_assert(!std::derived_from); } { // pointer-to-member if constexpr (std::is_class_v && !std::same_as) { static_assert(!std::derived_from); } if constexpr (std::is_class_v && !std::same_as) { static_assert(!std::derived_from); } } { // pointer-to-member-functions if constexpr (std::is_class_v) { static_assert(!std::derived_from); } if constexpr (std::is_class_v) { static_assert(!std::derived_from); } } } template constexpr void CheckNotDerivedFromReference() { if constexpr (!std::same_as) { static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); } if constexpr (!std::same_as) { static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); } // From as lvalue references if constexpr (!std::same_as && !std::same_as) { static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert( !std::derived_from); // From as rvalue references static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert( !std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert( !std::derived_from); } // From as the return type of a reference-to-function if constexpr (!std::is_array_v) { static_assert(!std::derived_from); static_assert(!std::derived_from); } // To as the return type of a reference-to-function if constexpr (!std::is_array_v) { static_assert(!std::derived_from); static_assert(!std::derived_from); } // Both as the return type of a reference-to-function if constexpr (!std::is_array_v && !std::is_array_v) { static_assert(!std::derived_from); static_assert(!std::derived_from); } } template constexpr void CheckDerivedFrom() { static_assert(std::derived_from); static_assert(std::derived_from); static_assert(std::derived_from); static_assert(std::derived_from); static_assert(std::derived_from); static_assert(std::derived_from); static_assert(std::derived_from); static_assert(std::derived_from); static_assert(std::derived_from); static_assert(std::derived_from); static_assert(std::derived_from); static_assert(std::derived_from); static_assert(std::derived_from); CheckNotDerivedFromPointer(); CheckNotDerivedFromReference(); } template constexpr void CheckNotDerivedFrom() { static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); static_assert(!std::derived_from); CheckNotDerivedFromPointer(); CheckNotDerivedFromReference(); } enum Enumeration { Yes, No }; enum class ScopedEnumeration : int { No, Yes }; int main(int, char**) { { // Fundamentals shouldn't be derived from anything CheckNotDerivedFrom(); CheckNotDerivedFrom(); CheckNotDerivedFrom(); CheckNotDerivedFrom(); CheckNotDerivedFrom(); CheckNotDerivedFrom(); CheckNotDerivedFrom(); } { // Nothing should be derived from a fundamental type CheckNotDerivedFrom(); CheckNotDerivedFrom(); CheckNotDerivedFrom(); CheckNotDerivedFrom(); CheckNotDerivedFrom(); CheckNotDerivedFrom(); } { // Other built-in things shouldn't have derivations CheckNotDerivedFrom(); CheckNotDerivedFrom(); CheckNotDerivedFrom(); CheckNotDerivedFrom(); CheckNotDerivedFrom(); CheckNotDerivedFrom(); CheckNotDerivedFrom(); CheckNotDerivedFrom(); } { // Base1 is the subject. CheckDerivedFrom(); CheckNotDerivedFrom(); CheckNotDerivedFrom(); CheckNotDerivedFrom(); CheckNotDerivedFrom(); CheckNotDerivedFrom(); CheckNotDerivedFrom(); CheckNotDerivedFrom(); } { // Derived1 is the subject. CheckDerivedFrom(); CheckDerivedFrom(); CheckNotDerivedFromPointer(); CheckNotDerivedFrom(); CheckNotDerivedFrom(); CheckNotDerivedFrom(); CheckNotDerivedFrom(); CheckNotDerivedFrom(); } { // Derived2 is the subject. CheckDerivedFrom(); CheckDerivedFrom(); CheckNotDerivedFrom(); CheckNotDerivedFrom(); CheckNotDerivedFrom(); CheckNotDerivedFrom(); CheckNotDerivedFrom(); } { // DerivedPrivate is the subject. CheckDerivedFrom(); CheckNotDerivedFrom(); CheckNotDerivedFrom(); CheckNotDerivedFrom(); CheckNotDerivedFrom(); CheckNotDerivedFrom(); CheckNotDerivedFrom(); } { // Derived3 is the subject. CheckDerivedFrom(); CheckDerivedFrom(); CheckNotDerivedFrom(); CheckNotDerivedFrom(); CheckNotDerivedFrom(); CheckNotDerivedFrom(); CheckNotDerivedFrom(); } { // DerivedProtected is the subject. CheckDerivedFrom(); CheckNotDerivedFromPointer(); CheckNotDerivedFromPointer(); CheckNotDerivedFromPointer(); CheckNotDerivedFromPointer(); CheckNotDerivedFromPointer(); CheckNotDerivedFromPointer(); } { // Derived4 is the subject. CheckDerivedFrom(); CheckDerivedFrom(); CheckNotDerivedFrom(); CheckNotDerivedFrom(); CheckNotDerivedFrom(); CheckNotDerivedFrom(); CheckNotDerivedFrom(); } { // Derived5 is the subject. CheckDerivedFrom(); CheckDerivedFrom(); CheckDerivedFrom(); CheckNotDerivedFrom(); CheckNotDerivedFrom(); CheckNotDerivedFrom(); CheckNotDerivedFrom(); CheckNotDerivedFrom(); } return 0; }