为什么 std::is_rvalue_reference 没有按照广告宣传的那样去做?
Why does std::is_rvalue_reference not do what it is advertised to do?
例如,如果我有
#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
。我已经在我自己的代码中验证了这一点,前者有效而后者无效。
谁能解释为什么显而易见的方法不起作用?
因为对于 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
}
例如,如果我有
#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
。我已经在我自己的代码中验证了这一点,前者有效而后者无效。
谁能解释为什么显而易见的方法不起作用?
因为对于 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
}