type
TEmptyOptional = record;
{ TOptional }
TOptional<T> = record
public type
PT = ^T;
private
FHasValue: Boolean;
FValue: T;
class operator Initialize(var a: TOptional<T>);
public
constructor Create(constref AValue: T);
function ValuePtr: PT; inline;
function Value: T; inline;
function GetOrDefault(constref def: T): T;
class operator Implicit(constref AValue: T): TOptional<T>; inline;
class operator Explicit(constref AValue: T): TOptional<T>; inline;
class operator Implicit(constref AValue: TEmptyOptional): TOptional<T>; inline;
class operator Explicit(constref AValue: TEmptyOptional): TOptional<T>; inline;
class operator Implicit(constref opt: TOptional<T>): Boolean; inline;
class operator Explicit(constref opt: TOptional<T>): Boolean; inline;
class operator LogicalNot(constref opt: TOptional<T>): Boolean; inline;
property HasValue: Boolean read FHasValue;
class function Empty: TOptional<T>; static; inline;
end;
function EmptyOptional: TEmptyOptional; inline;
implementation
{ TOptional }
class operator TOptional<T>.Initialize(var a: TOptional<T>);
begin
a.FHasValue := False;
end;
constructor TOptional<T>.Create(constref AValue: T);
begin
FHasValue := True;
FValue := AValue;
end;
function TOptional<T>.ValuePtr: PT;
begin
If not HasValue then
raise ENoValuePresentException.Create('Trying to access value of an empty optional');
Result := @FValue;
end;
function TOptional<T>.Value: T;
begin
If not HasValue then
raise ENoValuePresentException.Create('Trying to access value of an empty optional');
Result := FValue;
end;
function TOptional<T>.GetOrDefault(constref def: T): T;
begin
If HasValue then
Result := FValue
else
Result := def;
end;
class operator TOptional<T>.Implicit(constref AValue: T): TOptional<T>;
begin
Result.FHasValue := True;
Result.FValue := AValue;
end;
class operator TOptional<T>.Explicit(constref AValue: T): TOptional<T>;
begin
Result.FHasValue := True;
Result.FValue := AValue;
end;
class operator TOptional<T>.Implicit(constref AValue: TEmptyOptional): TOptional
<T>;
begin
Result.FHasValue := False;
end;
class operator TOptional<T>.Explicit(constref AValue: TEmptyOptional): TOptional
<T>;
begin
Result.FHasValue := False;
end;
class operator TOptional<T>.Implicit(constref opt: TOptional<T>): Boolean;
begin
Result := opt.HasValue;
end;
class operator TOptional<T>.Explicit(constref opt: TOptional<T>): Boolean;
begin
Result := opt.HasValue;
end;
class operator TOptional<T>.LogicalNot(constref opt: TOptional<T>): Boolean;
begin
Result := not opt.HasValue;
end;
class function TOptional<T>.Empty: TOptional<T>;
begin
Result.FHasValue := False;
end;
function EmptyOptional: TEmptyOptional;
begin
// Nothing to do here
end;