Delphi introduced record helper for built-in types a while ago (XE3).

These record helpers are much more powerful than you’d expect.

I found this out when I needed to hide some complex bit manipulation behind record helpers.

My real code involves lots of complex bit manipulation and partial population counts, but I’d like to use a simple example to demonstrate.

Suppose we have a int64 that holds 1 bit for every square on a checker board. A 1 means there’s a piece and a 0 means there’s no piece.

We can also keep track of just the white or just the black pieces and the combination of both.

unit Example; interface uses System.Types; type TPiece = type int64; TPieces = type TPiece; TCollision = type TPieces; TCollisionHelper = record helper for TCollision function IsHit(Piece: TPiece): boolean; overload; class function IsHit(White, Black: TPieces): TCollision; overload; static; function Count: integer; inline; end; TPiecesHelper = record helper for TPieces public function Count: integer; inline; //popcount private class function GetCount(Field: Int64): integer; static; end; TWhitePiece = type TPiece; TWhitePieceHelper = record helper for TWhitePiece procedure MoveTo(From, &To: TPoint); function CanJump: boolean; inline; end; TBlackPiece = type TPiece; TBlackPieceHelper = record helper for TBlackPiece procedure MoveByOne(From: TPoint; Direction: TDirection); function CanJump: boolean; inline; end; procedure Test; implementation uses System.SysUtils, System.Classes; { TCollisionHelper } function TCollisionHelper.IsHit(Piece: TPiece): boolean; begin Result:= (self and Piece) <> 0; end; function TCollisionHelper.Count: integer; begin Result:= TPieces.GetCount(Self); end; class function TCollisionHelper.IsHit(White, Black: TPieces): TCollision; begin Result:= White and Black; end; class function TPiecesHelper.GetCount(Field: Int64): integer; asm {$ifdef CPUX86} popcnt eax,eax popcnt edx,edx add eax,edx {$endif} {$ifdef CPUX64} popcnt rax,rcx {$endif} end; { TPiecesHelper } function TPiecesHelper.Count: integer; begin Result:= GetCount(Self); end; { TWhitePieceHelper } procedure TWhitePieceHelper.MoveTo(From, &To: TPoint); begin writeln('white moves'); end; function TWhitePieceHelper.CanJump: boolean; begin Result:= true; end; { TBlackPieceHelper } procedure TBlackPieceHelper.MoveByOne(From: TPoint; Direction: TDirection); begin writeln('black slides'); end; function TBlackPieceHelper.CanJump: boolean; begin Result:= false; end; procedure Test; var White, Black: TPieces; PieceA: TPiece; Clashes: TCollision; begin White:= Random(Int64.MaxValue); Black:= not(White); Clashes:= TCollision.IsHit(Black, White); Clashes.Count; end; end.

Why not use (enhanced) records?

The problem with records is that all the normal operators (or/xor+/-) don’t work out of the box. With plain types + helpers you get a little of both worlds.

I haven’t found a way to get proper inheritance; it is so close. I wish Embarcadero would get enhanced helpers done already.