From 513729bf59b1d10561ceb132d1e6ce5d9dba423e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6nke=20Ludwig?= Date: Mon, 12 Jun 2017 20:43:15 +0200 Subject: [PATCH] Enable proper default initialization. Since @disable this() still leaves an invalid .init open, TaggedAlgebraic.init has now been changed to always contain the .init value of the first specified sub type. Note that this change is restricted to DMD 2.072 and up, because earlier versions of DMD do not allow postblits or destructors within unions and using a union appears to be the only way to implement this. --- source/taggedalgebraic.d | 36 +++++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/source/taggedalgebraic.d b/source/taggedalgebraic.d index d35e0c8..2301ab4 100644 --- a/source/taggedalgebraic.d +++ b/source/taggedalgebraic.d @@ -56,7 +56,16 @@ struct TaggedAlgebraic(U) if (is(U == union) || is(U == struct)) private { - void[Largest!FieldTypes.sizeof] m_data; + static if (is(FieldTypes[0] == typeof(null)) || is(FieldTypes[0] == Void) || __VERSION__ < 2072) { + void[Largest!FieldTypes.sizeof] m_data; + } else { + union Dummy { + FieldTypes[0] initField; + void[Largest!FieldTypes.sizeof] data; + alias data this; + } + Dummy m_data = { initField: FieldTypes[0].init }; + } Kind m_kind; } @@ -556,6 +565,17 @@ unittest { assert(c[0] == "hello"); } +static if (__VERSION__ >= 2072) unittest { // default initialization + struct S { + int i = 42; + } + + union U { S s; int j; } + + TaggedAlgebraic!U ta; + assert(ta.i == 42); +} + /** Tests if the algebraic type stores a value of a certain data type. */ @@ -981,12 +1001,14 @@ private string generateConstructors(U)() string ret; - // disable default construction if first type is not a null/Void type - static if (!is(FieldTypeTuple!U[0] == typeof(null)) && !is(FieldTypeTuple!U[0] == Void)) - { - ret ~= q{ - @disable this(); - }; + static if (__VERSION__ < 2072) { + // disable default construction if first type is not a null/Void type + static if (!is(FieldTypeTuple!U[0] == typeof(null)) && !is(FieldTypeTuple!U[0] == Void)) + { + ret ~= q{ + @disable this(); + }; + } } // normal type constructors