Home > Blockchain >  C another unique_ptr incomplete type question
C another unique_ptr incomplete type question

Time:12-18

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;
}

Edit: Forgot to add the link. Works the other way too.

  • Related