1 module core
.internal
.lifetime
;
3 import core
.lifetime
: forward
;
6 emplaceRef is a package function for druntime internal use. It works like
7 emplace, but takes its argument by ref (as opposed to "by pointer").
8 This makes it easier to use, easier to be safe, and faster in a non-inline
10 Furthermore, emplaceRef optionally takes a type parameter, which specifies
11 the type we want to build. This helps to build qualified objects on mutable
12 buffer, without breaking the type system with unsafe casts.
14 void emplaceRef(T
, UT
, Args
...)(ref UT chunk
, auto ref Args args
)
16 static if (args
.length
== 0)
18 static assert(is(typeof({static T i
;})),
19 "Cannot emplace a " ~ T
.stringof
~ " because " ~ T
.stringof
~
20 ".this() is annotated with @disable.");
21 static if (is(T
== class)) static assert(!__traits(isAbstractClass
, T
),
22 T
.stringof
~ " is abstract and it can't be emplaced");
23 emplaceInitializer(chunk
);
26 !is(T
== struct) && Args
.length
== 1 /* primitives, enums, arrays */
28 Args
.length
== 1 && is(typeof({T t
= forward
!(args
[0]);})) /* conversions */
30 is(typeof(T(forward
!args
))) /* general constructors */)
35 this()(auto ref Args args
)
37 static if (__traits(compiles
, payload
= forward
!args
))
38 payload
= forward
!args
;
40 payload
= T(forward
!args
);
45 static if (__traits(compiles
, chunk
= T(forward
!args
)))
46 chunk
= T(forward
!args
);
47 else static if (args
.length
== 1 && __traits(compiles
, chunk
= forward
!(args
[0])))
48 chunk
= forward
!(args
[0]);
49 else assert(0, "CTFE emplace doesn't support "
50 ~ T
.stringof
~ " from " ~ Args
.stringof
);
54 S
* p
= () @trusted { return cast(S
*) &chunk
; }();
55 static if (UT
.sizeof
> 0)
56 emplaceInitializer(*p
);
57 p
.__ctor(forward
!args
);
60 else static if (is(typeof(chunk
.__ctor(forward
!args
))))
62 // This catches the rare case of local types that keep a frame pointer
63 emplaceInitializer(chunk
);
64 chunk
.__ctor(forward
!args
);
68 //We can't emplace. Try to diagnose a disabled postblit.
69 static assert(!(Args
.length
== 1 && is(Args
[0] : T
)),
70 "Cannot emplace a " ~ T
.stringof
~ " because " ~ T
.stringof
~
71 ".this(this) is annotated with @disable.");
75 T
.stringof
~ " cannot be emplaced from " ~ Args
[].stringof
~ ".");
80 static import core
.internal
.traits
;
81 void emplaceRef(UT
, Args
...)(ref UT chunk
, auto ref Args args
)
82 if (is(UT
== core
.internal
.traits
.Unqual
!UT
))
84 emplaceRef
!(UT
, UT
)(chunk
, forward
!args
);
89 In contrast to `emplaceRef(chunk)`, there are no checks for disabled default
92 void emplaceInitializer(T
)(scope ref T chunk
) nothrow pure @trusted
93 if (!is(T
== const) && !is(T
== immutable) && !is(T
== inout))
95 import core
.internal
.traits
: hasElaborateAssign
;
97 static if (__traits(isZeroInit
, T
))
99 import core
.stdc
.string
: memset
;
100 memset(cast(void*) &chunk
, 0, T
.sizeof
);
102 else static if (__traits(isScalar
, T
) ||
103 T
.sizeof
<= 16 && !hasElaborateAssign
!T
&& __traits(compiles
, (){ T chunk
; chunk
= T
.init
; }))
107 else static if (__traits(isStaticArray
, T
))
109 // For static arrays there is no initializer symbol created. Instead, we emplace elements one-by-one.
110 foreach (i
; 0 .. T
.length
)
112 emplaceInitializer(chunk
[i
]);
117 import core
.stdc
.string
: memcpy
;
118 const initializer
= __traits(initSymbol
, T
);
119 memcpy(cast(void*)&chunk
, initializer
.ptr
, initializer
.length
);
125 static void testInitializer(T
)()
130 emplaceInitializer(dst
);
131 assert(dst
is T
.init
);
137 emplaceInitializer(dst
);
138 assert(dst
is shared(T
).init
);
144 static assert(!__traits(compiles
, emplaceInitializer(dst
)));
148 static struct ElaborateAndZero
154 static struct ElaborateAndNonZero
160 static union LargeNonZeroUnion
165 testInitializer
!int();
166 testInitializer
!double();
167 testInitializer
!ElaborateAndZero();
168 testInitializer
!ElaborateAndNonZero();
169 testInitializer
!LargeNonZeroUnion();
171 static if (is(__vector(double[4])))
173 // DMD 2.096 and GDC 11.1 can't compare vectors with `is` so can't use
175 enum VE
: __vector(double[4])
177 a
= [1.0, 2.0, 3.0, double.nan
],
178 b
= [4.0, 5.0, 6.0, double.nan
],
180 const VE expected
= VE
.a
;
182 shared VE sharedDst
= VE
.b
;
183 emplaceInitializer(dst
);
184 emplaceInitializer(sharedDst
);
186 import core
.stdc
.string
: memcmp
;
187 assert(memcmp(&expected
, &dst
, VE
.sizeof
) == 0);
188 assert(memcmp(&expected
, cast(void*) &sharedDst
, VE
.sizeof
) == 0);
190 static assert(!__traits(compiles
, emplaceInitializer(expected
)));
195 Simple swap function.
197 void swap(T
)(ref T lhs
, ref T rhs
)
199 import core
.lifetime
: move
, moveEmplace
;
202 moveEmplace(rhs
, lhs
);
203 moveEmplace(tmp
, rhs
);