11a50ac497
implementation of std::is_polymorphic does this: template <class _Tp> struct __is_polymorphic1 : public _Tp {}; ... and that g++ rejects this if _Tp has an inaccessible virtual destructor (because __is_polymorphic1<_Tp> would have a deleted virtual destructor overriding _Tp's non-deleted destructor). Clang was failing to reject this; I've fixed that in r178563, but that causes libc++'s corresponding test case to fail with both clang and gcc when using the fallback implementation. The fallback code also incorrectly rejects final types. The attached patch fixes the fallback implementation of is_polymorphic; we now use dynamic_cast's detection of polymorphic class types rather than trying to determine if adding a virtual function makes the type larger: enable_if<sizeof((_Tp*)dynamic_cast<const volatile void*>(declval<_Tp*>())) != 0, ...> Two things of note here: * the (_Tp*) cast is necessary to work around bugs in Clang and g++ where we otherwise don't instantiate the dynamic_cast (filed as PR15656) * the 'const volatile' is here to treat is_polymorphic<cv T> as true for a polymorphic class type T -- my reading of the standard suggests this is incorrect, but it matches our builtin __is_polymorphic and gcc git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@178576 91177308-0d34-0410-b5e6-96231b3b80d8
78 lines
1.8 KiB
C++
78 lines
1.8 KiB
C++
//===----------------------------------------------------------------------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is dual licensed under the MIT and the University of Illinois Open
|
|
// Source Licenses. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// type_traits
|
|
|
|
// is_polymorphic
|
|
|
|
#include <type_traits>
|
|
|
|
template <class T>
|
|
void test_is_polymorphic()
|
|
{
|
|
static_assert( std::is_polymorphic<T>::value, "");
|
|
static_assert( std::is_polymorphic<const T>::value, "");
|
|
static_assert( std::is_polymorphic<volatile T>::value, "");
|
|
static_assert( std::is_polymorphic<const volatile T>::value, "");
|
|
}
|
|
|
|
template <class T>
|
|
void test_is_not_polymorphic()
|
|
{
|
|
static_assert(!std::is_polymorphic<T>::value, "");
|
|
static_assert(!std::is_polymorphic<const T>::value, "");
|
|
static_assert(!std::is_polymorphic<volatile T>::value, "");
|
|
static_assert(!std::is_polymorphic<const volatile T>::value, "");
|
|
}
|
|
|
|
class Empty
|
|
{
|
|
};
|
|
|
|
class NotEmpty
|
|
{
|
|
virtual ~NotEmpty();
|
|
};
|
|
|
|
union Union {};
|
|
|
|
struct bit_zero
|
|
{
|
|
int : 0;
|
|
};
|
|
|
|
class Abstract
|
|
{
|
|
virtual ~Abstract() = 0;
|
|
};
|
|
|
|
class Final final {
|
|
};
|
|
|
|
int main()
|
|
{
|
|
test_is_not_polymorphic<void>();
|
|
test_is_not_polymorphic<int&>();
|
|
test_is_not_polymorphic<int>();
|
|
test_is_not_polymorphic<double>();
|
|
test_is_not_polymorphic<int*>();
|
|
test_is_not_polymorphic<const int*>();
|
|
test_is_not_polymorphic<char[3]>();
|
|
test_is_not_polymorphic<char[3]>();
|
|
test_is_not_polymorphic<Union>();
|
|
test_is_not_polymorphic<Empty>();
|
|
test_is_not_polymorphic<bit_zero>();
|
|
test_is_not_polymorphic<Final>();
|
|
test_is_not_polymorphic<NotEmpty&>();
|
|
test_is_not_polymorphic<Abstract&>();
|
|
|
|
test_is_polymorphic<NotEmpty>();
|
|
test_is_polymorphic<Abstract>();
|
|
}
|