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.
Details
- Reviewers
- None
Diff Detail
Event Timeline
The existing implementation is the correct one for C++11, where is_destructible<T> is defined as:
For a complete type T and given template <class U> struct test { U u; };, test<T>::˜test() is not deleted.
Yes, but this was changed for the resolution of http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2049, which was a defect in C++11.
Apparently, when I worked on this issue, I missed the part about abstract classes being destructible.
I reviewed the changes and are inline with the new rules. I verified the bug and testcases. This looks good to me.
test/utilities/meta/meta.unary/meta.unary.prop/is_destructible.pass.cpp | ||
---|---|---|
55–58 | Since the destructor is private, this tests access control SFINAE and not the abstract destructor. After making the abstract destructor public, this test fails for both C++11 and C++03. |
Hi Marshall,
Would you be able to explain why AbstractDestructor should not be destructible?
My reading of the standard seems to suggest that because AbstractDestructor should be destructible because " decltype(_VSTD::declval<_Tp1&>().~_Tp1())" only has to be well formed in an un-evaluated context. It seems to me that invoking the destructor is well formed in this case.
Please let me know if I've made any mistakes.
Eric - I believe that invoking the destructor in this case is not well formed, because the destructor has been explicitly deleted.
See section 8.4.2/2:
A program that refers to a deleted function implicitly or explicitly, other than to declare it, is ill-formed. [ Note: This includes calling the function implicitly or explicitly and forming a pointer or pointer-to-member to the function. It applies even for references in expressions that are not potentially-evaluated. If a function
is overloaded, it is referenced only if the function is selected by overload resolution. — end note ]
Indeed, and if you test this change with a deleted destructor it is not destructible.
However I don't see why a pure virtual destructor is explicitly deleted. Can you clarify on that?
P.S. A deleted destructor test-case should probably be added.
I don't know what the correct answer is for a publicly accessible destructor that has been marked = 0;
Since the destructor is private, this tests access control SFINAE and not the abstract destructor. After making the abstract destructor public, this test fails for both C++11 and C++03.