1 static assert(!hasComplexCopying!int); 2 static assert(!hasComplexCopying!real); 3 static assert(!hasComplexCopying!string); 4 static assert(!hasComplexCopying!(int[])); 5 static assert(!hasComplexCopying!(int[42])); 6 static assert(!hasComplexCopying!(int[string])); 7 static assert(!hasComplexCopying!Object); 8 9 static struct NoCopyCtor1 10 { 11 int i; 12 } 13 static assert(!hasComplexCopying!NoCopyCtor1); 14 static assert(!__traits(hasCopyConstructor, NoCopyCtor1)); 15 static assert(!__traits(hasPostblit, NoCopyCtor1)); 16 17 static struct NoCopyCtor2 18 { 19 int i; 20 21 this(int i) 22 { 23 this.i = i; 24 } 25 } 26 static assert(!hasComplexCopying!NoCopyCtor2); 27 static assert(!__traits(hasCopyConstructor, NoCopyCtor2)); 28 static assert(!__traits(hasPostblit, NoCopyCtor2)); 29 30 struct HasCopyCtor 31 { 32 this(ref HasCopyCtor) 33 { 34 } 35 } 36 static assert( hasComplexCopying!HasCopyCtor); 37 static assert( __traits(hasCopyConstructor, HasCopyCtor)); 38 static assert(!__traits(hasPostblit, HasCopyCtor)); 39 40 // hasComplexCopying does not take constness into account. 41 // Code that wants to check whether copying works will need to test 42 // __traits(isCopyable, T) or test that copying compiles. 43 static assert( hasComplexCopying!(const HasCopyCtor)); 44 static assert( __traits(hasCopyConstructor, const HasCopyCtor)); 45 static assert(!__traits(hasPostblit, const HasCopyCtor)); 46 static assert(!__traits(isCopyable, const HasCopyCtor)); 47 static assert(!__traits(compiles, { const HasCopyCtor h; 48 auto h2 = h; })); 49 static assert(!is(typeof({ const HasCopyCtor h1; 50 auto h2 = h1; }))); 51 52 // An rvalue constructor is not a copy constructor. 53 struct HasRValueCtor 54 { 55 this(HasRValueCtor) 56 { 57 } 58 } 59 static assert(!hasComplexCopying!HasRValueCtor); 60 static assert(!__traits(hasCopyConstructor, HasRValueCtor)); 61 static assert(!__traits(hasPostblit, HasRValueCtor)); 62 63 struct HasPostblit 64 { 65 this(this) 66 { 67 } 68 } 69 static assert( hasComplexCopying!HasPostblit); 70 static assert(!__traits(hasCopyConstructor, HasPostblit)); 71 static assert( __traits(hasPostblit, HasPostblit)); 72 73 // The compiler will generate a copy constructor if a member variable 74 // has one. 75 static struct HasMemberWithCopyCtor 76 { 77 HasCopyCtor s; 78 } 79 static assert( hasComplexCopying!HasMemberWithCopyCtor); 80 81 // The compiler will generate a postblit constructor if a member variable 82 // has one. 83 static struct HasMemberWithPostblit 84 { 85 HasPostblit s; 86 } 87 static assert( hasComplexCopying!HasMemberWithPostblit); 88 89 // If a struct has @disabled copying, hasComplexCopying is still true. 90 // Code that wants to check whether copying works will need to test 91 // __traits(isCopyable, T) or test that copying compiles. 92 static struct DisabledCopying 93 { 94 @disable this(this); 95 @disable this(ref DisabledCopying); 96 } 97 static assert( hasComplexCopying!DisabledCopying); 98 static assert(!__traits(isCopyable, DisabledCopying)); 99 static assert(!__traits(compiles, { DisabledCopying dc1; 100 auto dc2 = dc1; })); 101 static assert(!is(typeof({ DisabledCopying dc1; 102 auto dc2 = dc1; }))); 103 104 // Static arrays have complex copying if their elements do. 105 static assert( hasComplexCopying!(HasCopyCtor[1])); 106 static assert( hasComplexCopying!(HasPostblit[1])); 107 108 // Static arrays with no elements do not have complex copying, because 109 // there's nothing to copy. 110 static assert(!hasComplexCopying!(HasCopyCtor[0])); 111 static assert(!hasComplexCopying!(HasPostblit[0])); 112 113 // Dynamic arrays do not have complex copying, because copying them 114 // just slices them rather than copying their elements. 115 static assert(!hasComplexCopying!(HasCopyCtor[])); 116 static assert(!hasComplexCopying!(HasPostblit[])); 117 118 // Classes and unions do not have complex copying even if they have 119 // members which do. 120 class C 121 { 122 HasCopyCtor s; 123 } 124 static assert(!hasComplexCopying!C); 125 126 union U 127 { 128 HasCopyCtor s; 129 } 130 static assert(!hasComplexCopying!U); 131 132 // https://issues.dlang.org/show_bug.cgi?id=24833 133 // This static assertion fails, because the compiler 134 // currently ignores assignment operators for enum types. 135 enum E : HasCopyCtor { a = HasCopyCtor.init } 136 //static assert( hasComplexCopying!E);
Whether copying an object of the given type involves either a user-defined copy / postblit constructor or a compiler-generated copy / postblit constructor rather than using the default copying behavior (which would use memcpy).
The compiler will generate a copy / postblit constructor for a struct when a member variable of that struct defines a copy / postblit constructor.
Note that hasComplexCopying is also true for static arrays whose element type has a copy constructor or postblit constructor, since while the static array itself does not have a copy constructor or postblit constructor, the compiler must use the copy / postblit constructor of the elements when copying the static array.
Due to https://issues.dlang.org/show_bug.cgi?id=24833, enums never have complex copying even if their base type does. Their copy / postblit constructor is never called, resulting in incorrect behavior for such enums. So, because the compiler does not treat them as having complex copying, hasComplexCopying is false for them.
No other types (including class references, pointers, and unions) ever have a copy constructor or postblit constructor and thus hasComplexCopying is never true for them. It is particularly important to note that unions never have a copy constructor or postblit constructor, so if a struct contains a union which contains one or more members which have a copy constructor or postblit constructor, that struct will have to have a user-defined copy constructor or posthblit constructor which explicitly copies the correct member of the union if you don't want the current value of the union to simply be memcopied when copying the struct.
If a particular piece of code cares about the existence of a copy constructor or postblit constructor specifically rather than if a type has one or the other, the traits __traits(hasCopyConstructor, T) and __traits(hasPostblit, T) can be used, though note that they will not be true for static arrays.