c++rvalue-reference

How can I make a forwarding-reference parameter bind only to rvalue references?


I'm writing a network library and use move semantics heavily to handle ownership for file descriptors. One of my classes wishes to receive file descriptor wrappers of other kinds and take ownership, so it's something like

struct OwnershipReceiver
{
  template <typename T>
  void receive_ownership(T&& t)
  {
     // taking file descriptor of t, and clear t
  }
};

It has to deal with multiple unrelated types so receive_ownership() has to be a template. To be safe, I wish it to bind only to rvalue references, so that user has to explicitly use std::move() when passing an lvalue.

receive_ownership(std::move(some_lvalue));

But the problem is that C++ template deduction allows an lvalue to be passed in without extra effort. And I actually shot myself in the foot once by accidentally passing an lvalue to receive_ownership() and using that lvalue (cleared) later.

So here is the question: how to make a template parameter that binds only to rvalue references?


Solution

  • You can restrict T to not be an lvalue reference, and thus prevent lvalues from binding to it:

    #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
      }
    };
    

    It might also be a good idea to add some sort of restriction to T such that it only accepts file descriptor wrappers.