Using __rvalue and placement new in new variants of core.lifetime.move

Per Nordlöw per.nordlow at gmail.com
Tue Apr 29 07:49:26 UTC 2025


I'm currently using these new implementations of 
core.lifetime.move

```d

	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`.


More information about the Digitalmars-d-learn mailing list