// Get Custom Data template Data *custom_get(typename Data::__Self *self) { return (Data *) (self + 1); } // Duplicate VTable template T *__dup_vtable(const T *vtable) { // Get Size constexpr size_t rtti_size = sizeof(void *); const unsigned char *const real_vtable = ((const unsigned char *) vtable) - rtti_size; constexpr size_t real_vtable_size = sizeof(T) + rtti_size; // Allocate unsigned char *const new_vtable = (unsigned char *) ::operator new(real_vtable_size); T *ret = (T *) (new_vtable + rtti_size); new (ret) T; // Copy memcpy(new_vtable, real_vtable, real_vtable_size); // Return return ret; } // Base template struct __CustomBase { // Properties typedef A __Self; typedef B __VTable; __Self *const self; // Prevent Copying __PREVENT_COPY(__CustomBase); #define get_self(ptr) (((__Self *) ptr) - 1) #ifdef {{ BUILDING_SYMBOLS_GUARD }} // Constructor __CustomBase(): self(get_self(this)) {} #else // Prevent Construction __PREVENT_JUST_CONSTRUCTION(__CustomBase); #endif // Destructor virtual ~__CustomBase() = default; // Allocation void *operator new(const size_t count) { const size_t size = sizeof(__Self) + count; __Self *out = (__Self *) ::operator new(size); return (void *) custom_get<__CustomBase>(out); } void *operator new[](size_t) = delete; // Deallocation void operator delete(__CustomBase *ptr, std::destroying_delete_t) { if (ptr) { __Self *self = ptr->self; // This Calls The Actual Destructor self->vtable->destructor_deleting(self); } } void operator delete(void *ptr) { if (ptr) { // Issue During Construction, Just Free Memory ::operator delete(get_self(ptr)); } } #undef get_self void operator delete[](void *) = delete; protected: // VTable virtual void __patch_vtable(__VTable *vtable) { // Patch Destructors #define patch(type) \ vtable->type = [](__Self *self) { \ custom_get<__CustomBase>(self)->~__CustomBase(); \ return __VTable::base->type(self); \ } patch(destructor_complete); patch(destructor_deleting); #undef patch } void __set_vtable() { static __VTable *vtable = nullptr; if (!vtable) { vtable = __dup_vtable(__VTable::base); __patch_vtable(vtable); } this->self->vtable = vtable; } };