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
Aren’t you missing a reference?
Hint, near x.
foo
is lvalue, so compiler will select l-value reference constructor (a.k.a. copy constructor) forstd::unique_ptr
– but it is deleted. Instead, you have to tell compiler that you want to use r-value reference constructor (move constructor) by usingstd::move()
In this example:
std::make_unique<Foo>()
is a temporary object, it doesn’t have a name, so it’s an r-value. No additional call tostd::move
needed.Due to ownership semantics,
std::unique_ptr<T>
cannot be shared. Copy constructor special member function is deleted for it, hence the error.