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









"IgorStepanov" <wazar mail.ru> 