I just started investigating the generics classes in fcl-stl for a program that I'm writing. I haven't written anything using generics in Free Pascal before, so this is all new to me. I am trying to specialize THashMap to map both strings to unsigned integers and then again to map integers back to strings, like so:
program maps; {$mode objfpc}{$H+} uses ghashmap, gutil; type TStrHashingClass = class class function hash(a: AnsiString; b: SizeUint): SizeUint; end; TWordHashingClass = class class function hash(a: Word; b: SizeUint): SizeUint; end; TStringWordMap = specialize THashMap<AnsiString, Word, TStrHashingClass>; TWordStringMap = specialize THashMap<Word, AnsiString, TWordHashingClass>; function StrHash(const S: string): Cardinal; begin Result := 3; // yes I know, I'm trying to keep this short to illustrate my problem. I have a real hash function for my program. end; class function TWordHashingClass.hash(a: Word; b: SizeUint): SizeUint; begin Result := a mod b; end; class function TStrHashingClass.hash(a: AnsiString; b: SizeUint): SizeUint; begin Result := StrHash(a) mod b; end; var strtable: TStringWordMap; begin strtable := TStringWordMap.Create; strtable['ábcdéf'] := 3; strtable.Destroy; end. This code will not compile: $ fpc -Fu/usr/share/fpcsrc/2.6.4/packages/fcl-stl/src/ -FU. maps.lpr Free Pascal Compiler version 2.6.4 [2014/04/20] for x86_64 Copyright (c) 1993-2014 by Florian Klaempfl and others Target OS: Linux for x86-64 Compiling maps.lpr ghashmap.pp(111,16) Error: Incompatible types: got "THashmap$AnsiString$Word$TStrHashingClass.TPair" expected "THashmap$Word$AnsiString$TWordHashingClass.TPair" ghashmap.pp(116,34) Error: Incompatible type for arg no. 1: Got "THashmap$Word$AnsiString$TWordHashingClass.TPair", expected "THashmap$AnsiString$Word$TStrHashingClass.TPair" ghashmap.pp(160,29) Error: Incompatible types: got "Word" expected "AnsiString" ghashmap.pp(161,41) Error: Incompatible types: got "AnsiString" expected "Word" ghashmap.pp(168,27) Error: Incompatible type for arg no. 1: Got "THashmap$Word$AnsiString$TWordHashingClass.TPair", expected "THashmap$AnsiString$Word$TStrHashingClass.TPair" ghashmap.pp(139,29) Error: Incompatible types: got "Word" expected "AnsiString" ghashmap.pp(180,29) Error: Incompatible types: got "Word" expected "AnsiString" ghashmap.pp(150,29) Error: Incompatible types: got "Word" expected "AnsiString" ghashmap.pp(150,44) Error: Incompatible types: got "Word" expected "AnsiString" ghashmap.pp(206,12) Error: Incompatible types: got "THashmap$AnsiString$Word$TStrHashingClass.TPair" expected "THashmap$Word$AnsiString$TWordHashingClass.TPair" ghashmap.pp(227,11) Error: Incompatible types: got "AnsiString" expected "Word" ghashmap.pp(232,13) Error: Incompatible types: got "Word" expected "AnsiString" ghashmap.pp(242,39) Error: Incompatible types: got "AnsiString" expected "Word" maps.lpr(44) Fatal: There were 13 errors compiling module, stopping Fatal: Compilation aborted Error: /usr/bin/ppcx64 returned an error exitcode (normal if you did not specify a source file to be compiled) But, if I remove the definition of TWordStringMap on line 18 from the type section, the code compiles just fine. It seems that fpc has gotten confused by the second specialization and has confused the two. As I understand it, fpc generics work by writing placeholders into the ppu which are then replaced with the specialized types. But how does it handle cases where there's more than one specialization? Or is there something else I've overlooked? I am running fpc 2.6.4 on Debian stable and on Fedora 20, and both display the same behaviour. _______________________________________________ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal