0

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);
umläute
  • 28,885
  • 9
  • 68
  • 122

3 Answers3

4
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.

Yksisarvinen
  • 18,008
  • 2
  • 24
  • 52
0

Aren't you missing a reference?

Hint, near x.

Kharski
  • 43
  • 7
0

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

Obsidian
  • 3,719
  • 8
  • 17
  • 30
vtronko
  • 478
  • 3
  • 10