From 1cc4d143f3016bac2415be840500b0f68b872113 Mon Sep 17 00:00:00 2001 From: Martin Nowak Date: Fri, 25 Jan 2013 12:57:34 +0100 Subject: [PATCH] check for postblit and opAssign in emplace - use memcpy & postblit if emplacing same type - initialize memory if hasElaborateAssign!T is true --- std/conv.d | 51 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 2 deletions(-) diff --git a/std/conv.d b/std/conv.d index 1f67ce8574a..90b7e19c4b6 100644 --- a/std/conv.d +++ b/std/conv.d @@ -3551,8 +3551,18 @@ T* emplace(T, Args...)(T* chunk, auto ref Args args) { static assert(Args.length == 1); //static assert(0, T.stringof ~ " " ~ Args.stringof); - // initialize(); - *chunk = args[0]; + static if (is(T == Args[0])) + { + memcpy(chunk, &args[0], T.sizeof); + static if (hasElaborateCopyConstructor!T) + chunk.__postblit(); + } + else + { + static if (hasElaborateAssign!T) + initialize(); + *chunk = args[0]; + } } return chunk; } @@ -3579,6 +3589,43 @@ unittest assert(*emplace!S(cast(S*) s1, 44, 45) == S(44, 45)); } +unittest +{ + static struct Postblit + { + this(this) + { + if (ptr) ++*ptr; + } + size_t* ptr; + } + + // fake uninitialized memory + Postblit mem = Postblit(cast(size_t*)0x1); + auto p = new size_t; + emplace(&mem, Postblit(p)); + assert(mem.ptr == p && *p == 1); +} + +unittest +{ + static struct Assign + { + void opAssign(Assign rhs) + { + if (ptr && rhs.ptr) *ptr = *rhs.ptr; + else ptr = rhs.ptr; + } + size_t* ptr; + } + + // fake uninitialized memory + Assign mem = Assign(cast(size_t*)0x1); + auto p = new size_t; + emplace(&mem, Assign(p)); + assert(mem.ptr == p); +} + unittest { __conv_EmplaceTest k = void;