7

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 using 2 Interfaces, inherited and 2 Classes, inherited. The following code reproduces the error:

program Project22;

{$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.

The compiler error for 'TKeyObjectStorage' is:

[DCC Error] Project22.dpr(11): E2514 Type parameter 'T' must support interface 'IStorageObject'

What I think is, that the compiler is not recognizing that Parameter T of the Class 'TKeyObjectStorage' correctly. It should be correct, since the wanted Type 'IKeyStorageObject' has the parent type IStorageObject.

Why is this not working? What am I doing wrong? Is this not possible in Delphi?

5
  • Did you just completely change the question?!! Did you just replace that comma with as semi-colon?!! And the code you posted is still not enough to exhibit the error. Please do what I suggested and post a complete program. I showed you how in my answer. Commented Oct 30, 2013 at 12:44
  • Sorry for this David, Yes i did, but the ',' did not throw an or this error and was only a minor oversight. Sry again. Commented Oct 30, 2013 at 12:52
  • @Hugie, Do not change the question to deviate from it's original problem. Any errors that are in the original need to stay in the question; however create a console app with the minimal code to demonstrate the issue. and paste that console app in the question. Commented Oct 30, 2013 at 12:52
  • OK, I think I have a workaround for you. Code at the top of my answer compiles in XE2. I also should have been more careful in my compiler selection. Commented Oct 30, 2013 at 12:54
  • I've put in the SSCCE, with the original , error. Commented Oct 30, 2013 at 13:02

1 Answer 1

9

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 and U are both bound to the ISerializable constraint.

Sign up to request clarification or add additional context in comments.

8 Comments

Thx David, i edited my code to a complete unit (without instantiation) and it reproduces the error in a clean project. And yes, you were right, i had a minor logical mistake due to ,->; but it was not the error i am dealing with. Thx for your effort.
Your update does not produce an error. Try it. Start with a new project, and add that unit, and then compile. Guess what, it compiles. As I said in my answer, you need to instantiate an object. I'm a bit frustrated by this. You need to learn how to make an SSCCE so that you don't waste our time. I'm off to lunch now. I hope the question is fixed by the time I return.
I've copy-pasted your code into XE2, it still gives an error: [DCC Error] Project22.dpr(11): E2514 Type parameter 'T' must support interface 'IStorageObject' on this line: TKeyObjectStorage<TKey; T: IKeyStorageObject<TKey>> = class(TObjectStorage<T>)
@Johan Gah, XE2 compiler bug fixed in XE3. Guess what compiler I am using.
@David. It's my first Question and i am Sorry for waisting your time.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.