D hackers requested. Dancing around postblit.
Please try to solve this task: We have a struct S. S has a some kind of postblit (user-defined or inherited frome field) and destructor. S has a @disabled opAssign. We have an unitialized allocated memory block whick mapped to a S array. struct S { //postblit and dtor here } S[] data; // contains a garbarge void emplace()(ref S val, size_t i); The task: we should write emplace function, which initializes i-th element of data with val; This function shouldn't call any dtors for example for the old data[i] (which contains a garbarge). This function should be transparent for attributes. For example, if S postblit is nothrow emplace should be nothrow too. If S postblit is not nothrow, S should't be nothrow. This function should call postblit only one time and shouldn't call any other S special functions (opAssign, ctor etc.)
Re: D hackers requested. Dancing around postblit.
If you're willing to make it @system or @trusted, you can just copy the data and call postblit manually: extern(C) @safe int printf(in char*); struct S { ~this() { printf(dtor\n); } this(this) { printf(postblit\n); } @disable S opAssign(S s); } S[] data; void emplace(Struct)(ref Struct val, size_t i) { // just blit the struct contents over // (same thing normal assign does anyway) (cast(ubyte*)(data[i]))[0 .. Struct.sizeof] = (cast(ubyte*)val)[0 .. Struct.sizeof]; // call postblit data[i].__postblit(); } void main() { data.length = 1; S s; emplace(s, 0); } Since it is a template, attribute inference should take care of nothrow, etc.
Re: D hackers requested. Dancing around postblit.
On Wednesday, 5 November 2014 at 20:01:59 UTC, Adam D. Ruppe wrote: If you're willing to make it @system or @trusted, you can just copy the data and call postblit manually: extern(C) @safe int printf(in char*); struct S { ~this() { printf(dtor\n); } this(this) { printf(postblit\n); } @disable S opAssign(S s); } S[] data; void emplace(Struct)(ref Struct val, size_t i) { // just blit the struct contents over // (same thing normal assign does anyway) (cast(ubyte*)(data[i]))[0 .. Struct.sizeof] = (cast(ubyte*)val)[0 .. Struct.sizeof]; // call postblit data[i].__postblit(); } void main() { data.length = 1; S s; emplace(s, 0); } Since it is a template, attribute inference should take care of nothrow, etc. It was my first try :( data[i].__postblit(); calls the user-defined postblit and only it. struct Sx { ~this() { printf(dtor\n); } this(this) { printf(postblit\n); } @disable S opAssign(S s); } struct S { Sx s; } data[i].__postblit(); //error: S hasn't __postblit member, but it need the postblit call for Sx typeid(S).postblit(data[i]) works as needed, but doesn't save postblit attributes.
Re: D hackers requested. Dancing around postblit.
FYI: My second try: void emplace(V1)(ref V1 dst, ref V1 src) @trusted if (is(V1 == struct)) { static if (new_obj) { V1 tmp = cast(V1)src; //create copy and call postblit static V1 init = V1.init; //bitwise copy of object, which already postblitted (cast(void*)dst)[0 .. V1.sizeof] = (cast(void*)tmp)[0 .. V1.sizeof]; //initialize tmp with V1.init. (cast(void*)tmp)[0 .. V1.sizeof] = (cast(void*)init)[0 .. V1.sizeof]; } } This method do one extra dtor call for tmp, but it may be trivial because tmp is V.init. However it is not a complete solution of the task.
Re: D hackers requested. Dancing around postblit.
On Wednesday, 5 November 2014 at 20:19:03 UTC, IgorStepanov wrote: data[i].__postblit(); //error: S hasn't __postblit member, but it need the postblit call for Sx Hmm, we could perhaps do a recursive call with __traits(allMembers) and if it has a __postblit.
Re: D hackers requested. Dancing around postblit.
On Wednesday, 5 November 2014 at 20:33:40 UTC, Adam D. Ruppe wrote: On Wednesday, 5 November 2014 at 20:19:03 UTC, IgorStepanov wrote: data[i].__postblit(); //error: S hasn't __postblit member, but it need the postblit call for Sx Hmm, we could perhaps do a recursive call with __traits(allMembers) and if it has a __postblit. Good point. I'll try it. Thanks.