I'm currently using these new implementations of core.lifetime.move
import core.stdc.string : memcpy;
/++ Variant of `core.lifetime.move(source)` that uses `__rvalue`.
If `T` is a struct with a destructor or postblit defined, source is
reset to its `.init` value after it is moved into target, otherwise it
is left unchanged.
See https://github.com/dlang/dmd/pull/20946/files.
+/
/+TODO:ref+/ T move(T)(return scope ref T source) @trusted /+TODO:__rvalue+/ {
static if (__traits(isStaticArray, T)) {
typeof(return) destination = void;
foreach (const i, ref e; source) // TODO: use single call to `moveEmplaceAll`
// TODO: Replace with: new (destination[i]) typeof(T.init[i])(__rvalue(e)); // placement new
moveEmplace(e, destination[i]);
return destination;
} else {
typeof(return) destination = __rvalue(source); // runs move constructors if present
static if (is(T == struct) && (__traits(hasMember, T, "__xdtor") || __traits(hasMember, T, "__fieldPostblit"))) {
static immutable init = T.init;
memcpy(&source, &init, T.sizeof);
}
return destination;
}
}
/++ Variant of `core.lifetime.move(source, destination)` that uses `__rvalue`.
If `T` is a struct with a destructor or postblit defined, source is
reset to its `.init` value after it is moved into target, otherwise it
is left unchanged.
+/
void move(T)(ref T source, ref T destination) @trusted {
static if (__traits(isStaticArray, T)) {
foreach (const i, ref e; source) // TODO: use single call to `moveAll`
move(e, destination[i]);
} else {
destination = __rvalue(source); // runs move constructors if present
static if (is(T == struct) && (__traits(hasMember, T, "__xdtor") || __traits(hasMember, T, "__fieldPostblit"))) {
static immutable init = T.init;
memcpy(&source, &init, T.sizeof);
}
}
}
/++ Variant of `core.lifetime.moveEmplace(source, destination)` that uses `__rvalue`.
If `T` is a struct with a destructor or postblit defined, source is
reset to its `.init` value after it is moved into target, otherwise it
is left unchanged.
+/
void moveEmplace(T)(ref T source, ref T destination) @system {
static if (__traits(isStaticArray, T)) {
foreach (const i, ref e; source) // TODO: use single call to `moveEmplaceAll`
moveEmplace(e, destination[i]);
} else {
memcpy(&destination, &source, T.sizeof); // TODO: Use `__rvalue` here?
static if (is(T == struct)) {
static if ((__traits(hasMember, T, "__xdtor") || __traits(hasMember, T, "__fieldPostblit"))) {
static immutable init = T.init;
memcpy(&source, &init, T.sizeof);
}
}
}
}
.
How can these be improved?
I'm asking because uncommenting the usages of placement new in the implementations triggers segmentation faults that I fail to understand the source of.
I also haven't found a way to qualify any of the overloads with __rvalue
.