![]() |
Delphi-Version: XE2
class operator OnesComplement ? o.O
Ja ähhhhhhhh,
im Grunde weiß ich was diese Operation machen sollte, ich kann sie sogar implementieren.
Delphi-Quellcode:
Aber praktisch hab ich keine Ahnung wie ich das verwenden soll. :oops:
type
TTest = record x: Integer; class operator OnesComplement(a: TTest): TTest; end; Rein praktisch ist es ja eine Art "BitwiseNot", aber
Delphi-Quellcode:
wird nicht angenommen.
x := not X;
Nja, bin zufällig auf diesen Operator gestoßen, aber bisher scheint ihn noch keiner zu kennen. Weder die OH, nur die hat ja eh nie eine Ahnung, aber auch Google weiß von nix :shock: und in der DP und Co. kennt Dieses scheinbar auch noch keiner? :lol: Ach ja, nur zur Info, das sind übrigens alle Operatoren, welche der XE3-Compiler kennt: Explicit Implicit Add Subtract Multiply Divide Modulus LogicalAnd LogicalOr LogicalXor LogicalNot LeftShift RightShift BitwiseAnd BitwiseOr BitwiseXor Equal GreaterThan LessThan NotEqual GreaterThanOrEqual LessThanOrEqual Inc Dec Negative Positive OnesComplement (gut, den Positive-Operator hab ich auch noch nie verstanden, da er mathematisch praktisch nutzlos ist und die Operatoren, welche ich mir mal gewünscht hab, gibt es leider immernoch nicht :cry: ) NOT wird ja komischer Weise nut von LogicalNot behandelt, selbst wenn es mal ein "BitwiseNot" sollte (
Delphi-Quellcode:
), was es aber nicht gibt.
i := not 1
Und warum es überhaupt Logical- und Bitwise.Operatoren gibt, ist auch unklar, da man das in Delphi nicht via Code entscheiden kann, außer das Booleans Logical sein sollten und der Rest Bitwise. (wie in C die |, ||, & und && gibt's halt nicht) |
AW: class operator OnesComplement ? o.O
Hallo Himitsu,
bitweises invertieren läßt sich auch durch folgende Operation durchführen: bei Bytes:
Delphi-Quellcode:
x := x xor $FF
bei Word:
Delphi-Quellcode:
x := x xor $FFFF
bei Integer:
Delphi-Quellcode:
x := x xor $FFFFFFFF
usw. mfg Markus |
AW: class operator OnesComplement ? o.O
Ich wollte es nicht nutzen ... war nur neugierig, da es das ja scheinbar gibt, aber es noch keiner kenn :zwinker:
bei Bytes:
Delphi-Quellcode:
oder
x := not x
Delphi-Quellcode:
x := x xor not 0
bei Word:
Delphi-Quellcode:
oder
x := not x
Delphi-Quellcode:
x := x xor not 0
bei Integer:
Delphi-Quellcode:
oder
x := not x
Delphi-Quellcode:
x := x xor not 0
usw. oder eben LogicalNot nutzen und darin einfach bitweise Invertieren :angle2: |
AW: class operator OnesComplement ? o.O
Da ich grade wieder drüber gestopert bin und meinen alten Post in Google fand... (falls es auch Andere finden)
OnesComplement ist in Delphi nicht nutzbar (auch wenn man es dort implementieren kann). Es ist eigentlich für den C++Builder gedacht und .NET kennt den Befehl ebenfalls. LogicalNot ist also das "logische not" (Boolean) und OnesComplement das "binäre not" (Integer). Außerdem gibt es auch noch die undokumentierten True und False. Für
Delphi-Quellcode:
implementiert man somit das
if MyRecord then
Delphi-Quellcode:
, wobei man natürlich auch einen Implicit-Cast nach Boolean verwenden könnte. :stupid:
MyRecord.True
Schachsinnig ist, daß der Delphicompiler bei
Delphi-Quellcode:
nicht das
if not MyRecord then
Delphi-Quellcode:
oder
MyRecord.False
Delphi-Quellcode:
benutzt, sondern es zwanghaft nach
not MyRecord.True
Delphi-Quellcode:
übersetzen will, was beim Fehlen des LogicalNot schön knallt.
MyRecord.LogicalNot.True
Delphi-Quellcode:
TRecord = record
class operator OnesComplement(A: TRecord): TRecord; class operator True(A: TRecord): boolean; class operator False(A: TRecord): boolean; end; |
AW: class operator OnesComplement ? o.O
Zitat:
|
AW: class operator OnesComplement ? o.O
IstWar halt geheim. :lol:
Hier nochmal alles, was die Kompiler (bis XE7) kennen: ![]() (fehlt nur noch Initialize, Finalize und CopyRecord :cry:) |
AW: class operator OnesComplement ? o.O
Oder man erlaubt endlich einen impliziten Standard-Konstruktoraufruf (und Destruktor) für Records. Warum das nicht implementiert ist habe ich nie verstanden.
|
AW: class operator OnesComplement ? o.O
OK, ob es Initialize und Finalize heißt (siehe die Funktionen in der System.pas) oder Contrucor (ohne Parameter) und Destructor, ist ja erstmal egal. (aber stimmt, deinee Namen klingen besser)
Es werden für Records bereits diese Methoden ausgeführt (siehe System.pas), aber es gibt keine Weiterleitung zu "eigenen" Implementationen, was sich durch die zentralen Stellen hätte bestimmt ganz leicht implementieren lassen. |
AW: class operator OnesComplement ? o.O
Zitat:
und was ist Convert? |
AW: class operator OnesComplement ? o.O
Zitat:
Delphi-Quellcode:
Beim Copy werden "direkte" Inhalte kopiert (Move) und Referenzen von Interface, String, dyn. Array, Variant und ARC-Objecten behandelt,
var
A, B: TMyRecord; begin // Initialize/Create ... A := B; // Copy (B -> A) + Finalize (altes A) ... end; // Finalize/Destroy aber eigene Behandlungen kann man nicht durchühren, wie z.B. das darin verlinkte Interface/Objekt zu klonen, was man oft benötigen könnte. |
AW: class operator OnesComplement ? o.O
Nur mal kurz zusammengeschludert:
Delphi-Quellcode:
program RecordFinalizer;
{$APPTYPE CONSOLE} {$R *.res} uses Generics.Collections, SysUtils, TypInfo, DDetours; type TFinalizer = procedure (Self: Pointer); TCopyOperator = procedure (Dest, Source: Pointer); var Finalizers: TDictionary<PTypeInfo,TFinalizer>; CopyOperators: TDictionary<PTypeInfo,TCopyOperator>; type TMyRecord = record private s: string; public procedure Destroy; class procedure Copy(var dest, source: TMyRecord); static; end; { TMyRecord } class procedure TMyRecord.Copy(var dest, source: TMyRecord); begin dest.s := 'Copy: ' + source.s; end; procedure TMyRecord.Destroy; begin Writeln(s); Writeln('TMyRecord.Destroy'); end; procedure Main; var r, r2: TMyRecord; begin r.s := 'Hello World'; r2 := r; end; function GetFinalizeRecord: Pointer; asm mov @Result, offset System.@FinalizeRecord end; function GetCopyRecord: Pointer; asm mov @Result, offset System.@CopyRecord end; var FinalizeRecord: function(p: Pointer; typeInfo: Pointer): Pointer; CopyRecord: procedure (Dest, Source, TypeInfo: Pointer); function FinalizeRecordHook(p: Pointer; typeInfo: Pointer): Pointer; var finalizer: TFinalizer; begin if Finalizers.TryGetValue(typeInfo, finalizer) then finalizer(p); if Assigned(FinalizeRecord) then Result := FinalizeRecord(p, typeInfo); end; procedure CopyRecordHook(Dest, Source, TypeInfo: Pointer); var copyOperator: TCopyOperator; begin if CopyOperators.TryGetValue(TypeInfo, copyOperator) then copyOperator(Dest, Source) else CopyRecord(Dest, Source, TypeInfo); end; begin Finalizers := TDictionary<PTypeInfo,TFinalizer>.Create; Finalizers.Add(TypeInfo(TMyRecord), @TMyRecord.Destroy); CopyOperators := TDictionary<PTypeInfo,TCopyOperator>.Create; CopyOperators.Add(TypeInfo(TMyRecord), @TMyRecord.Copy); FinalizeRecord := InterceptCreate(GetFinalizeRecord, @FinalizeRecordHook); CopyRecord := InterceptCreate(GetCopyRecord, @CopyRecordHook); try Main; except on E: Exception do Writeln(E.ClassName, ': ', E.Message); end; Readln; ReportMemoryLeaksOnShutdown := True; InterceptRemove(@FinalizeRecord); InterceptRemove(@CopyRecord); Finalizers.Free; CopyOperators.Free; end. |
AW: class operator OnesComplement ? o.O
Zitat:
Immer wenn ich "Deinen" Sourcecode lese, habe ich das Gefühl ich habe keine Ahnung von Delphi... :stupid: Bedeutet das ich kann doch den RecordCopy "überladen"? Problem ist:
Delphi-Quellcode:
Leider ist Foo[3] danach mit 'Soll nicht geändert werden' belegt, da "nur" die Referenzen Kopiert werden.
type
TFoo = record A : Array of String; end; Var Foo : TFoo; Procedure MachNixMitFoo; var Merk : TFoo; begin Merk := Foo; Foo[3] := 'Soll nicht geändert werden'; Machwas(Foo); Foo := Merk; end; Bietet "Deine" Routine da einen Lösung? Mavarik |
AW: class operator OnesComplement ? o.O
Das ist das eines der Probleme, die ich damit lösen wollte.
Für dynamische Arrays gibt es kein CopyOnWrite, wenn man schreibend auf ein Feld des dynamischen Arrays zugreift. Bei Strings (die intern auch nur aufgemotzte dynamische Arrays sind) wird vor jedem Schreibzugriff auf ein Char (da ja
Delphi-Quellcode:
) sichergestellt, daß RefCount auch 1 ist.
array[1..length] of char
(durch Aufruf von ![]() |
AW: class operator OnesComplement ? o.O
Zitat:
D.h. bei allen vom Compiler generierten CopyRecord aufrufen in deiner gesamten Anwendung läuft der extra Dictionary Lookup. Ich bin ja schon recht großzügig, Code nicht als Hack sondern als "geschickte Ausnutzung der Mechanik" zu bezeichnen, aber das ist definitiv ein Hack - und zwar ein gewaltiger - da muss man schon wissen, was man damit anstellt :) Zitat:
Delphi-Quellcode:
Jo, müsste gehen.
class procedure TFoo.Copy(var dest, source: TFoo);
begin dest.a := System.Copy(source.a); end; Gibt allerdings noch eine andere Möglichkeit, die genauso funktioniert, wie bei Strings:
Delphi-Quellcode:
type
TFoo = record private a: array of string; function GetItem(i: Integer): string; inline; procedure SetItem(i: Integer; const Value: string); inline; public property Items[i: Integer]: string read GetItem write SetItem; default; end; function GetArrayRef(A: Pointer): Integer; inline; type // geliehen aus der System.pas PDynArrayRec = ^TDynArrayRec; TDynArrayRec = packed record {$IFDEF CPUX64} _Padding: LongInt; {$ENDIF} RefCnt: LongInt; Length: NativeInt; end; begin Result := NativeInt(A); if Result <> 0 then Result := PDynArrayRec(PByte(A) - SizeOf(TDynArrayRec))^.RefCnt; end; function TFoo.GetItem(i: Integer): string; begin Result := a[i]; end; procedure TFoo.SetItem(i: Integer; const Value: string); begin if GetArrayRef(a) > 1 then a := System.Copy(a); a[i] := Value; end; |
AW: class operator OnesComplement ? o.O
Am schönsten wäre es ja, wenn man auf sowas wie deim GetArrayRef verzichten könnte.
Für Strings hat man das ja inzwischen auch eingebaut. ![]() Copy(arr) ruft System.DynArrayCopy auf, aber du kannst stattdessen, und ohne RefCount vorher zu prüfen, System.DynArrayUnique ausrufen (prüft selbst intern das RefCount) Aber am "optimalsten" wäre es halt, wenn Emba solche Methoden in der RTTI aufnimmt, also direkt als Flag/Referenz, so wie z.B. beim [Weak]-Status, und dann in den originalen Funktionen ganz schnell zu schauen, ob es was zum Aufrufen gibt, welches per Class-Operator dort eingetragen wurde. |
AW: class operator OnesComplement ? o.O
Zitat:
Ich suche eher eine Lösung für den Umstiegt von Short auf Long und Array[L..H] nach Array of... Beispiel:
Delphi-Quellcode:
Der "Rest" der Software hat keine Ahnung von der Umstellung... Abgesehen von den entsprechenden SetLength.
type
TFooOld = Record Bla : Integer; Blub : Array[0..10] of Shortstring; end; TFooNeu = Record Bla : Integer; Blub : Array of String; // Oder auch TStringDynArray end; So ALLE
Delphi-Quellcode:
müssen sich genau verhalten wie vorher... Ohne
var
A,B : TFooNeu; begin ... A := B; end;
Delphi-Quellcode:
aufrufen zu müssen....
A := B.Clone
Mavarik |
AW: class operator OnesComplement ? o.O
Blub als Array-Property deklarieren und dort im Setter ein UniqueArray.
|
AW: class operator OnesComplement ? o.O
Zitat:
Einfach Zähne zusammen beißen, die Record Types vernünftig kapseln und dann is gut. |
AW: class operator OnesComplement ? o.O
Zitat:
Gab es das schon in D2007? Momentan mach ich immer ein Copy im Setter... |
AW: class operator OnesComplement ? o.O
k.A.
In XE(1) hab ich es nicht gefunden ... dachte aber das gibt's schon viel länger. Vielleicht unter einem anderem Name, aber auch da fand ich auf die Schnelle nix. |
AW: class operator OnesComplement ? o.O
Zitat:
![]() Kannste dir aber auch selbst bauen, denn da steckt keine Compilermagic hinter - array und typeInfo übergeben und gut. |
AW: class operator OnesComplement ? o.O
Daß da nix drin war, hatte ich gesehn, aber es ist halt praktischer, wenn man "nur TypeInfo und Pointer" übergeben muß, denn dann muß man sich nicht selber um das "böse" rumgepointere kümmern, um an den RefCount zu kommen.
(oder man ruft Copy einfach nur immer blind auf, egal ob der RefCount schon kleiner 2 ist) |
AW: class operator OnesComplement ? o.O
Zitat:
Delphi-Quellcode:
und sehr viele "Moves" enthalten.. Da hält der Compiler leider nicht an.
Procedure Foo(Var Data);
|
AW: class operator OnesComplement ? o.O
Zitat:
|
AW: class operator OnesComplement ? o.O
:thumb:
|
AW: class operator OnesComplement ? o.O
Zitat:
Ein paar Longstrings in einem Record haben jetzt schon 6 Monate mit nahezu 18/7 Programmierung gekostet... Bei Projekten > 500 Units und > 2 Mio. Zeilen ist nix "mal eben" gemacht. Da gibt es auch keine Inseln die man mal eben umbaut... Jede Änderung zieht sich durch mindestens 350 Units. Immer wenn schon der Grep mehr als 10000 Stellen ausgibt, sucht man nach besseren Lösungen. Besonders, da es 5000 Stellen gibt die weder grep noch der Compiler findet... Mavarik |
AW: class operator OnesComplement ? o.O
Zitat:
![]() |
AW: class operator OnesComplement ? o.O
Zitat:
Man muß seine Codes weiterentwickeln, sich neue Wege überlegen und kann die schöne Abwärtskompatibilität genauso vergessen, wie die problemlose Wiederverwendbarkeit in allen Platformen. |
AW: class operator OnesComplement ? o.O
Zitat:
Aber wir reden von Compiler D2007 auf XE7 und dann ggf. noch auf 64Bit... Kaum machbar bzw. der Aufwand einfach seht groß. Hier muss man sich gut überlegen ob es das Wert ist! Der Eigenantrieb ist natürlich schon groß, wenn man auf der einen Seite iOS&Android programmiert mit Generics, Parallel.Library und anonymen Proceduren und dann wieder zurück geht um die Windows Version zu pflegen und "alles" fehlt. Mavarik |
AW: class operator OnesComplement ? o.O
Zitat:
Auch andere Projekte meiner Kunden, die z.B. von D5 nach XE3 portiert wurden, machten zumindest in diesem Punkt keine Probleme. Der Löwenaufwand steckt dort meistens im Aufräumen der im Laufe der Jahre verwachsenen Architektur. Wenn man sich frühzeitig von PChar-Arithmetik, AnsiStrings und ShortStrings verabschiedet hat, sind solche Umstellungen eigentlich kaum der Rede wert. Es hilft wirklich, seinen Code ständig so zu pflegen, wie manche Leute ihr Auto. |
AW: class operator OnesComplement ? o.O
Zitat:
|
AW: class operator OnesComplement ? o.O
Zitat:
|
AW: class operator OnesComplement ? o.O
Catch-22:
... man müßte das System tiefgreifend ändern, um es testfähig zu machen. ... ohne ein testfähiges System zu haben, kann man es nicht tiefgreifend ändern. :stupid: |
AW: class operator OnesComplement ? o.O
Zitat:
![]() |
AW: class operator OnesComplement ? o.O
Zitat:
Diese Angst beruht aber oft darauf, dass es dunkle Ecken im System geht, die man nicht kennt oder versteht. Hat man Code, den man versteht, der abgetestet ist und wo keine schwarze Magie drin steckt, dann ist eine Änderung genauso painless wie nen Öl- oder Reifenwechsel. Da die meisten Programmierer aber immer noch vorgehen wie Meister Röhrig, sieht der Code halt auch oft "zusammengetüdelt" aus. |
AW: class operator OnesComplement ? o.O
Zitat:
|
AW: class operator OnesComplement ? o.O
Zitat:
Was machst du denn, wenn du ein altes vergammeltes Haus erbst? Einziehen und drauf hoffen, dass es dir nicht aufn Kopf fällt? Oder es renovieren? |
AW: class operator OnesComplement ? o.O
Zitat:
Alle 4 Wochen gibts Windows-Updates (OS-API-Verhaltensänderungen), Alle 2 Woche Adobe-Updates (PDF-Integration), alle 5 Jahre wird der Rechner ausgetauscht (Neues OS, Ander HW mit unterschiedlichen Treiberverhalten), alle 5 wird ein ERP/PLM/CRM-System mit dem man Arbeitet durch ein anderes ersetzt... |
AW: class operator OnesComplement ? o.O
Zitat:
Ich wollte eigentlich nur aufzeigen, daß fehlende Pflege nicht immer in unserer Hand liegt. Das "Renovieren eines vergammelten Hauses" ist genau das, was ich eigentlich ausdrücken wollte. Danke für diese Metapher :thumb: |
AW: class operator OnesComplement ? o.O
Zitat:
Edit: [OT] Man(n) hat irgendwo im Jahr 1984 mit dem Code angefangen... Turbo Pascal 1.5/2.0 Aus dieser Zeit existiert noch Code der bis heute unverändert ist. Der Tag hat nur 24h, die Woche nur 7 Tage... Die Kundenanzahl wächst, die Wünsche auch... Also bleibt Code so lange unangetastet, bis dafür Bedarf besteht. Dann Mitte 96 die versuchen mit Delphi 1 den DOS-Bildschirm in einem Windowsfenster zu emulieren verworfen. Denn Delphi 2 ist rausgekommen... Also schnell im RAD-Style die nötigen Fenster zusammen geklickt... Button -> Doppelklick -> Code rein... Genau wie es in JEDER Präsentation gezeigt wurde... JEDER hat so programmiert... Es soll mir keine erzählen er hätte mit Delphi 2 MVVM gemacht und nur gegen Interfaces programmiert... Also: Der Tag hat nur 24h, die Woche nur 7 Tage... Die Kundenanzahl wächst, die Wünsche auch... Also bleibt Code so lange unangetastet, bis dafür Bedarf besteht. Dann kommt plötzlich jemand auf die Idee das "alle" Strings plötzlich Unicode "seien müssen"... Und schon bleiben unzählige Projekte auf D2007... Hätte man es 1984 wissen können? Hätte man früher etwas machen müssen? Alles Fragen nach der verschütteten Milch... Ein Monster-Projekt auf MVVM umbauen? Eher nicht... Das wäre eine Neuentwicklung.. Dem Kunden ist es auch egal wo der Code ist, wenn er einen Button drückt... Es bezahlt keiner für "schönen" Code, damit wir Programmierer uns um Kreis stellen und gegenseitig auf die Schulter klopfen können. Denn: Der Tag hat nur 24h, die Woche nur 7 Tage... Die Kundenanzahl wächst, die Wünsche auch... Also bleibt Code so lange unangetastet, bis dafür Bedarf besteht. Und die ein oder andere "dunkle Ecken im System" bleibt uns noch ein bisschen erhalten... Aber hin und wieder wird eine beseitigt... Alles wird gut... Edit: [/OT] Mavarik |
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:52 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