为什么 is_destructible 是使用 declval<U&>().~U() 而不是 declval<U>().~U() 定义的?
Why is `is_destructible` defined using `declval<U&>().~U()` and not `declval<U>().~U()`?
根据 is_destructible
(http://eel.is/c++draft/meta.unary.prop#lib:is_destructible) 的定义,is_destructible_v<T>
是 true
时:
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>
.
为什么它使用 declval<U&>().~U()
而不是 declval<U>().~U()
?
在 https://cplusplus.github.io/LWG/issue2049 中添加了 declval
的措辞,以解决定义中抽象类型的问题。也许作者在想 declval<U>
有 return 类型 U
所以它不适用于抽象类型?
所以我通过电子邮件询问了 Daniel Krügler,他允许我发布他的答案:
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 ;-)
根据 is_destructible
(http://eel.is/c++draft/meta.unary.prop#lib:is_destructible) 的定义,is_destructible_v<T>
是 true
时:
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>
.
为什么它使用 declval<U&>().~U()
而不是 declval<U>().~U()
?
在 https://cplusplus.github.io/LWG/issue2049 中添加了 declval
的措辞,以解决定义中抽象类型的问题。也许作者在想 declval<U>
有 return 类型 U
所以它不适用于抽象类型?
所以我通过电子邮件询问了 Daniel Krügler,他允许我发布他的答案:
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 ;-)