C++20 added the concept of "destroying delete" which lets you create overloads of operator delete
that are required to run the object destructor themselves. Normally the destructor call is emitted by the compiler automatically and happens before the delete
is invoked, so the delete operator is only expected to handle freeing the memory. The advantage of destroying delete is that since the object is still alive the custom delete
implementation can inspect the object to decide how to delete it (for example by delegating the deletion to an allocator stored on the object itself).
Unfortunately destroying delete was not added for coroutines, and there are of course people still on pre-C++-20 versions who would like a workaround in general.
I'm wondering if you know that instances of some type Foo
are always heap allocated, if you can get away with having a no-op destructor, such that the delete operator can then cast the memory back to the type, before manually running the deletion logic. For each member of Foo
, instead of storing it normally you would store it as a MaybeUninit<T>
and use placement new in order to prevent automatic invocation of member destructors:
template<class T>
class MaybeUninit {
alignas(T) char _storage[sizeof(T)];
};
And you would define the Foo
destructor to be empty:
class Foo {
public:
~Foo() {}
// ... snip
};
Then in your operator delete
you would take the passed in void*
and cast it to Foo
, inspect whatever you need to and then manually invoke all the destructors. I'm guessing this is UB, since you are using the object after the compiler thinks the object's lifetime ended (its destructor was invoked)? If so is there anyway to rescue the trick?