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
Tis a reference type, orTis a complete object type for which the expressiondeclval<U&>().~U()is well-formed when treated as an unevaluated operand, whereUisremove_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 ofTwhere the destructor was applied to.I'm pretty sure that I didn't believe that
declval()was returning theTdirectly, 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