What a type parameter asks for
( of T ) does not say what T can do. The compiler therefore checks a
generic's body once for each type it is used with, against that real type. If
the body uses an operator the type does not have, that instantiation fails.
'' Largest( of T ) uses '>' on T, but nothing in its header says so.
function Largest( of T )( items() as T ) as T
var best = items( lbound( items ) )
for each x in items
if x > best then best = x
next
return best
end function
type Version
as int32 major, minor
end type
dim releases( 0 to 2 ) as Version = { ( 1, 4 ), ( 2, 0 ), ( 1, 9 ) }
var newest = Largest( releases() ) '' Version has no '>'
print newest.major; newest.minor
Version has no >, so this does not build:
needsgt.tiko(5,14): error TKO0720: no operator > compares this type
|
5 | if x > best then best = x
| ^
needsgt.tiko(15,21): note: in instantiation of 'largest( of version )'
|
15 | var newest = Largest( releases() ) '' Version has no '>'
| ^
The error points at the generic's body, which is correct code. The cause is
in the note: under it: line 15 asked for Largest( of Version ). Read an
error from a generic to the end before you edit anything.
The fix is on the type's side: give Version the operator the generic uses.
'' Largest( of T ) needs '>' on T.
function Largest( of T )( items() as T ) as T
var best = items( lbound( items ) )
for each x in items
if x > best then best = x
next
return best
end function
type Version
as int32 major, minor
end type
'' Supply the operator the generic asks for.
operator > ( byref a as Version, byref b as Version ) as boolean
if a.major <> b.major then return a.major > b.major
return a.minor > b.minor
end operator
dim releases( 0 to 2 ) as Version = { ( 1, 4 ), ( 2, 0 ), ( 1, 9 ) }
var newest = Largest( releases() )
print "newest:"; newest.major; "."; str( newest.minor )
dim scores( 0 to 3 ) as int32 = { 70, 85, 90, 62 }
print "best score:"; Largest( scores() )
Output
newest: 2.0
best score: 90
Largest did not change. The same generic serves int32, which has >
built in, and Version, which now has one of its own. Because a generic's
demands are not written in its header, state them in a comment above it, as
this one does.
Activities
- Write a generic
Contains( of T )( items() as T, byval x as T )and use it withVersion. Which operator does it need? - Remove the
>operator and add a<instead. Does the error change?