What general restriction do I use for the type of anonymous method?

I would like to declare such a generic entry:

type
  TMyDelegate<T: constraint> = record
  private
    fDelegate: T;
  public
    class operator Implicit(a: T): TMyDelegate;
    class operator Implicit(A: TMyDelegate: T);
  end;

I would like to limit Tto reference to procedure/function. (As much as possible).

I tried this, but it does not compile:

program Project3;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  System.SysUtils;

type

  TProc1 = reference to procedure(a: Integer);
  TProc2 = reference to procedure(b: TObject);

  TTest<T: TProc1, TProc2> = record
  private
    fData: T;
  public
    class operator Implicit(a: T): TTest<T>;
    class operator Implicit(a: TTest<T>): T;
  end;

  { TTest<T> }

class operator TTest<T>.Implicit(a: T): TTest<T>;
begin
  Result.fData:= a;
end;

class operator TTest<T>.Implicit(a: TTest<T>): T;
begin
  Result:= a.fData;
end;

var
  Delegate1: TProc1;
  Delegate2: TProc2;

var
  MyTest1: TTest<TProc1>;  <<-- error
  MyTest2: TTest<TProc2>;

begin
  MyTest1:=
    procedure(a: Integer)
    begin
      WriteLn(IntToStr(a));
    end;
end.

This gives a compilation error:

[dcc32 error] Project3.dpr (39): E2514. A parameter of type "T" must support the interface "TProc2"

Is there a way to limit the generic type (list) of anonymous types?

+4
source share
3 answers

Cannot specify such a restriction. Possible limitations:

  • Type of value.
  • A class derived from a specific ancestor.
  • An interface derived from a specific ancestor.
  • Parametric constructor.

: http://docwiki.embarcadero.com/RADStudio/en/Constraints_in_Generics

, . . . . , , - - .

. ,

T: TProc1, TProc2

, T . . TProc1, TProc2.

+3

- , - :

program Project51;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  System.SysUtils;

type
  TTest<T> = record
  type
    TProcT = reference to procedure(a: T);
  private
    fData: TProcT;
  public
    class operator Implicit(a: TProcT): TTest<T>;
    class operator Implicit(a: TTest<T>): TProcT;
  end;

  { TTest<T> }

class operator TTest<T>.Implicit(a: TProcT): TTest<T>;
begin
  Result.fData:= a;
end;

class operator TTest<T>.Implicit(a: TTest<T>): TProcT;
begin
  Result:= a.fData;
end;

var
  MyTest1: TTest<Integer>;
  MyTest2: TTest<TObject>;

begin
  MyTest1:=
    procedure(a: Integer)
    begin
      WriteLn(IntToStr(a));
    end;
  MyTest2:=
    procedure(a: TObject)
    begin
      WriteLn(a.ClassName);
    end;
end.
+5

GrayMatter David .

, .

The following functions are defined.

TA = reference to procedure(const &In, &Out: TArray<TOmniValue>);
TB = reference to procedure(const &In, &Out: TArray<IOmniBlockingCollection>);
TC = .....

The trick is to override the methods as follows:

program Project3;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  System.SysUtils;

type
  IData<Tin, Tout> = interface
    ['{D2132F82-CAA9-4F90-83A9-9EFD6221ABE2}']
    function GetInput: TArray<TIn>;
    function GetOutput: TArray<Tout>;
  end;

  TData<TIn, TOut> = class(TInterfacedObject, IData<Tin, Tout>)
  private
    fInput: TArray<Tin>;
    fOutput: TArray<Tout>;
  public
    constructor Create(const input: TArray<TIn>; const output: TArray<TOut>);
    function GetInput: TArray<Tin>;
    function GetOutput: TArray<Tout>;
  end;

  TDelegate<Tin, Tout> = reference to procedure(const Data: IData<TIn, TOut>);

{ TSimpleData }

constructor TData<TIn, TOut>.Create(const input: TArray<TIn>;
  const output: TArray<TOut>);
begin
  finput:= input;
  foutput:= output;
end;

function TData<Tin, Tout>.GetInput: TArray<Tin>;
begin
  Result:= fInput;
end;

function TData<Tin, Tout>.GetOutput: TArray<TOut>;
begin
  Result:= fOutput;
end;

var
  IntegerDelegate: TDelegate<Integer, Integer>;
  input, output: TArray<Integer>;
  i: Integer;
  Data: TData<Integer, Integer>;

begin
  IntegerDelegate:= procedure(const Data: IData<Integer, Integer>)
  var
    i: Integer;
    input: TArray<Integer>;
  begin
    input:= Data.GetInput;
    for i:= 0 to High(input) do begin
      Data.GetOutput[i]:= input[i]+10;
    end;
  end;
  SetLength(input,10);
  SetLength(output, Length(input));
  for i:= Low(input) to High(input) do begin
    input[i]:= i;
  end;
  Data:= TData<Integer, Integer>.Create(input, output);
  IntegerDelegate(Data);
  for i in output do Writeln(i);
  Readln;
end.

Now I can limit the delegation to valid types (more or less).

+2
source

All Articles