@@ -84,23 +84,84 @@ if (is(UT == core.internal.traits.Unqual!UT))
84
84
emplaceRef! (UT , UT )(chunk, forward! args);
85
85
}
86
86
87
- // emplace helper functions
88
- private nothrow pure @trusted
89
- void emplaceInitializer (T)(scope ref T chunk)
87
+ /+
88
+ Emplaces T.init.
89
+ In contrast to `emplaceRef(chunk)`, there are no checks for disabled default
90
+ constructors etc.
91
+ +/
92
+ void emplaceInitializer (T)(scope ref T chunk) nothrow pure @trusted
93
+ if (! is (T == const ) && ! is (T == immutable ) && ! is (T == inout ))
90
94
{
91
- // Emplace T.init.
92
- // Previously, an immutable static and memcpy were used to hold an initializer.
93
- // With improved unions, this is no longer needed.
94
- union UntypedInit
95
+ import core.internal.traits : hasElaborateAssign;
96
+
97
+ static if (! hasElaborateAssign! T && __traits(compiles, chunk = T.init))
98
+ {
99
+ chunk = T.init;
100
+ }
101
+ else static if (__traits(isZeroInit, T))
102
+ {
103
+ static if (is (T U == shared U))
104
+ alias Unshared = U;
105
+ else
106
+ alias Unshared = T;
107
+
108
+ import core.stdc.string : memset;
109
+ memset(cast (Unshared* ) &chunk, 0 , T.sizeof);
110
+ }
111
+ else
95
112
{
96
- T dummy;
113
+ // emplace T.init (an rvalue) without extra variable (and according destruction)
114
+ alias RawBytes = void [T.sizeof];
115
+
116
+ static union U
117
+ {
118
+ T dummy = T.init; // U.init corresponds to T.init
119
+ RawBytes data;
120
+ }
121
+
122
+ * cast (RawBytes* ) &chunk = U.init.data;
97
123
}
98
- static struct UntypedStorage
124
+ }
125
+
126
+ @safe unittest
127
+ {
128
+ static void testInitializer (T)()
129
+ {
130
+ // mutable T
131
+ {
132
+ T dst = void ;
133
+ emplaceInitializer(dst);
134
+ assert (dst is T.init);
135
+ }
136
+
137
+ // shared T
138
+ {
139
+ shared T dst = void ;
140
+ emplaceInitializer(dst);
141
+ assert (dst is shared (T).init);
142
+ }
143
+
144
+ // const T
145
+ {
146
+ const T dst = void ;
147
+ static assert (! __traits(compiles, emplaceInitializer(dst)));
148
+ }
149
+ }
150
+
151
+ static struct ElaborateAndZero
152
+ {
153
+ int a;
154
+ this (this ) {}
155
+ }
156
+
157
+ static struct ElaborateAndNonZero
99
158
{
100
- align (T.alignof) void [T.sizeof] dummy;
159
+ int a = 42 ;
160
+ this (this ) {}
101
161
}
102
162
103
- () @trusted {
104
- * cast (UntypedStorage* ) &chunk = cast (UntypedStorage) UntypedInit.init;
105
- } ();
163
+ testInitializer! int ();
164
+ testInitializer! double ();
165
+ testInitializer! ElaborateAndZero();
166
+ testInitializer! ElaborateAndNonZero();
106
167
}
0 commit comments