[教程]使用泛型为 Delphi 提供一个位运算的模板支持

说起来,Delphi 自 2009 引和泛型已经很长时间了,而 Delphi 缺少位域也已经更久远了,早在远古之前……,扯远了:)

新版的 Delphi 提供了一个类,名字叫 TBits,好吧,顾名思意,可是为什么是类呀?这意味着我们没法像C++一样将它嵌入到结构体里,如果你能,你就上天了@

好吧,为了实现这一目的,本着为了人类和平的思想,所以提供了 TQBits 的模板封装,几句代码:

首先看声明:

TQBits < T >= record //
private
var
  Data: T;
public
  function GetBit(const AIndex: Integer): Boolean;inline;
  procedure SetBit(const AIndex: Integer; const Value: Boolean);inline;
  property Bits[const AIndex: Integer]: Boolean read GetBit write SetBit;default;
end;

接下来看实现:

{ TQBits<T> }

function TQBits<T>.GetBit(const AIndex: Integer): Boolean;
begin
  Result := (PByte(@Data)[AIndex shr 3] and (1 shl (AIndex and $7))) <> 0;
end;

procedure TQBits<T>.SetBit(const AIndex: Integer; const Value: Boolean);
var
  p: PByte;
begin
  p := PByte(IntPtr(@Data) + (AIndex shr 3));
  if Value then
    p^ := p^ or (1 shl (AIndex and $7))
  else
    p^ := p^ and (not(1 shl (AIndex and $7)));
end;

最后当然是测试用例:

procedure Test;
var
  B8:TQBits<Byte>;
  B16:TQBits<Word>;
  B24:TQBits<array[0..2] of Byte>;
  B32:TQBits<Integer>;
begin
  B8.Data:=0;
  B8[0]:=true;
  B8[7]:=true;
  assert(Sizeof(B8)=1);
  B16.Data:=0;
  B16[8]:=true;
  assert(SizeOf(B16)=2);
  FillChar(B24,SizeOf(B24),0);
  B24[23]:=true;
  assert(SizeOf(B24)=3);
  B32.Data:=0;
  B32[31]:=true;
  assert(SizeOf(B32)=4);
end;

蛋扯完了,大家有媳妇抱媳妇,没媳妇抱大腿去吧。这个例子实际上演示的还有另一个目的,就是给大家提供下泛型使用的另一种思路,正常 Delphi 中的泛型类型支持能力实在是有限,但我们可以在实现的时候,将其类型具体化,取地址,转类型指针,然后再操作。看不懂的就算了,扯乎~~~

分享到: