D-Programming-Language/phobos — pull request #911 by monarchdodra (2012-10-30 12:24:46+00:00)
Title: emplace!struct should not use opAssign

Second attempt to fix an issue where emplace was using opAssign:
1. emplace was calling opAssign directly, without T.init'ing the payload first.
2. emplace should not use opAssign at all anyways.
3. Now correctly bypasses issue 8847

Now supports emplacement for @disabled this object, *provided* arguments are actually passed.

```D
// Specialization for struct
T* emplace(T, Args...)(T* chunk, auto ref Args args)
if (is(T == struct))
{
auto result = cast(typeof(return)) chunk;

//Copies T.init over destination
//Templated to assert only when actually used
void initialize()(T* dest, size_t size = T.sizeof)
{
static T i = T.init;
memcpy(dest, &i, size);
}

//From std.algorithm.move, but without destroying destination (since it is uninitialized).
void moveOver(ref T source)
{
memcpy(result, &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 (hasElaborateDestructor!T || hasElaborateCopyConstructor!T)
{
static if (T.tupleof[$-1].stringof.endsWith("this"))
{
// Keep original context pointer
initialize(&source, T.sizeof - (void*).sizeof);
}
else
{
initialize(&source);
}
}
}

static if (Args.length == 1 && is(Args[0] == T) &&
ParameterStorageClassTuple!emplace[0] != ParameterStorageClass.ref_ )
{
// Special case for already passed by value and exact type match.
// Move the argument directly (not a copy)
moveOver(args[0]);
}
static if (is(typeof(result.__ctor(args))))
{
// T defines a genuine constructor accepting args
// Go the classic route: write .init first, then call ctor
initialize(result);
result.__ctor(args);
}
else static if (is(typeof(T(args))))
{
// Struct without constructor that has one matching field for
// each argument: This is an agglomerate construction.
T t = T(args);
moveOver(t);
}
else static if (Args.length == 1 && is(Args[0] : T))
{
T t = args[0];
moveOver(t);
}
else
{
//Give up
static assert(0, text("Don't know how to emplace a ", T.stringof, " with ", Args[0].stringof));
}

return result;
}
```