Created attachment 924
testcase
std.algorithm.move does not work on T that hasElaborateDestructor!T or
hasElaborateCopyConstructor!T.
This test should work.
----
unittest
{
static struct S
{
static struct X
{
int n = 0;
~this(){n = 0;}
}
X x;
}
static assert(hasElaborateDestructor!S);
S s1, s2;
s1.x.n = 1;
move(s1, s2);
assert(s1.x.n == 0);
assert(s2.x.n == 1);
static struct T
{
static struct X
{
int n = 0;
this(this){n = 0;}
}
X x;
}
static assert(hasElaborateCopyConstructor!T);
T t1, t2;
t1.x.n = 1;
move(t1, t2);
assert(t1.x.n == 0);
assert(t2.x.n == 1);
}
----
See also attached file of full test case.
Comment #1 by k.hara.pg — 2011-02-27T21:31:26Z
Following patch fixes this bug:
std/algorithm.d | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/std/algorithm.d b/std/algorithm.d
index 0a1e496..ed05c85 100644
--- a/std/algorithm.d
+++ b/std/algorithm.d
@@ -1057,11 +1057,11 @@ void move(T)(ref T source, ref T target)
{
// Most complicated case. Destroy whatever target had in it
// and bitblast source over it
- static if (is(typeof(target.__dtor()))) target.__dtor();
+ static if (hasElaborateDestructor!T) typeid(T).destroy(&target);
memcpy(&target, &source, T.sizeof);
// If the source defines a destructor or a postblit hook, we must obliterate the
// object in order to avoid double freeing and undue aliasing
- static if (is(typeof(source.__dtor())) || is(typeof(source.__postblit())))
+ static if (hasElaborateDestructor!T || hasElaborateCopyConstructor!T)
{
static T empty;
memcpy(&source, &empty, T.sizeof);