Recent

Author Topic: Generic method with const and interface  (Read 2751 times)

Okoba

  • Hero Member
  • *****
  • Posts: 651
Generic method with const and interface
« on: November 16, 2020, 03:27:40 pm »
This code does not compile with FPC Trunk with this message:
Quote
unit1.pas(16,11) Error: Function header doesn't match the previous declaration "Test2$2(T);"
It can not compile the Test2, a generic method with const and interface, but can compile the Test with no interface.
Is this a bug, or am I missing something?

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode delphi}
  4.  
  5. interface
  6.  
  7. procedure Test2<T,const N:Integer>(A: T);
  8.  
  9. implementation
  10.  
  11. procedure Test<T,const N:Integer>(A: T);
  12. begin
  13.  
  14. end;
  15.  
  16. procedure Test2<T,const N:Integer>(A: T);
  17. begin
  18.  
  19. end;
  20.  
  21. end.

ASerge

  • Hero Member
  • *****
  • Posts: 2481
Re: Generic method with const and interface
« Reply #1 on: November 16, 2020, 06:14:51 pm »
...but can compile the Test with no interface.
Code: Pascal  [Select][+][-]
  1. procedure Test<T,const N:Integer>(A: T);
  2. begin
  3.  
  4. end;
I doubt it.
1. A type parameter cannot be prefixed with const.
2. A type restriction cannot be an integer type (the documentation, by the way, does not reflect that the restriction can be "constructor"). See Generic type definition.

The implementation part should not include type restrictions for generics.

Warfley

  • Hero Member
  • *****
  • Posts: 2050
Re: Generic method with const and interface
« Reply #2 on: November 16, 2020, 06:42:26 pm »
The implementation part should not include type restrictions for generics.

This is not a type restriction. I don't know about generic functions, but for classes generic parameters can be used to specialize constants:
Code: Pascal  [Select][+][-]
  1.   TStaticBitset<const Size: SizeInt> = record
  2.   private type
  3.     TElementType = NativeInt;
  4.     //[...]
  5.   private
  6.     const ElementSize = BitSizeOf(TElementType);
  7.     const NumElements = (Size + ElementSize - 1) div ElementSize; // Ceil(Size / ElementSize)
  8.   public
  9.     FData: Array[0..NumElements - 1] of TElementType;
  10.  

ASerge

  • Hero Member
  • *****
  • Posts: 2481
Re: Generic method with const and interface
« Reply #3 on: November 16, 2020, 07:26:08 pm »
This is not a type restriction. I don't know about generic functions, but for classes generic parameters can be used to specialize constants:
"Type restriction" is the documentation term - what is specified in the type after the colon.
But you are right, if use generics in the type declaration, this syntax works. However I don't really understand the meaning of const in this case.

Warfley

  • Hero Member
  • *****
  • Posts: 2050
Re: Generic method with const and interface
« Reply #4 on: November 16, 2020, 11:41:58 pm »
"Type restriction" is the documentation term - what is specified in the type after the colon.
But you are right, if use generics in the type declaration, this syntax works. However I don't really understand the meaning of const in this case.
My bad, I wanted to say that this is not a type parameter. I somehow mixed that up. From my understanding, the use of const says that this parameter shall not be a type but a constant, as in my example.

For example (I don't have an fpc to try it out):
Code: Pascal  [Select][+][-]
  1. generic function MultiplyByN<const N: Integer>(a: Integer): Integer;
  2. begin
  3.   Result := a * N;
  4. end;
This would be equivalent to
Code: Pascal  [Select][+][-]
  1. generic TTest<const N: Integer> = record
  2.   class function MulitplyByN(a: Integer);
  3. end:
This way when using the generic parameter N = 2 (or a power of two), the optimizer could replace this with a left shift

Okoba

  • Hero Member
  • *****
  • Posts: 651
Re: Generic method with const and interface
« Reply #5 on: November 17, 2020, 07:01:32 am »

PascalDragon

  • Hero Member
  • *****
  • Posts: 6381
  • Compiler Developer
Re: Generic method with const and interface
« Reply #6 on: November 17, 2020, 09:43:14 am »
Is this a bug, or am I missing something?

Yes, you're missing something.

The important point is the following: if you have a declaration of a generic routine in the interface section of a unit or as a method of a class you must not repeat any constraints for the generic parameters, that includes both type as well as constant constraints. Delphi behaves (at least with type constraints) similarly which is why we used that for constant parameters as well. Where you must repeat the constraints however is if you use a forward declaration, because it behaves the same with normal parameters (though I should probably loosen that restriction in mode Delphi, cause there one can leave out the normal parameters as well... :-\ ).

So your code becomes this (I've changed Test into a forward declaration just to show what I mean):

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode delphi}
  4.  
  5. interface
  6.  
  7. procedure Test2<T,const N:Integer>(A: T);
  8.  
  9. implementation
  10.  
  11. procedure Test<T,const N:Integer>(A: T); forward;
  12.  
  13. procedure Test2<T,N>(A: T);
  14. begin
  15.  
  16. end;
  17.  
  18. procedure Test<T,const N:Integer>(A: T);
  19. begin
  20.  
  21. end;
  22.  
  23. end.

But you are right, if use generics in the type declaration, this syntax works. However I don't really understand the meaning of const in this case.

Constant parameters allow you to define a constant of which the value is provided when specializing the generic. See the announcement mail that OkobaPatino linked to.

Okoba

  • Hero Member
  • *****
  • Posts: 651
Re: Generic method with const and interface
« Reply #7 on: November 17, 2020, 10:24:12 am »
Thanks, @PascalDragon, for clarification. That is a little bit odd as you usually repeat what you write in the interface to implementation. I couldn't find what you've said in the docs. Do you know if it is documented or not, and if not, do you want me to add an issue to update them?
Maybe I should report an issue for CodeTools too.

PascalDragon

  • Hero Member
  • *****
  • Posts: 6381
  • Compiler Developer
Re: Generic method with const and interface
« Reply #8 on: November 17, 2020, 01:01:32 pm »
Thanks, @PascalDragon, for clarification. That is a little bit odd as you usually repeat what you write in the interface to implementation.

As I said, that's how Delphi handles type constraints. It would be odd if constant parameters would behave differently there.

I couldn't find what you've said in the docs. Do you know if it is documented or not, and if not, do you want me to add an issue to update them?

The docs are for the released version (3.2.0) and generic constant parameters are trunk only, so of course they are not mentioned.

However the whole feature of generic routines seems to not be documented yet, so you should file a bug for that (and mention that this behaviour regarding constraints should be documented as well).

Maybe I should report an issue for CodeTools too.

Would be good, yes.

Okoba

  • Hero Member
  • *****
  • Posts: 651
« Last Edit: November 17, 2020, 02:49:21 pm by OkobaPatino »


 

TinyPortal © 2005-2018