| Thread overview | ||||||||
|---|---|---|---|---|---|---|---|---|
|
November 05, 2014 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.)
| ||||
November 05, 2014 Re: D hackers requested. Dancing around postblit. | ||||
|---|---|---|---|---|
| ||||
Posted in reply to IgorStepanov | 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.
| |||
November 05, 2014 Re: D hackers requested. Dancing around postblit. | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Adam D. Ruppe | 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.
| |||
November 05, 2014 Re: D hackers requested. Dancing around postblit. | ||||
|---|---|---|---|---|
| ||||
Posted in reply to IgorStepanov | 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.
| |||
November 05, 2014 Re: D hackers requested. Dancing around postblit. | ||||
|---|---|---|---|---|
| ||||
Posted in reply to IgorStepanov | 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.
| |||
November 05, 2014 Re: D hackers requested. Dancing around postblit. | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Adam D. Ruppe | 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.
| |||
Copyright © 1999-2021 by the D Language Foundation
Permalink
Reply