Need help to compile code with traits
Xavier Bigand via Digitalmars-d-learn
digitalmars-d-learn at puremagic.com
Sun Feb 5 11:06:38 PST 2017
Le 05/02/2017 à 18:32, Basile B. a écrit :
> 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;
> }
>
Nice, thank you for that, it is much elegant ;-)
>
> Your nogcDelete() is bug-prone & leaky
Certainly I didn't think a lot about it for the moment.
>
> - 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.
Thank you a lot for this great help.
More information about the Digitalmars-d-learn
mailing list