Let's start with the warm-up.
I created a class template whose destructor just cannot be instantiated without compiler activating static_assert
:
File: M.hpp
template <typename T>
struct M
{
M(){}
~M()
{
static_assert(sizeof(T) == 0, "no type can pass this");
}
};
Next I used this class in two different ways: allocate it on heap and allocate it on stack:
File main.cpp
#include "M.hpp"
int main()
{
M<int> *pmi = new M<int>(); // does compile
M<int> mi; // doen't compile
}
Allocating it on a heap M<int> *pmi = new M<int>();
works. It is so as we only use constructor and don't need destructor. The rules for class template implicit instantiation say:
... unless the member is used in the program, it is not instantiated ...
Allocating it on stack M<int> mi;
doesn't work as compiler definitely need to instantiate the destructor.
So far so good, clear rules.
Let's get to the point.
I wrote another class which uses M
as a member:
File X.cpp
#include "M.hpp"
struct X
{
X() = default;
~X() = delete;
private:
M<int> m_;
};
I deleted the destructor intentionally because I don't want it to interfere anyhow with my experiment.
Constructor is defaulted which in my understanding should only generate constructor of M<int>
, its only member, and call it.
To my surprise this is not the case. X()
also tries to generate the destructor of M<int>
:
File main.cpp
#include "X.hpp"
int main()
{
X* px = new X();
}
and this is what I get from a compiler:
$ g++ -std=c++17 main.cpp
In file included from X.hpp:1,
from main.cpp:1:
M.hpp: In instantiation of ‘M<T>::~M() [with T = int]’:
X.hpp:5:3: required from here
M.hpp:7:29: error: static assertion failed: no type can pass this
static_assert(sizeof(T) == 0, "no type can pass this");
The question is: why during the instantiation of the default constructor a compiler tries to instantiate a destructor for a member class template if it is not needed? If it is indeed needed could you point me at the documentation where it is stated?