The existing implementation of is_destructible assumes that if a class is 
abstract, then it is not destructible. Apparently, the fact that you can't 
construct one of these objects doesn't mean that you can't destruct them.

http://reviews.llvm.org/D4306

Files:
  include/type_traits
  test/utilities/meta/meta.unary/meta.unary.prop/is_constructible.pass.cpp
  test/utilities/meta/meta.unary/meta.unary.prop/is_destructible.pass.cpp
Index: include/type_traits
===================================================================
--- include/type_traits
+++ include/type_traits
@@ -1541,43 +1541,57 @@
 
 // is_destructible
 
+//	if it's a reference, return true
+//	if it's a function, return false
+//	if it's   void,     return false
+//	if it's an array of unknown bound, return false
+//	Otherwise, return "std::declval<_Up&>().~_Up()" is well-formed
+//    where _Up is remove_all_extents<_Tp>::type
+
+template <typename _Tp>
+struct __is_destructor_wellformed {
+	template <typename _Tp1, typename _Tp2 = decltype(_VSTD::declval<_Tp1&>().~_Tp1())>
+	static char  __test (int);
+
+	template <typename _Tp1>
+	static __two __test (...);
+	
+	static const bool value = sizeof(__test<_Tp>(12)) == sizeof(char);
+	};
+
+template <class _Tp, bool>
+struct __destructible_imp;
+
 template <class _Tp>
-struct __destructible_test
-{
-    _Tp __t;
-};
+struct __destructible_imp<_Tp, false> 
+   : public _VSTD::integral_constant<bool, 
+        __is_destructor_wellformed<typename _VSTD::remove_all_extents<_Tp>::type>::value> {};
 
 template <class _Tp>
-decltype((_VSTD::declval<__destructible_test<_Tp> >().~__destructible_test<_Tp>(), true_type()))
-#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
-__is_destructible_test(_Tp&&);
-#else
-__is_destructible_test(_Tp&);
-#endif
+struct __destructible_imp<_Tp, true>
+    : public _VSTD::true_type {};
 
-false_type
-__is_destructible_test(__any);
+template <class _Tp, bool>
+struct __destructible_false;
 
-template <class _Tp, bool = is_void<_Tp>::value || is_abstract<_Tp>::value
-                                                || is_function<_Tp>::value>
-struct __destructible_imp
-    : public common_type
-        <
-            decltype(__is_destructible_test(declval<_Tp>()))
-        >::type {};
+template <class _Tp>
+struct __destructible_false<_Tp, false> : public __destructible_imp<_Tp, _VSTD::is_reference<_Tp>::value> {};
 
 template <class _Tp>
-struct __destructible_imp<_Tp, true>
-    : public false_type {};
+struct __destructible_false<_Tp, true> : public _VSTD::false_type {};
 
 template <class _Tp>
 struct is_destructible
-    : public __destructible_imp<_Tp> {};
+    : public __destructible_false<_Tp, _VSTD::is_function<_Tp>::value> {};
 
 template <class _Tp>
 struct is_destructible<_Tp[]>
-    : public false_type {};
+    : public _VSTD::false_type {};
 
+template <>
+struct is_destructible<void>
+    : public _VSTD::false_type {};
+
 // move
 
 #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Index: test/utilities/meta/meta.unary/meta.unary.prop/is_constructible.pass.cpp
===================================================================
--- test/utilities/meta/meta.unary/meta.unary.prop/is_constructible.pass.cpp
+++ test/utilities/meta/meta.unary/meta.unary.prop/is_constructible.pass.cpp
@@ -24,6 +24,16 @@
     A(char);
 };
 
+class Abstract
+{
+    virtual void foo() = 0;
+};
+
+class AbstractDestructor
+{
+    virtual ~AbstractDestructor() = 0;
+};
+
 template <class T>
 void test_is_constructible()
 {
@@ -71,4 +81,6 @@
     test_is_not_constructible<A, void> ();
     test_is_not_constructible<void> ();
     test_is_not_constructible<int&> ();
+    test_is_not_constructible<Abstract> ();
+    test_is_not_constructible<AbstractDestructor> ();
 }
Index: test/utilities/meta/meta.unary/meta.unary.prop/is_destructible.pass.cpp
===================================================================
--- test/utilities/meta/meta.unary/meta.unary.prop/is_destructible.pass.cpp
+++ test/utilities/meta/meta.unary/meta.unary.prop/is_destructible.pass.cpp
@@ -49,9 +49,14 @@
 
 class Abstract
 {
-    virtual ~Abstract() = 0;
+    virtual void foo() = 0;
 };
 
+class AbstractDestructor
+{
+    virtual ~AbstractDestructor() = 0;
+};
+
 struct A
 {
     ~A();
@@ -72,10 +77,11 @@
     test_is_destructible<char[3]>();
     test_is_destructible<bit_zero>();
     test_is_destructible<int[3]>();
+    test_is_destructible<Abstract>();
 
     test_is_not_destructible<int[]>();
     test_is_not_destructible<void>();
-    test_is_not_destructible<Abstract>();
+    test_is_not_destructible<AbstractDestructor>();
 #if __has_feature(cxx_access_control_sfinae) 
     test_is_not_destructible<NotEmpty>();
 #endif
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to