例如,如果我有
#include <type_traits>
struct OwnershipReceiver
{
template <typename T,
class = typename std::enable_if
<
!std::is_lvalue_reference<T>::value
>::type
>
void receive_ownership(T&& t)
{
// taking file descriptor of t, and clear t
}
};
从How to make template rvalue reference parameter ONLY bind to rvalue reference?复制
发布者使用!std::is_lvalue_reference
而不是立即出现的std::is_rvalue_reference
。我已经在自己的代码中对此进行了验证,前者可以工作,而后者则不能。
有人可以解释为什么显而易见的东西不起作用吗?
答案 0 :(得分:4)
由于forwarding reference,T
永远不会被推导为右值引用。假设将类型为int
的对象传递给OwnershipReceiver
,如果该对象是左值,则将推导T
作为左值引用,即int&
;如果对象是右值,则将T
推导为非引用,即int
。这就是std::is_rvalue_reference<T>::value
不能正常运行的原因,因为它总是false
。
请注意,代码的目的是确保OwnershipReceiver
的参数类型为右值引用,但这并不意味着T
的类型也为右值引用。
换句话说,此处的要点是区分左值引用和非引用,因此!std::is_reference<T>::value
也适用。
顺便说一句:如果您坚持使用std::is_rvalue_reference
,则可以使用comment中的std::is_rvalue_reference<T&&>::value
,也可以在参数t
上使用它,例如
template <typename T>
auto receive_ownership(T&& t) -> typename std::enable_if<std::is_rvalue_reference<decltype(t)>::value>::type
{
// taking file descriptor of t, and clear t
}