std.variant unions cannot have postblit or destructors

This commit is contained in:
Walter Bright 2014-11-15 15:04:57 -08:00
parent b049c00bbe
commit 196ef0c7a5

View file

@ -779,13 +779,22 @@ public:
@property T get(T)() if (!is(T == const))
{
union Buf
{
TypeInfo info;
T result;
}
auto p = *cast(T**) &store;
Buf buf = { typeid(T) };
/* handler(OpID.get, ) expects the TypeInfo for T in the same buffer it
* writes the result to afterwards. Because T might have a non-trivial
* destructor, postblit or invariant, we cannot use a union.
*/
struct Buf
{
T result;
// Make sure Buf.sizeof is big enough to store a TypeInfo in
void[T.sizeof < TypeInfo.sizeof ? TypeInfo.sizeof - T.sizeof : 0] init = void;
}
TypeInfo info = typeid(T);
Buf buf;
memcpy(&buf, &info, info.sizeof);
if (fptr(OpID.get, &store, &buf))
{
throw new VariantException(type, typeid(T));
@ -795,16 +804,26 @@ public:
@property T get(T)() const if (is(T == const))
{
union Buf
auto p = *cast(T**) &store;
/* handler(OpID.get, ) expects the TypeInfo for T in the same buffer it
* writes the result to afterwards. Because T might have a non-trivial
* destructor, postblit or invariant, we cannot use a union.
*/
struct Buf
{
TypeInfo info;
static if (is(T == shared))
shared(Unqual!T) result;
else
Unqual!T result;
// Make sure Buf.sizeof is big enough to store a TypeInfo in
void[T.sizeof < TypeInfo.sizeof ? TypeInfo.sizeof - T.sizeof : 0] init = void;
}
auto p = *cast(T**) &store;
Buf buf = { typeid(T) };
TypeInfo info = typeid(T);
Buf buf;
memcpy(&buf, &info, info.sizeof);
if (fptr(OpID.get, cast(ubyte[size]*) &store, &buf))
{
throw new VariantException(type, typeid(T));