Destructors can't be @nogc?

user1234 user1234 at 12.de
Sun Jul 25 01:17:06 UTC 2021


On Friday, 23 July 2021 at 20:24:02 UTC, Jim wrote:
> Hello,
>
> I've been playing with D and trying to understand how to work 
> with @nogc. I must be doing something wrong, because even 
> though I tagged the destructor for my class `@nogc`, I'm 
> getting the following error: `.\min.d(27): Error: "@nogc" 
> function "D main" cannot call non- at nogc function 
> "object.destroy!(true, TestClass).destroy`
>
> [...]
> What is the problem here? Should I not call `destroy`? If so,

`destroy()` uses the runtime types informations to detect the 
most derived destructor (as you might cast from `TestClass` to 
least specialized, i.e `Object`). The type infos for classes 
stores the destructor in form of a function pointer that has not 
`@nogc` as part of its attributes.

> what should I call instead?

get rid of `destroy()` and instead use your own allocator, 
virtual constructor (instead of `this(){}`) and virtual 
destructor (instead of `~this(){}`) in a base class.

e.g

```d
class Base
{
     static auto make(T : Base, Args...)(Args args)
     {
         auto size = __traits(classInstanceSize, T);
         auto memory = malloc(size)[0..size];
         T t = emplace!(T)(memory);
         t.construct(args); // call the most derived
         return t;
     }

     void construct() @nogc
     {
         printf("Base constructor called\n");
     }

     void destruct() @nogc
     {
         printf("Base destructor called\n");
         free(cast(void*) this);
     }
}

class Derived : Base
{
     override void construct() @nogc
     {
         super.construct(); // construct from base to most derived
         printf("Derived constructor called\n");
     }

     override void destruct() @nogc
     {
         printf("Derived destructor called\n");
         super.destruct(); // destruct from derived to base
                           // finishing with the deallocation
     }
}

void main(string[] args) @nogc
{
     Base b = Base.make!(Derived);
     b.destruct();
}
```

things get called correctly

> Base constructor called
Derived constructor called
Derived destructor called
Base destructor called

That bypasses the runtime mechanism for classes construction and 
destruction.
But `new` and `destroy` must not be called anymore, you must get 
stick with your own system.



More information about the Digitalmars-d-learn mailing list