diff --git a/libcxx/include/concepts b/libcxx/include/concepts --- a/libcxx/include/concepts +++ b/libcxx/include/concepts @@ -157,6 +157,12 @@ template concept same_as = __same_as_impl<_Tp, _Up> && __same_as_impl<_Up, _Tp>; +// [concept.derived] +template +concept derived_from = + is_base_of_v<_Bp, _Dp> && + is_convertible_v; + // [concept.convertible] template concept convertible_to = diff --git a/libcxx/test/std/concepts/lang/derived.compile.pass.cpp b/libcxx/test/std/concepts/lang/derived.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/concepts/lang/derived.compile.pass.cpp @@ -0,0 +1,498 @@ +//===----------------------------------------------------------------------===// +// +// 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++98, c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-no-concepts + +// 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; +}