When is copy assignment @safe to use when the left-hand-side is an undefined l-value?

Nordlöw per.nordlow at gmail.com
Sat Mar 17 02:09:40 UTC 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");
     }
}



More information about the Digitalmars-d-learn mailing list