I am currently stuck with a compiling error, no one in our company can help and I am sadly not finding the correct search patterns for SO or google.
As code I am us
Update
The original question had a problem which I identified (see below). However, the fix I describe there is fine for XE3 and later, but that program below does not compile in XE2. Thus I conclude that this is an XE2 generics compiler bug.
Anyway, here's a workaround for Delphi XE2:
{$APPTYPE CONSOLE}
type
IStorageObject = interface(IInterface)
end;
TObjectStorage<T: IStorageObject> = class(TObject)
end;
IKeyStorageObject<TKey> = interface(IStorageObject)
end;
TKeyObjectStorage<TKey; T: IKeyStorageObject<TKey>, IStorageObject> = class(TObjectStorage<T>)
end;
TImplementingClass<TKey> = class(TInterfacedObject, IStorageObject, IKeyStorageObject<TKey>)
end;
begin
TKeyObjectStorage<Integer, TImplementingClass<Integer>>.Create;
end.
Original answer
It would have been better if you had provided a complete program that exhibited the compiler error. You need to attempt to instantiate an object to see that error.
But, I think I've reproduced your problem. So I believe that the issue is that this code:
TKeyObjectStorage<TKey, T: IKeyStorageObject<TKey>> = ...
applies the generic constraint to both TKey
and T
. Now, clearly you only want the constraint to apply to T
so you'll need to write:
TKeyObjectStorage<TKey; T: IKeyStorageObject<TKey>> = ...
Here's a short program that compiles following the change in Delphi XE3:
{$APPTYPE CONSOLE}
type
IStorageObject = interface(IInterface)
end;
TObjectStorage<T: IStorageObject> = class(TObject)
end;
IKeyStorageObject<TKey> = interface(IStorageObject)
end;
TKeyObjectStorage<TKey; T: IKeyStorageObject<TKey>> = class(TObjectStorage<T>)
end;
TImplementingClass<TKey> = class(TInterfacedObject, IKeyStorageObject<TKey>)
end;
begin
TKeyObjectStorage<Integer, TImplementingClass<Integer>>.Create;
end.
This is quite a nuance, the changing of a comma to a semi-colon. Programming by significant punctuation is never much fun. That said, you are familiar with the difference between commas and semi-colons in formal parameter lists and so it should not come as too much of a surprise to see the same distinction drawn here.
The documentation does cover this mind you:
Multiple Type Parameters
When you specify constraints, you separate multiple type parameters by semicolons, as you do with a parameter list declaration:
type TFoo<T: ISerializable; V: IComparable>
Like parameter declarations, multiple type parameters can be grouped together in a comma list to bind to the same constraints:
type TFoo<S, U: ISerializable> ...
In the example above,
S
andU
are both bound to theISerializable
constraint.