program NestedVariantRecord;
{$mode objfpc}{$H+}{$J-} // Enable ObjFPC mode and Ansistrings
uses
SysUtils; // BoolToStr
type
// 1. Define the tag (discriminator) enum
TShapeType = (stCircle, stRectangle);
// 2. Define specific nested sub-records
TCircle = record
Radius: Single;
end;
TRectangle = record
Width: Single;
Height: Single;
end;
// 3. Define nested metadata record
TMetadata = record
Name: string;
IsActive: Boolean;
end;
// 4. Main record containing nested fields and a variant part (union)
TShape = record
ID: Integer;
Metadata: TMetadata;
// Variant record (union) — must be the last part of the record
case ShapeType: TShapeType of
stCircle: (Circle: TCircle);
stRectangle: (Rectangle: TRectangle);
end;
(**
* Safely accesses and prints items from nested variant records.
* Uses 'const' to pass by reference efficiently without pointers.
*)
procedure PrintShapeProperties(const AShape: TShape);
begin
// Access nested fields using direct dot notation
WriteLn('Shape ID: ', AShape.ID);
WriteLn('Shape Name: ', AShape.Metadata.Name);
WriteLn('Status: ', BoolToStr(AShape.Metadata.IsActive, 'Active', 'Inactive'));
// Switch on the tag field to safely read the active variant branch
case AShape.ShapeType of
stCircle:
begin
WriteLn('Type: Circle');
WriteLn('Radius: ', AShape.Circle.Radius:0:2);
end;
stRectangle:
begin
WriteLn('Type: Rectangle');
WriteLn('Width: ', AShape.Rectangle.Width:0:2,
', Height: ', AShape.Rectangle.Height:0:2);
end;
end;
WriteLn('------------------------------------');
end;
var
MyCircle, MyRectangle: TShape;
begin
// Initialize Circle
MyCircle.ID := 101;
MyCircle.Metadata.Name := 'Unit Circle';
MyCircle.Metadata.IsActive := True;
MyCircle.ShapeType := stCircle;
MyCircle.Circle.Radius := 5.5;
// Initialize Rectangle
MyRectangle.ID := 102;
MyRectangle.Metadata.Name := 'Bounding Box';
MyRectangle.Metadata.IsActive := False;
MyRectangle.ShapeType := stRectangle;
MyRectangle.Rectangle.Width := 10.0;
MyRectangle.Rectangle.Height := 20.0;
// Print properties
PrintShapeProperties(MyCircle);
PrintShapeProperties(MyRectangle);
end.
{
run:
Shape ID: 101
Shape Name: Unit Circle
Status: Active
Type: Circle
Radius: 5.50
------------------------------------
Shape ID: 102
Shape Name: Bounding Box
Status: Inactive
Type: Rectangle
Width: 10.00, Height: 20.00
------------------------------------
}