如何将整数常量作为泛型参数传递

时间:2018-04-02 12:16:50

标签: delphi generics

我需要传递一个整数常量作为泛型参数。例如,这里是一个使用非标准浮点数(float16)的代码(代码取自githab并稍加修改):

const 
  ES = 5;  // exponent size (bits)
  MS = 10; // mantissa size (bits)
           // plus sign (1 bit)
  ESMS = ES + MS;

function FloatXXToSingle(const _in: cardinal): Single;
var
  t1, t2, t3: cardinal;
begin
  t1 := _in and (Cardinal(1 shl ESMS) - 1);               // Non-sign bits
  t2 := _in and (1 shl ESMS);                   // Sign bit
  t3 := _in and ((1 shl ES - 1) shl MS);        // Exponent

  t1 := t1 shl (23 - MS);                       // Align mantissa on MSB
  t2 := t2 shl (31 - ESMS);                     // Shift sign bit into position

  t1 := t1 + cardinal((127-(1 shl (ES-1)-1)) shl 23);   // Adjust bias

  if t3 = 0 then                                // Denormals-as-zero
    t1 := 0;

  t1 := t1 or t2;                               // Re-insert sign bit

  pCardinal(@Result)^ := t1;
end;

我想在它的基础上创建一个泛型,这样我就可以自己设置指数和尾数的位数。 现在我做这样的事情:

type
  TFloat<TES, TMS> = class
    const ES = sizeof(TES);
    const MS = sizeof(TMS);
    const ESMS = ES + MS;
    class function ToSingle(const _in: cardinal): Single;
  end;

class function TFloat<TES, TMS>.ToSingle(const _in: cardinal): Single;
var
  t1, t2, t3: cardinal;
begin
  t1 := _in and (Cardinal(1 shl ESMS) - 1);               // Non-sign bits
  t2 := _in and (1 shl ESMS);                   // Sign bit
  t3 := _in and ((1 shl ES - 1) shl MS);        // Exponent

  t1 := t1 shl (23 - MS);                       // Align mantissa on MSB
  t2 := t2 shl (31 - ESMS);                     // Shift sign bit into position

  t1 := t1 + cardinal((127-(1 shl (ES-1)-1)) shl 23);   // Adjust bias

  if t3 = 0 then                                // Denormals-as-zero
    t1 := 0;

  t1 := t1 or t2;                               // Re-insert sign bit

  pCardinal(@Result)^ := t1;
end;

但是要使用它,我必须写这样的东西:

type
  TMyFloat = TFloat<packed record a:Integer; b:Byte; end, packed record a: Extended; end>;

begin
  writeln(TMyFloat.ToSingle($1234));
end.

但这种方法并不优雅。也许有一种方法可以直接将两个数字传递给泛型:指数的大小和尾数?

0 个答案:

没有答案