Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

unique_ptr to a derived class as an argument to a function that takes a unique_ptr to a base class

I'm trying to use a unique_ptr to derived class in a function that takes a unique_ptr to a base class. Something like:

class Base {};  class Derived : public Base {};  void f(unique_ptr<Base> const &base) {}  …  unique_ptr<Derived> derived = unique_ptr<Derived>(new Derived); f(derived); 

If I understand this answer correctly, this code should work, but it causes the following compile errors:

error C2664: 'f' : cannot convert parameter 1 from 'std::unique_ptr<_Ty>' to 'const std::unique_ptr<_Ty> &'

IntelliSense: no suitable user-defined conversion from "std::unique_ptr<Derived, std::default_delete<Derived>>" to "const std::unique_ptr<Base, std::default_delete<Base>>" exists

If I change f to take unique_ptr<Derived> const &derived, it works fine, but that's not what I want.

Am I doing something wrong? What can I do to work around this?

I'm using Visual Studio 2012.

like image 683
svick Avatar asked Jul 04 '13 15:07

svick


People also ask

Can unique_ptr be passed to function?

Because the unique pointer does not have a copy constructor. Hence you cannot pass it by value, because passing by value requires making a copy.

How do I pass a unique_ptr argument to a constructor or a function?

You cannot copy a unique_ptr . You can only move it. The proper way to do this is with the std::move standard library function. If you take a unique_ptr by value, you can move from it freely.

What happens when you move a unique_ptr?

A unique_ptr can only be moved. This means that the ownership of the memory resource is transferred to another unique_ptr and the original unique_ptr no longer owns it.

When should we use unique_ptr?

When to use unique_ptr? Use unique_ptr when you want to have single ownership(Exclusive) of the resource. Only one unique_ptr can point to one resource. Since there can be one unique_ptr for single resource its not possible to copy one unique_ptr to another.


1 Answers

You have three options:

  1. Give up ownership. This will leave your local variable without access to the dynamic object after the function call; the object has been transferred to the callee:

    f(std::move(derived)); 
  2. Change the signature of f:

    void f(std::unique_ptr<Derived> const &); 
  3. Change the type of your variable:

    std::unique_ptr<base> derived = std::unique_ptr<Derived>(new Derived); 

    Or of course just:

    std::unique_ptr<base> derived(new Derived); 

    Or even:

    std::unique_ptr<base> derived = std::make_unique<Derived>(); 
  4. Update: Or, as recommended in the comments, don't transfer ownership at all:

    void f(Base & b);  f(*derived); 
like image 144
Kerrek SB Avatar answered Sep 22 '22 13:09

Kerrek SB