D hackers requested. Dancing around postblit.

2014-11-05 Thread IgorStepanov via Digitalmars-d

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.

2014-11-05 Thread Adam D. Ruppe via Digitalmars-d
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.

2014-11-05 Thread IgorStepanov via Digitalmars-d
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.

2014-11-05 Thread IgorStepanov via Digitalmars-d

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.

2014-11-05 Thread Adam D. Ruppe via Digitalmars-d

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.

2014-11-05 Thread IgorStepanov via Digitalmars-d
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.