Search code examples
c++c++11move-semanticsunique-ptruniversal-reference

C++ Unable to move unique_ptr with universal references


Consider this code:

template<typename T>
T mov(T&& t){
   return std::move(t);
}

int main(){
   std::unique_ptr<int> a = std::unique_ptr<int>(new int());
   std::unique_ptr<int> b = mov(a);
}

The mov function should simply take a universal reference and return it by value but by moveing it instead of copying. Thus, no copying should be involved when calling this method. Consequently, it should be fine to call such a function with a unique_ptr which can only be moved. However, this code does not compile: I receive the error:

test.cpp:24:34: error: use of deleted function ‘std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = int; _Dp = std::default_delete<int>]’
    std::unique_ptr<int> b = mov(a);

So it seems that C++ tries to invoke unique_ptrs copy constructor which is of course deleted. But why does a copy happen here? How can I get this code to compile?


Solution

  • I believe the error is in the return type of mov

    The code should read

    #include <utility>
    #include <memory>
    template<typename T>
    typename std::remove_reference<T>::type&& mov(T&& t){
       return std::move(t);
    }
    
    int main(){
       std::unique_ptr<int> a = std::unique_ptr<int>(new int());
       auto b = mov(a);
    }
    

    The question hinted at a return by value scenario, this also compiles. I'm not sure if it will work in your situation;

    template<typename T>
    typename std::remove_reference<T>::type mov(T&& t){
       return std::move(t);
    }