skip to Main Content

i’m a bit of a noob when it comes to modern C++.

the problem at hand is, that i would like to pass a unique_ptr to a ctor via a variable.

everything works nicely, if i pass the unique_ptr directly, but as soon as i assign it to a variable, i get a compilation error:

test.cpp:25:22: error: use of deleted function ‘std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = Foo; _Dp = std::default_delete]’

#include <memory>

class Foo {
public:
  Foo(void) {;}
};

class Bar {
public:
  Bar(std::unique_ptr<Foo> x)
    : m_foo(std::move(x))
    { ; }
  std::unique_ptr<Foo> m_foo;
};


void test(void) {
  auto bar0 = Bar(std::make_unique<Foo>()); // this works

  auto foo = std::make_unique<Foo>(); // this works
  auto bar1 = Bar(foo);  // this FAILS
}

and

$ g++ --version
g++ (Debian 9.3.0-8) 9.3.0
$ g++ -c test.cpp -o test.o
test.cpp: In function ‘void test()’:
test.cpp:21:22: error: use of deleted function ‘std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = Foo; _Dp = std::default_delete<Foo>]’
   21 |   auto bar1 = Bar(foo);
      |                      ^
In file included from /usr/include/c++/9/memory:80,
                 from test.cpp:1:
/usr/include/c++/9/bits/unique_ptr.h:414:7: note: declared here
  414 |       unique_ptr(const unique_ptr&) = delete;
      |       ^~~~~~~~~~
test.cpp:10:28: note:   initializing argument 1 of ‘Bar::Bar(std::unique_ptr<Foo>)’
   10 |   Bar(std::unique_ptr<Foo> x)
      |       ~~~~~~~~~~~~~~~~~~~~~^
make: *** [<builtin>: test] Error 1

why?

the actual code i’m debugging (and make it compile with a new compiler) is similar to that:

auto x = function_creating_a_uniqptr(args,...); // might return NULL
if (pi == nullptr) {
  return std::make_unique<Plugin>(); // Invalid plug-in
}
return std::make_unique<Plugin>(x);

3

Answers


  1. Aren’t you missing a reference?

    Hint, near x.

    Login or Signup to reply.
  2. auto bar1 = Bar(std::move(foo)); 
    

    foo is lvalue, so compiler will select l-value reference constructor (a.k.a. copy constructor) for std::unique_ptr – but it is deleted. Instead, you have to tell compiler that you want to use r-value reference constructor (move constructor) by using std::move()

    In this example:

    auto bar0 = Bar(std::make_unique<Foo>());
    

    std::make_unique<Foo>() is a temporary object, it doesn’t have a name, so it’s an r-value. No additional call to std::move needed.

    Login or Signup to reply.
  3. Due to ownership semantics, std::unique_ptr<T> cannot be shared. Copy constructor special member function is deleted for it, hence the error.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search