View Issue Details

IDProjectCategoryView StatusLast Update
0037017FPCCompilerpublic2020-05-06 15:12
ReporterBlackShark Assigned ToSven Barth  
PrioritynormalSeverityminorReproducibilityalways
Status resolvedResolutionduplicate 
Product Version3.0.4 
Summary0037017: Generics
DescriptionFPCTestGenerics.lpr(19,51) Error: Identifier not found "T"
Steps To Reproduceprogram FPCTestGenerics;

{$mode delphi}

type

  { TItemHolderTemplate<T> }

  TItemHolderTemplate<T> = class
  private
    FItem: T;
  public
    constructor Create(AItem: T); virtual;
    property Item: T read FItem;
  end;

  { TItemsFactoryTemplate<T; H: TItemHolderTemplate<T>> }

  TItemsFactoryTemplate<T; H: TItemHolderTemplate<T>> = class //<---FPCTestGenerics.lpr(19,51) Error: Identifier not found "T"
  private

  public
    function CreateItemHolder(const Item: T): TItemHolderTemplate<T>;
  end;

  { TItemHolderTemplate }

  constructor TItemHolderTemplate<T>.Create(AItem: T);
  begin
    FItem := AItem;
  end;

  { TItemsFactoryTemplate<T; H: TItemHolderTemplate<T>> }

  function TItemsFactoryTemplate<T, H: TItemHolderTemplate<T>>.CreateItemHolder(const Item: T): TItemHolderTemplate<T>;
  begin
    // it feature rids us from use ".. class of .." construction which it is forbidden for generic types, furthermore it fine work in Delphi (such parameterization of generic class by other) and it is very convenient
    Result := H.Create;
  end;

begin
end.
Tagsgenerics
Fixed in Revision
FPCOldBugId
FPCTarget-
Attached Files

Relationships

duplicate of 0025678 new Nested generic parameter types inside constraints compile in Delphi XE+ but not in FPC 

Activities

Kai Burghardt

2020-05-04 18:36

reporter   ~0122622

Did you want to do generic type restriction https://freepascal.org/docs-html/current/ref/refse52.html ?

You can only do that with a _data_ _type_ https://freepascal.org/docs-html/current/ref/refse50.html . A template that needs to be specialized is not a data type, but merely a “recipe” for a data type.

I rewrote your program as attached. But maybe I’m missing some detail? Check it out, whether it’s just exactly want you intended/wanted.
fpcTestGenerics.pas (704 bytes)   
program testGenerics(input, output, stdErr);

{$ifNDef FPC_objFPC}
	{$mode Delphi}
{$endIf}

type
	{$ifNDef FPC_Delphi} generic {$endIf} itemHolder<T> = class
			private
				date: T;
			public
				constructor create(i: T); virtual;
				property item: T read date;
		end;

	{$ifNDef FPC_Delphi} generic {$endIf} itemsFactory<T> = class
			private
				type
					H = {$ifNDef FPC_Delphi} specialize {$endIf} itemHolder<T>;
			public
				function createItem(const item: T): H;
		end;

constructor itemHolder{$ifDef FPC_Delphi}<T>{$endIf}.create(i: T);
begin
	date := i;
end;

function itemsFactory{$ifDef FPC_Delphi}<T>{$endIf}.createItem(const item: T): H;
begin
	result := H.create(item);
end;

begin
end.
fpcTestGenerics.pas (704 bytes)   

BlackShark

2020-05-05 10:50

reporter   ~0122630

Last edited: 2020-05-05 21:54

View 6 revisions

No, I didn't find it in restrictions.
The first time I also thought to define a subgeneric in a generic. But.
Let's start practicing.

I define the item holder and the factory for the string type.

TItemHolderString = class({$ifNDef FPC_Delphi} specialize {$endIf} itemHolder<string>)
TItemsFactoryString = class ({$ifNDef FPC_Delphi} specialize {$endIf} itemsFactory<string>);

1. When I try to use it:
var
  FactoryStringItems: TItemsFactoryString;
  ItemString: TItemHolderString;

begin
  FactoryStringItems := TItemsFactoryString.create;
  ItemString := FactoryStringItems.createItem('I want to be TItemHolderString but I am not');<--Error: Incompatible types: got "itemHolder<System.AnsiString>" expected "TItemHolderString"
end.

2. How to force the factory to create TItemHolderString, not itemHolder<string>???

3. If would be possible to specialize:
    TItemHolderString = class(itemHolder<string>);
    TItemsFactoryString = class(itemsFactory<string, TItemHolderString>);
    In generic method "function createItem(const item: T): H;" the factory will be to know which type to create and It is great idea of metaprogramming (not mine). And it automatically make a unnecessary construction "TSomeClassClass = class of TSomeClass" which in fact is forbidden for generics.

I complemented your project for use from a practical point of view.
fpcTestGenerics2.pas (1,288 bytes)   
program fpcTestGenerics2;

{$ifNDef FPC_objFPC}
	{$mode Delphi}
{$endIf}

type
	{$ifNDef FPC_Delphi} generic {$endIf} itemHolder<T> = class
			private
				date: T;
			public
				constructor create(const i: T); virtual;
				property item: T read date;
		end;

	{$ifNDef FPC_Delphi} generic {$endIf} itemsFactory<T> = class
			private
				type
					H = {$ifNDef FPC_Delphi} specialize {$endIf} itemHolder<T>;
			public
				function createItem(const item: T): H;
		end;

    TItemHolderString = class({$ifNDef FPC_Delphi} specialize {$endIf} itemHolder<string>)
    private
      FItNewProperty: integer;
    published
      property ItNewProperty: integer read FItNewProperty;
    end;

    ItemsFactoryString = class ({$ifNDef FPC_Delphi} specialize {$endIf} itemsFactory<string>);

constructor itemHolder{$ifDef FPC_Delphi}<T>{$endIf}.create(const i: T);
begin
	date := i;
end;

function itemsFactory{$ifDef FPC_Delphi}<T>{$endIf}.createItem(const item: T): H;
begin
	result := H.create(item);
end;

var
  FactoryStringItems: itemsFactoryString;
  ItemString: TItemHolderString;

begin
  FactoryStringItems := itemsFactoryString.create;
  ItemString := FactoryStringItems.createItem('I want to be TItemHolderString but I am not');
end.

fpcTestGenerics2.pas (1,288 bytes)   

Sven Barth

2020-05-06 15:11

manager   ~0122645

Last edited: 2020-05-06 15:12

View 2 revisions

This was already reported in 0025678.

As a workaround you can do it like this:

type
  TItemsFactoryTemplate<T> = class
  public type
    THolder = TItemHolderTemplate<T>;
  public
    function CreateItemHolder(const Item: T): THolder;
  end;

Issue History

Date Modified Username Field Change
2020-05-04 18:01 BlackShark New Issue
2020-05-04 18:36 Kai Burghardt Note Added: 0122622
2020-05-04 18:36 Kai Burghardt File Added: fpcTestGenerics.pas
2020-05-05 10:50 BlackShark Note Added: 0122630
2020-05-05 10:50 BlackShark File Added: fpcTestGenerics2.pas
2020-05-05 12:11 BlackShark Note Edited: 0122630 View Revisions
2020-05-05 12:14 BlackShark Note Edited: 0122630 View Revisions
2020-05-05 12:52 BlackShark Note Edited: 0122630 View Revisions
2020-05-05 15:25 BlackShark Note Edited: 0122630 View Revisions
2020-05-05 21:54 BlackShark Note Edited: 0122630 View Revisions
2020-05-06 15:04 Sven Barth Tag Attached: generics
2020-05-06 15:11 Sven Barth Assigned To => Sven Barth
2020-05-06 15:11 Sven Barth Status new => resolved
2020-05-06 15:11 Sven Barth Resolution open => duplicate
2020-05-06 15:11 Sven Barth FPCTarget => -
2020-05-06 15:11 Sven Barth Note Added: 0122645
2020-05-06 15:11 Sven Barth Relationship added duplicate of 0025678
2020-05-06 15:12 Sven Barth Note Edited: 0122645 View Revisions