By the definition of is_destructible
(http://eel.is/c++draft/meta.unary.prop#lib:is_destructible), is_destructible_v<T>
is true
when:
Either
T
is a reference type, orT
is a complete object type for which the expressiondeclval<U&>().~U()
is well-formed when treated as an unevaluated operand, whereU
isremove_all_extents_t<T>
.
Why does it use declval<U&>().~U()
and not declval<U>().~U()
?
The wording with declval
was added in https://cplusplus.github.io/LWG/issue2049 to solve the problem the definition had with abstract types. Maybe the author was thinking that declval<U>
has return type U
so it won't work for abstract types?
So I asked Daniel Krügler via email and he allowed me to publish his answer:
Good question - albeit the answer is rather trivial and doesn't reveal any language secret: I was aware that
std::declval<T>()
would return an rvalue reference (and thus an rvalue) in the discussed context, but in my mental imagination I wanted to express the picture of translatingp->~T()
, which again according to the language corresponds to(*p).~T()
([expr.ref]), so the logical consequence was to change thestd::declval()
call to generate an lvalue ofT
where the destructor was applied to.I'm pretty sure that I didn't believe that
declval()
was returning theT
directly, this helper function was too deeply burned into my mind ;-)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With