Thread overview
Shallow copy object when type is know
Apr 20, 2016
Tofu Ninja
Apr 20, 2016
Tofu Ninja
Apr 20, 2016
Alex Parrill
Apr 20, 2016
Tofu Ninja
Apr 21, 2016
Rene Zwanenburg
Apr 21, 2016
Marc Schütz
Apr 21, 2016
rumbu
Aug 28, 2020
mw
April 20, 2016
Is there a way to shallow copy an object when the type is known? I cant seem to figure out if there is a standard way. I can't just implement a copy function for the class, I need a generic solution.
April 20, 2016
On Wednesday, 20 April 2016 at 12:32:48 UTC, Tofu Ninja wrote:
> Is there a way to shallow copy an object when the type is known? I cant seem to figure out if there is a standard way. I can't just implement a copy function for the class, I need a generic solution.

I feel like

void shallow_copy(T)(T s, T d) if(is(T == class)) {
	ubyte[] sp = (cast(ubyte*)s)[0..T.classinfo.m_init.length];
	ubyte[] dp = (cast(ubyte*)d)[0..T.classinfo.m_init.length];
	dp[] = sp[];
}

would be really unsafe but I dont see any other way to do it... I dont know what kind of hidden members I might be messing up when doing that.
April 20, 2016
On Wednesday, 20 April 2016 at 12:32:48 UTC, Tofu Ninja wrote:
> Is there a way to shallow copy an object when the type is known? I cant seem to figure out if there is a standard way. I can't just implement a copy function for the class, I need a generic solution.

A generic class copy function would require accessing private fields, so a clean per-attribute class copy is impossible. Doing a bitwise copy might work except for the synchronization mutex pointer.

Can you elaborate on why you need this?
April 20, 2016
On Wednesday, 20 April 2016 at 18:48:58 UTC, Alex Parrill wrote:
> On Wednesday, 20 April 2016 at 12:32:48 UTC, Tofu Ninja wrote:
>> Is there a way to shallow copy an object when the type is known? I cant seem to figure out if there is a standard way. I can't just implement a copy function for the class, I need a generic solution.
>
> A generic class copy function would require accessing private fields, so a clean per-attribute class copy is impossible. Doing a bitwise copy might work except for the synchronization mutex pointer.
>
> Can you elaborate on why you need this?

To implement a copy/paste/duplicate functionality in a game editor. I have an entity-component system, to duplicate an entity, all it's components need to be duplicated. I have many many components, I don't want to rely on manually writing copy methods for each, it is too error prone. There are only a very few that need special copies, almost all can get by with a simple shallow copy. I would like a generic way to do that shallow copy.

How does D not have shallow copy? Seems like a very basic functionality...
April 21, 2016
On Wednesday, 20 April 2016 at 19:58:15 UTC, Tofu Ninja wrote:
> To implement a copy/paste/duplicate functionality in a game editor. I have an entity-component system, to duplicate an entity, all it's components need to be duplicated. I have many many components, I don't want to rely on manually writing copy methods for each, it is too error prone. There are only a very few that need special copies, almost all can get by with a simple shallow copy. I would like a generic way to do that shallow copy.

How are you handling loading and saving of your components? Can't you use the same mechanism, without going through the storage format?

Anyway, to answer your question, perhaps something like this: (untested, it probably needs some minor modifications to compile)

T shallowCopy(T)(T source)
{
	assert(source.classinfo == T.typeinfo);
	auto rv = new T;
	shallowCopy(source, rv);
	return rv;
}

void shallowCopy(T)(T source, T target)
{
	foreach(i; 0 .. T.tupleof.length)
	{
		target.tupleof[i] = source.tupleof[i];
	}
	
	import std.traits : BaseClassesTuple;
	alias baseClasses = BaseClassesTuple!T;
	
	static if(baseClasses.length > 0)
	{
		shallowCopy!(baseClasses[0])(source, target);
	}
}


>
> How does D not have shallow copy? Seems like a very basic functionality...

Generally speaking copying class instances is a very bad idea. That's one of the things structs are for.
April 21, 2016
On Wednesday, 20 April 2016 at 19:58:15 UTC, Tofu Ninja wrote:
> How does D not have shallow copy? Seems like a very basic functionality...

You could implement a `dup()` method. `dup` is already used for shallow copying of arrays, why not reuse it for classes (as a convention)?
April 21, 2016
On Wednesday, 20 April 2016 at 12:32:48 UTC, Tofu Ninja wrote:
> Is there a way to shallow copy an object when the type is known? I cant seem to figure out if there is a standard way. I can't just implement a copy function for the class, I need a generic solution.

extern (C) Object _d_newclass(TypeInfo_Class ci);

Object dup(Object obj)
{
    if (obj is null)
        return null;
    ClassInfo ci = obj.classinfo;
    size_t start = Object.classinfo.init.length;
    size_t end = ci.init.length;
    Object clone = _d_newclass(ci);
    (cast(void*)clone)[start .. end] = (cast(void*)obj)[start .. end];
    return clone;
}

August 28, 2020
On Thursday, 21 April 2016 at 11:53:13 UTC, rumbu wrote:
> On Wednesday, 20 April 2016 at 12:32:48 UTC, Tofu Ninja wrote:
>> Is there a way to shallow copy an object when the type is known? I cant seem to figure out if there is a standard way. I can't just implement a copy function for the class, I need a generic solution.
>
> extern (C) Object _d_newclass(TypeInfo_Class ci);
>
> Object dup(Object obj)
> {
>     if (obj is null)
>         return null;
>     ClassInfo ci = obj.classinfo;
>     size_t start = Object.classinfo.init.length;
>     size_t end = ci.init.length;
>     Object clone = _d_newclass(ci);
>     (cast(void*)clone)[start .. end] = (cast(void*)obj)[start .. end];
>     return clone;
> }

Is this the established D-idiom of a generic class bit-wise clone function (as of 2020)?

Any risk of using this implementation I should be aware of?

Thanks.