简体   繁体   中英

Why does std::is_rvalue_reference not do what it is advertised to do?

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM