digitalmars.D - D hackers requested. Dancing around postblit.
- IgorStepanov (21/21) Nov 05 2014 Please try to solve this task:
- Adam D. Ruppe (24/24) Nov 05 2014 If you're willing to make it @system or @trusted, you can just
- IgorStepanov (18/42) Nov 05 2014 It was my first try :(
- IgorStepanov (20/20) Nov 05 2014 FYI:
- Adam D. Ruppe (3/5) Nov 05 2014 Hmm, we could perhaps do a recursive call with
- IgorStepanov (3/9) Nov 05 2014 Good point. I'll try it. Thanks.
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.)
Nov 05 2014
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.
Nov 05 2014
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.
Nov 05 2014
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.
Nov 05 2014
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 SxHmm, we could perhaps do a recursive call with __traits(allMembers) and if it has a __postblit.
Nov 05 2014
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:Good point. I'll try it. Thanks.data[i].__postblit(); //error: S hasn't __postblit member, but it need the postblit call for SxHmm, we could perhaps do a recursive call with __traits(allMembers) and if it has a __postblit.
Nov 05 2014