Need help to compile code with traits
Basile B. via Digitalmars-d-learn
digitalmars-d-learn at puremagic.com
Sun Feb 5 09:32:04 PST 2017
On Sunday, 5 February 2017 at 14:59:04 UTC, Xavier Bigand wrote:
> Hi,
>
> I am trying to create an allocator that don't use the GC, and I
> have issues for the initialization of member before calling the
> constructor.
> Here is my actual code :
>> mixin template NogcAllocator(T)
>> {
>> static T nogcNew(T, Args...)(Args args) @nogc
>> {
>> import core.stdc.stdlib : malloc;
>> import std.traits;
>>
>> T instance;
>>
>> instance = cast(T)malloc(__traits(classInstanceSize, T));
>> foreach (string member; __traits(allMembers, T))
>> {
>> static if (isType!(__traits(getMember, T, member)))
>> __traits(getMember, instance, member) =
>> typeof(__traits(getMember, T, member)).init;
>> }
>>
>> instance.__ctor(args);
>> return instance;
>> }
>>
>> static void nogcDelete(T)(T instance) @nogc
>> {
>> import core.stdc.stdlib : free;
>>
>> instance.__dtor();
>> free(instance);
>> }
>> }
>>
>> unittest
>> {
>> struct Dummy {
>> int field1 = 10;
>> int field2 = 11;
>> }
>>
>> class MyClass {
>> mixin NogcAllocator!MyClass;
>>
>> int a = 0;
>> int[] b = [1, 2, 3];
>> Dummy c = Dummy(4, 5);
>>
>> int d = 6;
>>
>> this() @nogc {
>> }
>>
>> this(int val) @nogc {
>> d = val;
>> }
>> }
>>
>> MyClass first = MyClass.nogcNew!MyClass();
>> MyClass second = MyClass.nogcNew!MyClass(7);
>>
>> assert(first.a == 0);
>> assert(first.b == [1, 2, 3]);
>> assert(first.c.field1 == 4);
>> assert(first.d == 6);
>>
>> assert(second.c.field1 == 4);
>> assert(second.d == 7);
>> }
>
>
> And the compilation errors :
>> ..\src\core\nogc_memory.d(16): Error: no property 'this' for
>> type 'core.nogc_memory.__unittestL39_3.MyClass'
>> ..\src\core\nogc_memory.d(17): Error: type Monitor is not an
>> expression
>> ..\src\core\nogc_memory.d(63): Error: template instance
>> core.nogc_memory.__unittestL39_3.MyClass.NogcAllocator!(MyClass).nogcNew!(MyClass) error instantiating
>> ..\src\core\nogc_memory.d(16): Error: no property 'this' for
>> type 'core.nogc_memory.__unittestL39_3.MyClass'
>> ..\src\core\nogc_memory.d(17): Error: type Monitor is not an
>> expression
>> ..\src\core\nogc_memory.d(64): Error: template instance
>> core.nogc_memory.__unittestL39_3.MyClass.NogcAllocator!(MyClass).nogcNew!(MyClass, int) error instantiating
>
> I don't understand my mistake with the getMember and isType
> traits.
> And I am curious about of what is the Monitor.
The whole thing you do to initialize could be replaced by a copy
of the initializer, which is what emplace does:
static T nogcNew(T, Args...)(Args args) @nogc
{
import core.stdc.stdlib : malloc;
import std.traits, std.meta;
T instance;
enum s = __traits(classInstanceSize, T);
instance = cast(T) malloc(s);
(cast(void*) instance)[0..s] = typeid(T).initializer[];
instance.__ctor(args);
return instance;
}
Your nogcDelete() is bug-prone & leaky
- use _xdtor, which also calls the __dtor injected by mixin.
- even if you do so, __xdtors are not inherited !! instead dtor
in parent classes are called by destroy() directly.
Currently what I do to simulate inherited destructor is to mix
this for each new generation.
mixin template inheritedDtor()
{
private:
import std.traits: BaseClassesTuple;
alias B = BaseClassesTuple!(typeof(this));
enum hasDtor = __traits(hasMember, typeof(this), "__dtor");
static if (hasDtor && !__traits(isSame, __traits(parent,
typeof(this).__dtor), typeof(this)))
enum inDtor = true;
else
enum inDtor = false;
public void callInheritedDtor(classT = typeof(this))()
{
import std.meta: aliasSeqOf;
import std.range: iota;
foreach(i; aliasSeqOf!(iota(0, B.length)))
static if (__traits(hasMember, B[i], "__xdtor"))
{
mixin("this." ~ B[i].stringof ~ ".__xdtor;");
break;
}
}
static if (!hasDtor || inDtor)
public ~this() {callInheritedDtor();}
}
When a dtor is implemented it has to call "callInheritedDtor()"
at end of the dtor implementation.
More information about the Digitalmars-d-learn
mailing list