Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi unverständlicher DCC-Fehler E2506 (https://www.delphipraxis.net/132817-unverstaendlicher-dcc-fehler-e2506.html)

himitsu 20. Apr 2009 13:51


unverständlicher DCC-Fehler E2506
 
also, ich hatte grad mal zur Abwechslung etwas rumgespielt und dabei ist dieses hier rausgekommen:
Delphi-Quellcode:
Unit AssocArray;

Interface
  Type TAssocArray<Typ> = Record
    Private
      Type TRec = Record
          Name: WideString;
          Value: Typ;
        End;
      Var Data: Array of TRec;
      Function GetName     (      Index: Integer):            String;
      Function GetValue    (      Index: Integer):            Typ;
      Procedure SetValue    (      Index: Integer; Const Value: Typ);
      Function GetNamedValue(Const Name: String):             Typ;
      Procedure SetNamedValue(Const Name: String; Const Value: Typ);
      Function GetIndex    (Const Name: String):             Integer;
    Public
      Procedure SetLength(i: Integer);
      Function Length:     Integer;

      Property Name [      Index: Integer]: String Read GetName;
      Property Value[      Index: Integer]: Typ    Read GetValue     Write SetValue;     Default;
      Property Value[Const Name: String]: Typ    Read GetNamedValue Write SetNamedValue; Default;
      Property Index[Const Name: String]: Integer Read GetIndex;

      Function Add  (Const Value: Typ;                Const Name: String = ''): Typ;
      Procedure Insert(Const Value: Typ; Index: Integer; Const Name: String = '');
      Procedure Move (     OldIndex, NewIndex: Integer);
      Function Delete(                  Index: Integer):                         Typ; Overload;
      Function Delete(            Const Name: String):                          Typ; Overload;
    End;

Implementation
  Uses Windows;

  Function TAssocArray<Typ>.GetName(Index: Integer): String;
    Begin
      If (Index >= 0) and (Index < System.Length(Data)) Then
        Result := Data[Index].Name
      Else System.Error(reRangeError);
    End;

  Function TAssocArray<Typ>.GetValue(Index: Integer): Typ;
    Begin
      If (Index >= 0) and (Index < System.Length(Data)) Then
        Result := Data[Index].Value
      Else System.Error(reRangeError);
    End;

  Procedure TAssocArray<Typ>.SetValue(Index: Integer; Const Value: Typ);
    Begin
      If (Index >= 0) and (Index < System.Length(Data)) Then
        Data[Index].Value := Value
      Else System.Error(reRangeError);
    End;

  Function TAssocArray<Typ>.GetNamedValue(Const Name: String): Typ;
    Var i: Integer;

    Begin
      i := GetIndex(Name);
      If (i >= 0) and (i < System.Length(Data)) Then
        Result := Data[i].Value
      Else System.Error(reRangeError);
    End;

  Procedure TAssocArray<Typ>.SetNamedValue(Const Name: String; Const Value: Typ);
    Var i: Integer;

    Begin
      i := GetIndex(Name);
      If (i >= 0) and (i < System.Length(Data)) Then
        Data[i].Value := Value
      Else If Name <> '' Then
        Add(Value, Name)
      Else System.Error(reRangeError);
    End;

  Function TAssocArray<Typ>.GetIndex(Const Name: String): Integer;
    Begin
      If Name <> '' Then Begin
        Result := High(Data);
        While (Result >= 0) and (Data[Result].Name <> Name) do Dec(Result);
      End Else Result := -1;
    End;

  Procedure TAssocArray<Typ>.SetLength(i: Integer);
    Begin
      System.SetLength(Data, i);
    End;

  Function TAssocArray<Typ>.Length: Integer;
    Begin
      Result := System.Length(Data);
    End;

  Function TAssocArray<Typ>.Add(Const Value: Typ; Const Name: String = ''): Typ;
    Var i: Integer;

    Begin
      If GetIndex(Name) >= 0 Then System.Error(reInvalidOp);
      i := System.Length(Data);
      System.SetLength(Data, i + 1);
      Data[i].Name := Name;
      Data[i].Value := Value;
    End;

  Procedure TAssocArray<Typ>.Insert(Const Value: Typ; Index: Integer; Const Name: String = '');
    Var i: Integer;
      Temp: TRec;

    Begin
      If (Index >= 0) and (Index <= System.Length(Data)) Then Begin
        If GetIndex(Name) >= 0 Then System.Error(reInvalidOp);
        i := System.Length(Data);
        System.SetLength(Data, i + 1);
        If Index < i Then Begin
{ja und hier wird nicht gemeckert}
{}        MoveMemory(@Temp, @Data[i], SizeOf(TRec));
{}        MoveMemory(@Data[Index + 1], @Data[Index], (i - Index) * SizeOf(TRec));
{}        MoveMemory(@Data[Index], @Temp, SizeOf(TRec));
{}        ZeroMemory(@Temp, SizeOf(TRec));
        End;
        Data[Index].Name := Name;
        Data[Index].Value := Value;
      End Else System.Error(reRangeError);
    End;

  Procedure TAssocArray<Typ>.Move(OldIndex, NewIndex: Integer);
    Var S: String;
      Temp: Typ;

    Begin
      If (NewIndex >= 0) and (NewIndex < System.Length(Data)) Then Begin
        S   := GetName(OldIndex);
        Temp := Delete(OldIndex);
        Insert(Temp, NewIndex, S);
      End Else System.Error(reRangeError);
    End;

  Function TAssocArray<Typ>.Delete(Index: Integer): Typ;
    Var i: Integer;
      Temp: TRec;

    Begin
      If (Index >= 0) and (Index < System.Length(Data)) Then Begin
        Result := Data[Index].Value;
        i := System.High(Data);
        If Index < i Then Begin
{hier tritt jeweils der Fehler auf}
{}        MoveMemory(@Temp, @Data[Index], SizeOf(TRec));
{}        MoveMemory(@Data[Index], @Data[Index + 1], (i - Index) * SizeOf(TRec));
{}        MoveMemory(@Data[i], @Temp, SizeOf(TRec));
{}        ZeroMemory(@Temp, SizeOf(TRec));
        End;
        System.SetLength(Data, i);
      End Else System.Error(reRangeError);
    End;

  Function TAssocArray<Typ>.Delete(Const Name: String): Typ;
    Begin
      Result := Delete(GetIndex(Name));
    End;

End.
Es wird theoretisch einfach so angewendet
Delphi-Quellcode:
Uses AssocArray;

Type TTestRec = Record
    A:      String;
    X, Y, Z: Integer;
  End;

  TStringAssocArray = TAssocArray<String>;
  TIntegerAssocArray = TAssocArray<Integer>;
  TTestAssocArray   = TAssocArray<TTestRec>;

Procedure Test;
  Var A: TStringAssocArray;

  Begin
    A['123'] := 'abc';

    If A[0] = A['123'] Then Beep;
  End;
und stellt praktisch ein assoziatives Array dar. :angel:

Nur leider bekomm ich beim Test eine komische Fehlermeldung. :wall:
Zitat:

[DCC Fehler] AssocArray.pas(149): E2506 Im interface-Abschnitt deklarierte Methode des parametrisierten Typs darf kein lokales Symbol '.2' verwenden
Und zwar genau 4 Mal in der Delete-Funktion.
Genauer gesagt bei den Zeilen mit MoveMemory und ZeroMemmory.

Nur da ist doch "nichts" anders, wie in der Insert-Funktion, wo nicht gemeckert wird? :gruebel:
(abgesehn von der Reinfolge der Source/Destination-Parameter)

Und dazu kommt noch, daß ich garnicht versteh was der genau will. :oops:

himitsu 20. Apr 2009 16:29

Re: unverständlicher DCC-Fehler E2506
 
OK, ich konnte es jetzt auf SizeOf(TRec) eingrenzen, was irgendwie mal geht und dann mal wieder nicht.
Und Array[1..SizeOf(Typ)] geht garnicht ... wollte eine Temp-Variable mit der selben Größe in der Move-Prozedur erstellen.

so ging es auch nicht
Delphi-Quellcode:
Type TAssocArray<Typ> = Record
  Private
    Type TRec = Record
        Name: WideString;
        Value: Typ;
      End;
    Const RecSize = SizeOf(TRec);
    Var Data: Array of TRec;
da kam dann nur dieses raus
Zitat:

[DCC Fehler] AssocArray.pas(10): E2005 'TAssocArray<>.TRec' ist kein gültiger Typenbezeichner
nja, am Ende konnte ich mit einem Umweg über die Variable Data lösen
und hab überall jetzt einfach SizeOf(Data[0]) verwendet :angel:

aber dennoch komisch, warum SizeOf(TRec) erst geht (in .Insert) und dann plötzlich nicht mehr (in .Delete) :wall:

jbg 20. Apr 2009 18:14

Re: unverständlicher DCC-Fehler E2506
 
Zitat:

Zitat von himitsu
aber dennoch komisch, warum SizeOf(TRec) erst geht (in .Insert) und dann plötzlich nicht mehr (in .Delete) :wall:

Update 3 soll ja einige Bugfixes für die Generics enthalten. Lassen wir uns da einfach mal überraschen, ob Generics in Delphi 2009 doch noch nutzbar werden.

Alter Mann 20. Apr 2009 18:26

Re: unverständlicher DCC-Fehler E2506
 
Hi,

Mach die Hilfe auf und suche nach E2506.

Gruss

himitsu 20. Apr 2009 19:22

Re: unverständlicher DCC-Fehler E2506
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Zitat von Alter Mann
Mach die Hilfe auf und suche nach E2506.

hast du das auch mal gemacht?
Zitat:

Zitat von OH
E2506: Explizite Spezialisierung ist nicht eindeutig: Template-Arg. müssen angegeben werden
Der folgende Programmcode erfordert explizite Template-Argumente:

Delphi-Quellcode:
template<class T> void foo(T);

template<class T> void foo(T *);

template<> void foo(int *); // Fehler, es muss 'foo<int>' oder 'foo<int *>' heißen

Also das klingt mehr nach einem Problem in der Definition des Generics

Ich hab aber Problemchem in der Implementierung
und diese treten auch noch nur sporatisch auf. :?




[add]
Also das ist aktuell mein kleines Testprogramm und die aktuelle Version liegt im Anhang.
Leider meckert der Compiler an unterschiedlichen Stellen und wenn man gleich nochmal compilert, wird oftmals plötzlich wo anders gemeckert. :?
Ansonsten wäre es eigentlich eine recht schicke Sache (wenn es denn vollständig liefe)
Delphi-Quellcode:
Program Project1; SysUtils, AssocArray;

Type TTestRec = Record
    A:      String;
    X, Y, Z: Integer;
  End;

  TStringAssocArray = TAssocArray<String>;
  TIntegerAssocArray = TAssocArray<Integer>;
  TTestAssocArray   = TAssocArray<TTestRec>;

Var A: TStringAssocArray;
  B: TTestAssocArray;
  T: TTestRec;

Begin
  A['123']   := 'abc';
  A['456']   := 'def';
  A['alfred'] := 'xyz';

  If A[1] = A['456'] Then Beep;

  // A.SetLength(3);
  //
  // A.Length                 = 3
  // A.Name[1]                = '123'
  // A.Value[1]    = A[1]    = 'abc'
  // A.Value['456'] = A['456'] = 'abc'
  // A.Index['456']           = 1
  //
  // A.Add('ghi', 'Name');
  // A.Add('ghi');
  // A.Insert('ghi', 3, 'Name');
  // A.Insert('ghi', 3);
  // A.Move(3, 2);
  // A.Delete(3);
  // A.Delete('alfred');

  B['test'] = T;
  If B[0] = T Then Beep;
End.
[edit=mkinzler]Delphi-Tag eingefügt Mfg, mkinzler[/edit]

Assertor 20. Apr 2009 21:54

Re: unverständlicher DCC-Fehler E2506
 
Hi,

Zitat:

Zitat von jbg
Update 3 soll ja einige Bugfixes für die Generics enthalten. Lassen wir uns da einfach mal überraschen, ob Generics in Delphi 2009 doch noch nutzbar werden.

Absolut Richtig!

@himitsu: Ich glaube fest daran, daß es an der Generics Unterstützung von D2009 liegt und dies bestimmt mit dem nächsten Update gehen wird!

Gruß Assertor

himitsu 20. Apr 2009 22:25

Re: unverständlicher DCC-Fehler E2506
 
mal sehn ob es besser ist, als Update2,das hat nach meinem Gefphl nix verbessert, nur verschlechtert :?

die Operatoren mag ich inzwischen ja schon und die Generics könnten mir gefallen, wenn sie mal richtig laufen :angel2:

jaenicke 21. Apr 2009 00:28

Re: unverständlicher DCC-Fehler E2506
 
Zitat:

Zitat von himitsu
und die Generics könnten mir gefallen, wenn sie mal richtig laufen :angel2:

Derweil gibts ja C# um Generics zu genießen. :mrgreen:

ecotron 7. Jul 2009 22:20

Re: unverständlicher DCC-Fehler E2506
 
Mit dem D2009 Update 3 kommt immer noch ein Fehler. Scheinbar gibt es ein Problem mit überladenen Default Properties und Generics.
Und wenn aber man Properties verschiebt oder Kleinigkeiten an andere Stelle ändert geht es manchmal.

Ganz seltsam ist auch dass man trotz Fehlermeldung eine Exe erzeugen kann. Einfach nach Projekt "Erzeugen" nochmals auf "Start" drücken.

himitsu 7. Jul 2009 23:41

Re: unverständlicher DCC-Fehler E2506
 
Zitat:

Zitat von ecotron
Scheinbar gibt es ein Problem mit überladenen Default Properties und Generics.

gut, das überladene Property könnte man ja notfalls als Variant-Parameter zusammenfassen, aber dann ging ein wenig die "Leistung" runter (halt wegen der Variantverwaltung),
oder man läßt den Zugriff via Index (Integer) weg, bzw. verlagert ihn (umbenennen)

Zitat:

Zitat von ecotron
Und wenn aber man Properties verschiebt oder Kleinigkeiten an andere Stelle ändert geht es manchmal.

Ganz seltsam ist auch dass man trotz Fehlermeldung eine Exe erzeugen kann. Einfach nach Projekt "Erzeugen" nochmals auf "Start" drücken.

sowas ist mir auch bei anderen Dingen schon paar Mal untergekommen. :shock:

BlackSeven 8. Jan 2011 09:53

AW: unverständlicher DCC-Fehler E2506
 
Zitat:

A['123'] := 'abc'; -> [DCC Error] Unit1.pas(61): E2010 Incompatible types: 'Integer' and 'string'
A['456'] := 'def';
A['alfred'] := 'xyz';
Ich bin davon ausgegangen, dass überladene Array-Properties unterstützt werden, bekomme aber einen Fehler unter Delphi XE.
Erlich gesagt, habe ich diese bisher noch nicht benötigt. Mache ich da etwas falsch?

himitsu 8. Jan 2011 11:04

AW: unverständlicher DCC-Fehler E2506
 
Funktionieren sollte dieses.

Wie hast du es denn deklariert?

BlackSeven 8. Jan 2011 14:58

AW: unverständlicher DCC-Fehler E2506
 
Zitat:


Delphi-Quellcode:

program Project1;

uses
  SysUtils, AssocArray;

type
  TStringAssocArray = TAssocArray<String>;

var
  A: TStringAssocArray;

begin
  A['123'] := 'abc';

end.


Ich habe die Unit "AssocArray" eingebunden und Dein Testprogramm verwendet. :?:

himitsu 8. Jan 2011 16:25

AW: unverständlicher DCC-Fehler E2506
 
Ups, da hatte ich was falsch verstanden. :oops:

OK, so wie es aussieht, hat Emba mal wieder Mist gebaut, welcher sich auch schon in Delphi 2010 nachvollziehen läßt.

Irgendwie wird bei direkten Angaben von Werten immer nur das zuerst deklarierte Property erkannt.
Delphi-Quellcode:
var MyArr: TAssocArray<String>;

MyArr['123'] := ...;
Nimmt man Variablen, dann klappt es.
Delphi-Quellcode:
var MyArr: TAssocArray<String>;
  S: String;
S := '123';
MyArr[S] := ...;
Auch sowas wie
Delphi-Quellcode:
MyArr[String('123')]
hilft nix.


Meine einzig mögliche Antwort ist aktuell also:
Toll gemacht Emba ... wieder was, welches nicht mehr funktioniert. :thumb:

Die einzige Lösung wäre, wenn man statt der überladenen Property nun nur noch ein Property nutzt, welches als Parameter einen Variant besitzt und man dann intern die entsprechenden Varianten Anhand des Variant-Inhalts ausführt.
Oder man mißhandelt wieder mal die Record-Operatoren und bastelt sich einen gemischten Parameter-Typen.
Allerdings sind beide Varianten zwar möglich, aber sie sind keine "optimale" Lösung.

Schön wäre es, wenn Embarcadero dieses reparieren würde.
(aber aus Erfahrung passiert sowas eher garnicht oder man muß sich die Bugfixes mit der nächsten Delphi-Version teuer erkaufen)

USchuster 9. Jan 2011 17:19

AW: unverständlicher DCC-Fehler E2506
 
Zitat:

Zitat von himitsu (Beitrag 1073282)
Schön wäre es, wenn Embarcadero dieses reparieren würde.

Hilfreich dafür wäre ein QC Report mit folgendem Testcase und dem Hinweis Regression.

Delphi-Quellcode:
program GenericsMultipleDefaultPropertiesTest;

{$APPTYPE CONSOLE}

type
  TAssocArray<T> = record
  private
    function GetNamedValue(const AName: string): T;
    function GetValue(AIndex: Integer): T;
    procedure SetNamedValue(const AName: string; const AValue: T);
    procedure SetValue(AIndex: Integer; const AValue: T);
  public
    property Value[AIndex: Integer]: T read GetValue write SetValue; default;
    property Value[const AName: string]: T read GetNamedValue write SetNamedValue; default;
  end;

{ TAssocArray<T> }

function TAssocArray<T>.GetNamedValue(const AName: string): T;
begin
  Result := Default(T);
end;

function TAssocArray<T>.GetValue(AIndex: Integer): T;
begin
  Result := Default(T);
end;

procedure TAssocArray<T>.SetNamedValue(const AName: string;
  const AValue: T);
begin
//
end;

procedure TAssocArray<T>.SetValue(AIndex: Integer; const AValue: T);
begin
//
end;

type
  TStringAssocArray = TAssocArray<string>;

procedure Test;
var
  A: TStringAssocArray;
begin
  A['123'] := 'abc';
  if A[0] = A['123'] then;
end;

begin
  WriteLn('PASS'); // on compile
end.
Zitat:

Zitat von himitsu (Beitrag 1073282)
(aber aus Erfahrung passiert sowas eher garnicht oder man muß sich die Bugfixes mit der nächsten Delphi-Version teuer erkaufen)

Eine Lösung wird es sehr wahrscheinlich nur für XE2 geben.

himitsu 9. Jan 2011 17:26

AW: unverständlicher DCC-Fehler E2506
 
Solange Emba in Punkto Datenschutz im QC nichts macht, werde ich da nichts mehr posten.
Abgesehn davon, daß ich dort schon Einiges reingestellt hab und dieses dennoch nicht behoben ist.

USchuster 9. Jan 2011 18:42

AW: unverständlicher DCC-Fehler E2506
 
Ich habs als

Report No: 90767 Status: Reported
Regression: E2010 with multiple default properties in a generic type
http://qc.embarcadero.com/wc/qcmain.aspx?d=90767

gemeldet.

Stevie 10. Jan 2011 12:10

AW: unverständlicher DCC-Fehler E2506
 
Zitat:

Zitat von himitsu (Beitrag 1073282)
Die einzige Lösung wäre, wenn man statt der überladenen Property nun nur noch ein Property nutzt, welches als Parameter einen Variant besitzt und man dann intern die entsprechenden Varianten Anhand des Variant-Inhalts ausführt.
Oder man mißhandelt wieder mal die Record-Operatoren und bastelt sich einen gemischten Parameter-Typen.
Allerdings sind beide Varianten zwar möglich, aber sie sind keine "optimale" Lösung.

Delphi-Quellcode:
type
  TAssocArray<T> = record
  private
    function GetNamedValue(const AName: string): string;
    function GetValue(AIndex: Integer): string;
    procedure SetNamedValue(const AName: string; const AValue: string);
    procedure SetValue(AIndex: Integer; const AValue: string);
  public
    property Value[AIndex: Integer]: string read GetValue write SetValue; default;
    property ValueByName[const AName: string]: string read GetNamedValue write SetNamedValue;
  end;
*fixed*

Assarbad 10. Jan 2011 12:14

AW: Re: unverständlicher DCC-Fehler E2506
 
Zitat:

Zitat von jaenicke (Beitrag 904875)
Derweil gibts ja C# um Generics zu genießen. :mrgreen:

Oder C++ mit Templates. Himmlisch ... speziell mit Boost. :tongue:

himitsu 10. Jan 2011 14:47

AW: unverständlicher DCC-Fehler E2506
 
Zitat:

*fixed*
Wenn man das so macht, dann sind die ganzen überladenen Default-Property nutzlos.
(sind sie jetzt zwar auch, da man sie nicht mehr nutzen kann)

Also ich würde diese gerne schon noch verwenden können.
Wobei ich es schonmal schade finde, daß man sowas (früher) nur bei den Defaultproperty und nicht bei allen Property nutzen konnte.

Stevie 10. Jan 2011 16:14

AW: unverständlicher DCC-Fehler E2506
 
Zitat:

Zitat von himitsu (Beitrag 1073690)
Zitat:

*fixed*
Wenn man das so macht, dann sind die ganzen überladenen Default-Property nutzlos.
(sind sie jetzt zwar auch, da man sie nicht mehr nutzen kann)

Das bezog sich auf deine waghalsigen Workaround Ideen ohne die offensichtliche "Lösung" zu sehen.
Ja, schade, dass dieses Feature an dieser Stelle nicht funktioniert, macht deinen Code aber nicht unbrauchbar.

himitsu 10. Jan 2011 21:29

AW: unverständlicher DCC-Fehler E2506
 
Es bleibt aber dennoch was Anderes ... also so, als wenn man ReadLn nutzt, weil TStringList kaputt ist.

PS: Das mit den Operatoren hab ich in meinem himXML gentzt, um den Code auch auf D2006 laufen zu lassen, welches noch keine überladenen Property kannte.

Eine sehr gute Bilanz also.
> in 2009 (?) eingeführt und in 2010 wieder geschrottet.


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:04 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz