For example if I have
#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
}
};
copied from How to make template rvalue reference parameter ONLY bind to rvalue reference?
the poster uses !std::is_lvalue_reference
instead of the immediately more obvious std::is_rvalue_reference
. I've verified this in my own code where the former works and the later doesn't.
Can anybody explain why the obvious doesn't work?
Because for forwarding reference , T
will never be deduced as an rvalue reference. Suppose passing an object of type int
to OwnershipReceiver
, if the object is an lvalue, T
will be deduced as an lvalue-reference, ie int&
; if the object is an rvalue, T
will be deduced as an non-reference, ie int
. That's why std::is_rvalue_reference<T>::value
won't work because it's always false
.
Note that the purpose of the code is to make sure the parameter type of OwnershipReceiver
is an rvalue-reference, it doesn't mean the type of T
is an rvalue-reference too.
In other words, the point here it to distinguish lvalue-reference and non-reference, so !std::is_reference<T>::value
works too.
BTW: If you stick to std::is_rvalue_reference
, you can use std::is_rvalue_reference<T&&>::value
as you found in the comment , or use it on the parameter t
, eg
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
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.