What Baltasar offers will compile, but not do what you want. marriageDate and divorceDate will overlap, and writing to one of them will also change the other, as they simply have the same address.
But in this case, there is no good reason to write the option.
Why not just:
type maritalStates = (single, married, widowed, divorced); TPerson = record name: record first, middle, last: string; end; sex: (male, female); dob: TDateTime; maritalStatus: maritalStates; // single, married, widowed, divorced marriageDate: TDateTime; // married, widowed, divorced divorceDate : TDateTime; // divorced isFirstDivorce: boolean; // divorced end;
Use and layout is exactly what you need. If the field is not applicable (for example, marriageDate for single or divorceDate for married ), you simply do not use it.
This is the same as with the recording option. There you also set only the fields that apply. Please note that the compiler or runtime does not prevent you from writing in the wrong field of the recording option in any case, that is, in the recording option, if the status is single , you can still write or read from divorceDate , even if it makes no sense.
If you want to distinguish several different settings, just do it in the comments and forget the recording option, you do not need it here. Now you can do:
var P: TPerson; begin P.name.first := 'Bob'; P.name.middle := 'The'; P.name.last := 'Builder'; P.sex := male; P.dob := StrToDate('05/05/1980'); P.maritalStatus := divorced; P.marriageDate := StrToDate('04/01/2013'); P.divorceDate := StrToDate('04/02/2016'); P.isFirstDivorce := True;
Update
Just to show that there is no need to do this recording option,
I will post my Project62.dpr, which shows exactly the same offsets for the corresponding fields and the same record sizes:
program Project62; {$APPTYPE CONSOLE} {$R *.res} uses System.SysUtils; type maritalStates = (single, married, widowed, divorced); tsex = (male, female); // No variant part PPerson = ^TPerson; TPerson = record name: record first, middle, last: string; end; sex: tsex; dob: TDateTime; maritalStatus: maritalStates; // single, married, widowed, divorced marriageDate: TDateTime; // married, widowed, divorced divorceDate : TDateTime; // divorced isFirstDivorceDate: boolean; // divorced end; // Variant part like tonypdmtr record PPerson2 = ^TPerson2; TPerson2 = record name: record first, middle, last: string; end; sex: tsex; dob: TDateTime; case maritalStatus: maritalStates of single: (); widowed: (w: record marriageDate: TDateTime; end); // overlaps with m.marriageDate and d.marriageDate married: (m: record marriageDate: TDateTime; end); // overlaps with w.marriageDate and d.marriageDate divorced: (d: record marriageDate: TDateTime; // overlaps with w.marriageDate and m.marriageDate divorceDate: TDateTime; // same offset as in my non-variant version isFirstDivorceDate: Boolean // same offset as in my non-variant version end); end; begin try Writeln('TPerson: size = ', Sizeof(TPerson)); Writeln('TPerson.maritalStatus: offset = ', NativeUInt(@PPerson(nil)^.maritalStatus)); Writeln('TPerson.marriageDate: offset = ', NativeUInt(@PPerson(nil)^.marriageDate)); Writeln('TPerson.divorceDate: offset = ', NativeUInt(@PPerson(nil)^.divorceDate)); Writeln('TPerson.isFirstDivorceDate: offset = ', NativeUInt(@PPerson(nil)^.isFirstDivorceDate)); Writeln; Writeln('TPerson2: size = ', Sizeof(TPerson2)); Writeln('TPerson2.maritalStatus: offset = ', NativeUInt(@PPerson2(nil)^.maritalStatus)); Writeln('TPerson2.w.marriageDate: offset = ', NativeUInt(@PPerson2(nil)^.w.marriageDate)); Writeln('TPerson2.m.marriageDate: offset = ', NativeUInt(@PPerson2(nil)^.m.marriageDate)); Writeln('TPerson2.d.marriageDate: offset = ', NativeUInt(@PPerson2(nil)^.d.marriageDate)); Writeln('TPerson2.d.divorceDate: offset = ', NativeUInt(@PPerson2(nil)^.d.divorceDate)); Writeln('TPerson2.d.isFirstDivorceDate: offset = ', NativeUInt(@PPerson2(nil)^.d.isFirstDivorceDate)); except on E: Exception do Writeln(E.ClassName, ': ', E.Message); end; Readln; end.
Output (on Windows):
TPerson: size = 56 TPerson.maritalStatus: offset = 24 TPerson.marriageDate: offset = 32 TPerson.divorceDate: offset = 40 TPerson.isFirstDivorceDate: offset = 48 TPerson2: size = 56 TPerson2.maritalStatus: offset = 24 TPerson2.w.marriageDate: offset = 32 TPerson2.m.marriageDate: offset = 32 TPerson2.d.marriageDate: offset = 32 TPerson2.d.divorceDate: offset = 40 TPerson2.d.isFirstDivorceDate: offset = 48
A 32-bit layout can be placed on a simple diagram:
00 TPerson: [name.first] TPerson2: [name.first] 04 [name.middle] [name.middle] 08 [name.last] [name.last] 12 [sex] [sex] 16 [dob] [dob] 24 [maritalStatus] [maritalStatus] 32 [marriageDate] [w.marriageDate] [m.marriageDate] [d.marriageDate] 40 [divorceDate] [d.divorceDate] 48 [isFirstDivorceDate] [d.isFirstDivorceDate]