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-@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.