Have looked at various similar questions here but still can't figure out why the following code does not compile:
// these three are defined somewhere
class A;
std::unique_ptr<A> make_a();
void take_a(std::unique_ptr<A>&&);
int main(){
take_a(make_a()); // this fails
return 0;
}
According to this:
If the default deleter is used, T must be complete at the point in code where the deleter is invoked, which happens in the destructor, move assignment operator, and reset member function of std::unique_ptr.
As far as I understand, none of these (destructor, move assignment operator, nor reset member function) happens in main
.
So why does compiler needs the definition of A
here?
CodePudding user response:
Since main has a unique_ptr within its scope, realistically it would need to know how to delete the object it holds.
It's possible that take_a doesn't actually take ownership of the object, thus main would need to delete.
CodePudding user response:
main
gets a temporary unique_ptr
from make_a()
, let's call it X
. It then passes an rvalue reference to X
to take_a
. It still has the destroy X
. Hence, it has to call the destructor after take_a
, even though X
would typically be empty at that point.
CodePudding user response:
We need class A description (at least constructor and destructor) in order to create and move std::unique_ptr<A>
objects; take_a(make_a())
is creating such object because make_a()
is pass-by-value. It first creates a new unique_ptr<A>
object, initialize it (using default constructor), and then update its value and returns this new object. Here the default constructor/destructor is being used, which the compiler is unable to find.
#include <bits/stdc .h>
class A {
public: A() {}
public: ~A() {}
};
std::unique_ptr<A> make_a() {
std::cout << "make";
std::unique_ptr <A> tt = nullptr;
return tt;
}
void take_a(std::unique_ptr<A>&&) {
std::cout << "take";
}
int main(){
take_a(make_a()); // this works now
return 0;
}