Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is `is_­destructible` defined using `declval<U&>().~U()` and not `declval<U>().~U()`?

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, or T is a complete object type for which the expression declval<U&>().~U() is well-formed when treated as an unevaluated operand, where U is remove_­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?

like image 280
Language Lawyer Avatar asked Feb 14 '19 21:02

Language Lawyer


1 Answers

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 translating p->~T(), which again according to the language corresponds to (*p).~T() ([expr.ref]), so the logical consequence was to change the std::declval() call to generate an lvalue of T where the destructor was applied to.

I'm pretty sure that I didn't believe that declval() was returning the T directly, this helper function was too deeply burned into my mind ;-)

like image 66
Language Lawyer Avatar answered Sep 22 '22 14:09

Language Lawyer