March 17, 2018
Given an uninitialized (undefined content from, for instance, malloc) value `x` of type `T`, when is it @safe to initalize `x` with a simple assignment such as

    x = y

in contrast to

    emplace(&x, y);

?

My current guess is when

    hasElaborateCopyConstructor!T

is `false`. Is this always correct?

I'm asking because I want the following function to work correctly for all types including default-uncopyable container types (that require explicit call to .dup)

private static void duplicateEmplace(T)(const scope ref T src,
                                        scope ref T dst) @system
{
    import std.conv : emplace;
    import std.traits : hasElaborateCopyConstructor, isCopyable, isBasicType;
    static if (!hasElaborateCopyConstructor!T)
    {
        import std.traits : isInstanceOf;
        static if (is(T == class) ||
                   is(T == string))
        {
            dst = cast(T)src;
        }
        else static if (isBasicType!T ||
                        isInstanceOf!(Nullable, T)) // `Nullable` types cannot be emplaced
        {
            dst = src;
        }
        else
        {
            emplace(&dst, cast(Unqual!T)src);
        }
    }
    else static if (__traits(hasMember, T, "dup"))
    {
        // TODO fix when emplace can handle uncopyable types
        emplace(&dst);
        dst = src.dup;
    }
    else
    {
        static assert(0, T.stringof ~ " is neither copyable or dupable");
    }
}