Reputation: 873
From C++ Primer (13.1.6):
The compiler will not let us define variables or create temporaries of a type that has a deleted destructor. Moreover, we cannot define variables or temporaries of a class that has a member whose type has a deleted destructor. If a member has a deleted destructor, then that member cannot be destroyed. If a member can’t be destroyed, the object as a whole can’t be destroyed.
This certaintly seems true:
class B{
public:
B() { }
~B() = delete;
};
class A{
public:
A() {}
~A() {}
B b;
};
int main(){
//B b; //error
A a; //error
}
brings in all sorts of errors about B
's deleted destructor. This must be because a destructor, even an explicit one, implictly calls destructors of the class members as pointed out in (12.4/8) of N3337:
After executing the body of the destructor and destroying any automatic objects allocated within the body, a destructor for class X calls the destructors for X’s direct non-variant non-static data members, the destructors for X’s direct base classes and, if X is the type of the most derived class (12.6.2), its destructor calls the destructors for X’s virtual base classes.
I'm now curious why the following works though:
#include <string>
class A{
public:
A() { }
union {
std::string test;
};
~A() { }
};
int main(){
A b;
}
Given that, from 9.5/2 of N3337:
If any non-static data member of a union has a non-trivial default constructor (12.1), copy constructor (12.8), move constructor (12.8), copy assignment operator (12.8), move assignment operator (12.8), or destructor (12.4), the corresponding member function of the union must be user-provided or it will be implicitly deleted (8.4.3) for the union.
My class A
has an anonymous union object which in turn has a string
data member which of course defines its own destructor. So the union, from above, must have a deleted destructor! But my quote from the top says it must not be possible to create objects of A
's type because it has a member with a deleted destructor. If I comment out ~A(){}
then indeed I get an error, but for some reason my explicit definition is okay. What happens when my explicit definition tries to implicitly destroy the union object?
Upvotes: 2
Views: 1048
Reputation: 283634
What happens when my explicit definition tries to implicitly destroy the union object?
It doesn't. There is no implicit destruction of variant members, your destructor must perform destruction explicitly using member.~TYPE()
syntax.
For that to happen, your destructor has to figure out which one (if any) of the variant members in each anonymous union is alive and in need to destruction.
Note that you even quoted the rule:
After executing the body of the destructor and destroying any automatic objects allocated within the body, a destructor for class X calls the destructors for X’s direct NON-VARIANT non-static data members, the destructors for X’s direct base classes and, if X is the type of the most derived class (12.6.2), its destructor calls the destructors for X’s virtual base classes.
Your paraphrase "implictly calls destructors of the class members" left out this important qualification.
Upvotes: 3