Enum-Type feststellen

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Antworten
LazProgger
Beiträge: 63
Registriert: Di 11. Mär 2014, 00:33

Enum-Type feststellen

Beitrag von LazProgger »

Gibt es irgendeine Möglichkeit den "Typ" eines Enums festzustellen?

Ich würde in der folgenden Funktion gerne wissen, ob sie mit einem Element aus TEnum1 oder TEnum2 aufgerufen wurde.

Code: Alles auswählen

type 
  TEnum1 = (a, b, c);
  TEnum2 = (d, e, f);
 
 
function FEnum(AEnum: variant): boolean;
begin
  if TypeOf(AEnum) is TEnum1 then ...   // Fehler: class identifier expected
  if AEnum in TEnum1 then ...           // Fehler: operator is not overloaded
  if AEnum is TEnum1 then ...           // Fehler: class or interface type expected  
 
  if TypeOf(AEnum) is TEnum2 then ...   // Fehler: class identifier expected
  if AEnum in TEnum2 then ...           // Fehler: operator is not overloaded
  if AEnum is TEnum2 then ...           // Fehler: class or interface type expected  
end;
Das sind meine Versuche bisher, im Kommentar dahinter stehen die Fehlermeldungen. Gibt es so etwas wie TypeOfEnum, was ich hier verwenden kann?

Warf
Beiträge: 2135
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Enum-Type feststellen

Beitrag von Warf »

Das einzige was mir einfallen würde wäre so etwas

Code: Alles auswählen

TEnum1 = (a=1, b=2, c=3);
TEnum2 = (c=4, d=5, e=6);
 
procedure Foo(const e);
begin
  case Integer(e) of
    1..3: Bar_E1(TEnum1(e));
    4..6: Bar_E2(TEnum2(e));
  end;
end;

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2822
Registriert: Fr 22. Sep 2006, 19:32
OS, Lazarus, FPC: Winux (Lazarus 2.0.10, FPC 3.2.0)
CPU-Target: x86, x64, arm
Wohnort: Berlin
Kontaktdaten:

Re: Enum-Type feststellen

Beitrag von m.fuchs »

Leider sieht man ja nicht, was deine Funktion macht. Aber gibt es einen sinnvollen Grund, für beide Typen dieselbe Funktion zu verwenden?
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

martin_frb
Beiträge: 588
Registriert: Mi 25. Mär 2009, 21:12
OS, Lazarus, FPC: Laz trunk / fpc latest release / Win and other
CPU-Target: mostly 32 bit

Re: Enum-Type feststellen

Beitrag von martin_frb »

Afaik geht das nicht.

Aber folgendes geht (F am Anfang, ist ueblich fuer Fields (variablen), nicht Funktionen):

Code: Alles auswählen

 
const
  ConstValForEnum1 = 1;
  ConstValForEnum2 = 3;
 
function FEnum(AEnum:TEnum1): boolean; OVERLOAD;
begin
  result := FEnum(ord(AEnum), ConstValForEnum1);
end;
 
function FEnum(AEnum:TEnum2): boolean; OVERLOAD;
begin
  result := FEnum(ord(AEnum), ConstValForEnum2);
end;
 
function FEnum(AEnum, AENumType: integer): boolean;
begin
  if AENumType =ConstValForEnum1 then
     if AEnum = ord(a) then ...           
 
 

LazProgger
Beiträge: 63
Registriert: Di 11. Mär 2014, 00:33

Re: Enum-Type feststellen

Beitrag von LazProgger »

Vielen Dank für eure Antworten.

@m.fuchs: Grundsätzlich geht es darum, dass ich verschiedene Enums habe und je nach Enum-Typ verschiedene Konstanten addieren muss. Ich hatte mir erhofft das mit einer einfachen Typabfrage zu machen, um mir zu ersparen für jeden Enum-Typ eine eigene Funktion zu schreiben.

@Warf: Für den kleinen Wertebereich sicher eine gute Lösung, kann ich aber bei mir nicht verwenden, da die Enums je nach Projekt andere sind (darauf habe ich keinen Einfluss) und ich eine allgemeine Funktion für alle schreiben wollte.

@martin_frb: Von der grundsätzlichen Idee her hat mir das schon mal weitergeholfen, obwohl man da wieder bei den mehreren Funktonen wäre. Aber prinzipiell kann man daraus etwas machen wenn es diese generelle Abfrage nach dem Typ nicht gibt. Aber dann vielleicht eher in dieser Form:

Code: Alles auswählen

const
  ConstValForEnum1 = 1;
  ConstValForEnum2 = 3;
 
function CheckEnum(AEnum: TEnum1): integer; OVERLOAD;
begin
  result := ConstValForEnum1;
end;
 
function CheckEnum(AEnum: TEnum2): integer; OVERLOAD;
begin
  result := ConstValForEnum2;
end;
Kann es sein dass der Compiler die Enmus immer durch die Integer-Werte ersetzt? Dann würde in der Funktion ja eh immer nur der Integer-Wert ankommen und der wäre nicht mehr rückverfolgbar?!

Socke
Lazarusforum e. V.
Beiträge: 3178
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: Enum-Type feststellen

Beitrag von Socke »

Falls du es vermeiden kannst, den Elementen der Aufzählung Werte zuzuweisen, kannst du in einem zweiten Parameter die RTTI-Informationen übergeben.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2822
Registriert: Fr 22. Sep 2006, 19:32
OS, Lazarus, FPC: Winux (Lazarus 2.0.10, FPC 3.2.0)
CPU-Target: x86, x64, arm
Wohnort: Berlin
Kontaktdaten:

Re: Enum-Type feststellen

Beitrag von m.fuchs »

LazProgger hat geschrieben:Grundsätzlich geht es darum, dass ich verschiedene Enums habe und je nach Enum-Typ verschiedene Konstanten addieren muss. Ich hatte mir erhofft das mit einer einfachen Typabfrage zu machen, um mir zu ersparen für jeden Enum-Typ eine eigene Funktion zu schreiben.
Warum? Was ist der Vorteil von einer Funktion gegenüber mehreren? Wenn du Codeverdeoppelung vermeiden willst, lagere den doppelten Code aus.
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

LazProgger
Beiträge: 63
Registriert: Di 11. Mär 2014, 00:33

Re: Enum-Type feststellen

Beitrag von LazProgger »

@Socke: Wie meinst du das mit den RTTI-Informationen?
m.fuchs hat geschrieben:Warum? Was ist der Vorteil von einer Funktion gegenüber mehreren? Wenn du Codeverdeoppelung vermeiden willst, lagere den doppelten Code aus.
Der allgemeine Code ist schon ausgegliedert, die Funktionen dienen schon einfach nur dazu den Enum in den richtigen Integer-Wert umzuwandeln.

Wieso ich mehrere Funktionen vermeiden möchte? Weil es mehrere Enums werden können und da wird es schnell sehr sehr viel. Nehmen wir den Aufruf mit nur 2 x 2 Enums, da hätten wir schon vier Funktionen:

Code: Alles auswählen

 
function FEnum(A:TEnum1; B: TEnum1): boolean; OVERLOAD;
function FEnum(A:TEnum1; B: TEnum2): boolean; OVERLOAD;
function FEnum(A:TEnum2; B: TEnum1): boolean; OVERLOAD;
function FEnum(A:TEnum2; B: TEnum2): boolean; OVERLOAD;
 
Da wäre es doch einfacher alles in eine Funktion zu schreiben und es mit einer simplen IF-Abfrage abzukürzen...

Innerhalb der Funktionen wird wie gesagt eine andere Funktion mit Integer-Werten aufgerufen.

Warf
Beiträge: 2135
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Enum-Type feststellen

Beitrag von Warf »

Das Problem ist, das jedes Enum den Speicher zur selben Art und Weise benutzt (Ganzzahlen) und daher ist eine Laufzeit Überprüfung genauso sinnreich wie die Abfrage ob 0 Jetzt ein Integer oder ein DWord ist

martin_frb
Beiträge: 588
Registriert: Mi 25. Mär 2009, 21:12
OS, Lazarus, FPC: Laz trunk / fpc latest release / Win and other
CPU-Target: mostly 32 bit

Re: Enum-Type feststellen

Beitrag von martin_frb »

Hier ist ein anderer weg. 2 oder mehr Argumente, und man muss nicht fuer jede Kombination eine overloaded Funktion schreiben.

Code: Alles auswählen

 
program Project1;
type
  TEnum1 = (e1a,e12);
  TEnum2 = (e2a,e22);
  TEnum3 = (e3a,e32);
 
  TFooArg = record
    Val, Id: Integer;
  end;
 
operator := (e: TEnum1): TFooArg;
begin
  Result.val := ord(e);
  Result.ID := 1;
end;
 
operator := (e: TEnum2): TFooArg;
begin
  Result.val := ord(e);
  Result.ID := 2;
end;
 
procedure Foo(a,b: TFooArg);
begin
end;
 
var
  a: TENum1;
  b: TENum2;
  x: TFooArg;
begin
  Foo(a,b);
end.
 
 

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2822
Registriert: Fr 22. Sep 2006, 19:32
OS, Lazarus, FPC: Winux (Lazarus 2.0.10, FPC 3.2.0)
CPU-Target: x86, x64, arm
Wohnort: Berlin
Kontaktdaten:

Re: Enum-Type feststellen

Beitrag von m.fuchs »

LazProgger hat geschrieben:Wieso ich mehrere Funktionen vermeiden möchte? Weil es mehrere Enums werden können und da wird es schnell sehr sehr viel. Nehmen wir den Aufruf mit nur 2 x 2 Enums, da hätten wir schon vier Funktionen:

Code: Alles auswählen

 
function FEnum(A:TEnum1; B: TEnum1): boolean; OVERLOAD;
function FEnum(A:TEnum1; B: TEnum2): boolean; OVERLOAD;
function FEnum(A:TEnum2; B: TEnum1): boolean; OVERLOAD;
function FEnum(A:TEnum2; B: TEnum2): boolean; OVERLOAD;
 
Da wäre es doch einfacher alles in eine Funktion zu schreiben und es mit einer simplen IF-Abfrage abzukürzen...
Das kommt darauf an. Wenn ich die Wahl habe zwischen vier Funktionen mit jeweils drei Zeilen oder einer Funktion mit zwanzig Zeilen, würde ich wohl die vier Funktionen vorziehen.
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

marcov
Beiträge: 1102
Registriert: Di 5. Aug 2008, 09:37
OS, Lazarus, FPC: Windows ,Linux,FreeBSD,Dos (L trunk FPC trunk)
CPU-Target: 32/64,PPC(+64), ARM
Wohnort: Eindhoven (Niederlande)

Re: Enum-Type feststellen

Beitrag von marcov »

Code: Alles auswählen

 
function FEnum(var A;var  B;TInfo1:PTypeinfo;Tinfo2:PTypeinfo): boolean; OVERLOAD;
begin
end
 
Und dann mit setordprop und korrespondierende getordprop die Funktion implementieren.

Der Nachteil ist natürlich das man es wie

Code: Alles auswählen

if FEnum(enumA,enumB,typeinfo(TEnumA),typeinfo(TEnumB)) then
anrufen muss.

(ich habe hier formal Parameters genutzt (var A; und VAR B;), hat als Vorteil das man jedes Typ mitgeben kann ohne Casting, aber das keine Konstanten)

Antworten