Search code examples
c++c++11movesmart-pointers

Passing unique_ptr<Derived>& to a function accepting unique_ptr<Base>&


I need to pass a unique pointer to a derived class by reference to a function which accepts a reference to a unique pointer to the base class, like here:

#include <memory>

using namespace std;

class Base {};
class Derived : public Base {};

void foo(std::unique_ptr<Base>& d){}

int main()
{
    unique_ptr<Derived> b = make_unique<Derived>();
    foo(b);
}
  1. Why doesn't this code work? I checked out other posts like this one, and the answer seems to be "because C++ wants the types to match exactly", but why is that? What dangerous situation am I potentially creating?

  2. If I instead do this, it compiles:

    void foo(unique_ptr<Base>&& d){}
    foo(move(b));
    

    Is this a reasonable approach?


Solution

  • What dangerous situation am I potentially creating?

    Imagine the following implementation for foo:

    void foo(std::unique_ptr<Base>& d){
        d.reset(new Base);
    }
    

    You now have a std::unique_ptr<Derived> pointing to an object which is not of type Derived, and the compiler couldn't give you any kind of warning about it.

    The correct solution to your problem, as explained in the comments, is to take a std::unique_ptr<Base> by value, and move it at the call site.

    void foo(std::unique_ptr<Base> d) {
        // move d to your list
    }
    
    int main() {
        unique_ptr<Derived> b = make_unique<Derived>();
        foo(std::move(b));
    }