Extra .tupleof field in structs with disabled postblit blocks non-GC-allocation trait

Meta jared771 at gmail.com
Thu May 10 19:14:39 UTC 2018


On Thursday, 10 May 2018 at 12:55:36 UTC, Uknown wrote:
> On Thursday, 10 May 2018 at 11:06:06 UTC, Per Nordlöw wrote:
>> On Wednesday, 9 May 2018 at 21:09:12 UTC, Meta wrote:
>>> It's a context pointer to the enclosing 
>>> function/object/struct. Mark the struct as static to get rid 
>>> of it.
>>
>> Ok, but why an extra void* for `S.tupleof` and not for 
>> `T.tupleof` which is also scoped inside a unittest?
>
> I'm guessing T is a POD, so it doesn't need a context pointer, 
> whereas S is not counted as a POD since a member function was 
> @disabled.

Yes, exactly. From my tests, if you add _any_ member method to a 
struct, it becomes non-POD. When you think about it, this makes 
perfect sense, as there's no possible way to access anything 
through a context pointer if there is no executable code within 
the struct's scope.

As far an @disabled postblit:

Plain Old Data
A struct or union is Plain Old Data (POD) if it meets the 
following criteria:

it is not nested
it has no postblits, destructors, or assignment operators
it has no ref fields or fields that are themselves non-PO

https://docarchives.dlang.io/v2.079.0/spec/struct.html#POD

Now if you do this:

struct R
{
     @disable this(this);
     int* _ptr;
}
unittest
{
     struct S
     {
         @disable this(this);
         int* _ptr;
     }
     struct T
     {
         int* _ptr;
     }
     pragma(msg, "R: ", typeof(R.tupleof));
     pragma(msg, __traits(allMembers, R));

     pragma(msg, "S: ", typeof(S.tupleof));
     pragma(msg, __traits(allMembers, S));

     pragma(msg, "T: ", typeof(T.tupleof));
     pragma(msg, __traits(allMembers, T));
}

It prints:

R: (int*)
tuple("__postblit", "_ptr", "__xpostblit", "opAssign")

S: (int*, void*)
tuple("__postblit", "_ptr", "this", "__xpostblit", "opAssign")

T: (int*)
tuple("_ptr")

So it looks like disabling a struct's postblit actually counts as 
having a __postblit and __xpostblit function (don't ask me why), 
in addition to a construction and opAssign... no idea why, and 
maybe this is a bug, but I bet there's a good reason for it.

Anyway, as per my first point, this means it'll need a context 
pointer unless you mark the struct as static.


More information about the Digitalmars-d-learn mailing list