Makros redifinieren bzw. für Programmteile deaktivieren
-
Hallo,
aus konkreten Anlass habe ich eine Frage zu Makros... Wie man Makros schreibt (bin absolut kein Fan davon) und sie deaktiviert (#undef) ist mir dabei aber klar...
Worum geht es ganz konkret geht: Ich habe einige allgemeiner Headerklassen für ein Projekt geschrieben, und eine minimale Testanwendung dafür erstellt. Klar das ich dafür nicht unnötige Header einbinde. Der Code dort ist auch sauber in Namensräume etc. untergliedert, wie man es halt macht...
Diese Header wurden nun woanders verwendet, und es kommt wie es kommen muss, ein Makro überschreibt einen meiner Funktionsnamen (Wie ich die windows.h doch liebe, mein Problem ist aber nicht WinAPI-Spezifisch)...
Okay, ein undef wäre möglich, aber da dieses Makro in einen anderen Teil des Projektes Verwendung findet, müsste es anschließend auch redifiniert werden. Gibt es dazu eine Möglichkeit wo man nicht die gesamte Definition wiederholen muss? (Ich würde ungern irgendwelche Bibliotheksspezifikas in den allgemeinen Headern stehen haben).
cu André
P.S: Wie sehr ich doch Makros (mit Ausnahme von Includes/Includeguards) hasse...
-
Eventuell mußt du da die Reihenfolge überdenken, in der die Header eingefügt werden (erst dein Header mit den Definitionen und danach die windows.h (oder ähnliches). Allerdings solltest du dabei bedenken, daß du dann keinen Zugriff auf die vermakro-ten Bezeichner aus deiner Lib mehr hast.
(ja, der Präprozessor ist noch dümmer als der Compiler - und sich mit dem auf ein verwertbares Ergebnis zu einigen kann manchmal ein Krampf sein)
-
CStoll schrieb:
(ja, der Präprozessor ist noch dümmer als der Compiler - und sich mit dem auf ein verwertbares Ergebnis zu einigen kann manchmal ein Krampf sein)
Naja, bleibt mir wohl nur die Möglichkeit meine Sachen umzunennen... Vor allem vorträglich und vorausschauend wenn es nach unserem Chefentwickler geht (Sprich: es ist mein Fehler wenn irgendeine Methode so wie ein Makro aus irgendeiner Lib heißt, und ich habe gefälligst mit kryptischen Kürzeln vor den Namen zu arbeiten damit sowas nicht auftritt...).
cu André
-
Da hat dein Chef aber keine Ahnung von der Materie - Namespaces und ähnliches wurden "erfunden", um sich solche kryptischen Namenszusätze zu ersparen. Da sollte man die Leute nicht belohnen, daß sie sie ignorieren (oder schlimmer, mit Präprozessor-Hilfe das Design anderer Leute in Stücke schießen).
-
Naja, ... kommt drauf an. Wenn du deine Funktionen im "Grossbuchstaben-mit-Underscores-dazwischen" Stil ("RA_RU_RICK") benennst würde ich sagen dein Chef(programmierer) hat Recht und der "Fehler" liegt bei dir.
Bei anderen Kollisionen... hm.
Eine IMO gute Möglichkeit wäre es diejenigen Libraries welche die "bösen" #defines enthalten in eigene Libraries zu kapseln, die nur genau die Funktionalität nach aussen zur Verfügung stellen die benötigt wird. Und zwar so dass man die Headers der "bösen" Libraries nicht in Client Code zu inkludieren braucht (mit Hilfe des PIMPL Patterns oder wie auch immer).
Eine andere Möglichkeit, wenn es nur um ein paar wenige Funktionen geht wie z.B. das von windows.h definierte "min" und "max" ist, diese Makros einfach zu #undef-en.
Oder man setzt alle Stellen wo man die Funktion statt des Makros braucht in Klammern:void foo() { int a = (std::min)(a, b); // verwendet das Template, nicht das Makro! } // oder auch: class bar { void (max)() // hässlich, geht aber auch { } };Oder man verzichtet einfach auf so blöde Libraries die meinen tausende dumme #defines mit Namen die leicht kollidieren verwenden zu müssen

-
hustbaer schrieb:
Naja, ... kommt drauf an. Wenn du deine Funktionen im "Grossbuchstaben-mit-Underscores-dazwischen" Stil ("RA_RU_RICK") benennst würde ich sagen dein Chef(programmierer) hat Recht und der "Fehler" liegt bei dir.
Ganz Konkret geht es um eine kleine Klasse die Meldungen verwaltet, um eine konkrete Meldung abzurufen habe ich eine Methode "GetMessage" genannt. Wirklich verwerflich von mir

hustbaer schrieb:
Eine IMO gute Möglichkeit wäre es diejenigen Libraries welche die "bösen" #defines enthalten in eigene Libraries zu kapseln, die nur genau die Funktionalität nach aussen zur Verfügung stellen die benötigt wird...
Keine Chance, das würde als Zeitverschwendung abgetan. Zudem ist üblich alle möglichen Includes in ein precompiled Header zu stopfen und so Projektglobal einzubinden... Undef geht wie oben genannt leider nicht, da ein anderer Teil eben auf jede Makros zugreift.
hustbaer schrieb:
Oder man setzt alle Stellen wo man die Funktion statt des Makros braucht in Klammern:...
Diese Möglichkeit ist mir tatsächlich neu. Wann werden Makros ersetzt und wann nicht? Hatte Makros als dümmer in Erinnerung. Leider kann ich es jetzt nicht überprüfen ob es mit dem Compiler läuft, da ich privat kein VC6 habe (Privat VS2005 Std, VS2008 Express; mein Comeau ist derzeit leider nicht eingerichtet).
hustbaer schrieb:
Oder man verzichtet einfach auf so blöde Libraries die meinen tausende dumme #defines mit Namen die leicht kollidieren verwenden zu müssen

Würde ich gerne, aber steht nicht zur Debatte

cu André
P.S: Nehme ein Buch wie "Antipattern" in die Hand, schlage eine beliebige Seite auf und nicke dann, das ist ungefähr der Projektstil (Netter gesagt "historisch gewachsene Anwendung"
)
-
Ich kenne die genauen Regeln wann Makros ersetzt werden und wann nicht auch nicht. Aber ich weiss dass man die Erweiterung von function-style Makros verhindern kann indem man den "Nicht-Makronamen" wie gezeigt klammert.
Blöderweise geht das aber nur mit function-style Makros, also welche die mit#define MAKRONAME(x) ...oder ähnlichem definiert werden. Wenn bei dir#define GetMessage GetMessageAoder ähnliches steht -> Pech.Andere Möglichkeit: nenn deine Funktion getMessage (kleiner Anfangsbuchstabe). Natürlich auch alle anderen Funktionen entsprechend mit kleinem Anfangsbuchstaben.
Ich hatte ein ähnliches Problem mal mit LoadImage (wird von windows.h definiert) - da hab ich die Funktion (Member einer Klasse) einfach LoadImageX genannt. Nicht seht toll, aber es war mir in dem Moment einfach zu blöd nach besseren alternativen zu suchen.
Keine Chance, das würde als Zeitverschwendung abgetan. Zudem ist üblich alle möglichen Includes in ein precompiled Header zu stopfen und so Projektglobal einzubinden... Undef geht wie oben genannt leider nicht, da ein anderer Teil eben auf jede Makros zugreift.
Sind das nun selbstgeschriebene Makros ("in house" Code), oder sind es Makros von einer 3rd-party-library? Wenn es selbstgeschriebene Makros sind dann sollen verdammtnochmal die Makros umbenannt werden. Für sowas nimmt man Visual Assist X oder ein ähnliches Tool, dann ist das in ein paar Minuten getan (ok, vielleicht ein paar Stunden, kommt auf die Projektgrösse an).
In userer Firma haben wir die Regel dass sämtliche Namen von #defines im "Grossbuchstaben-mit-Underscores" Stil zu sein haben, und mit dem Library-Namen wo sie definiert werden zu prefixen sind. Wenn die Library also Foo-Lib heisst, dann dürfte ein Makro FOO_LIB_GET_MESSAGE heissen, aber sicher nicht einfach nur GetMessage.
Wenn es natürlich um 3rd-party-libraries geht ist das etwas schwieriger.
----
Ansonsten: wenn dir der Chef(programmierer) sagt du darfst deine Funktion nicht GetMessage nennen, dann frag den einfach wie genau du sie sonst nennen sollst. Wenn er dann "Susi" sagt dann nenn sie Susi, ist das sein Problem, nicht deins.
-
hustbaer schrieb:
Andere Möglichkeit: nenn deine Funktion getMessage (kleiner Anfangsbuchstabe). Natürlich auch alle anderen Funktionen entsprechend mit kleinem Anfangsbuchstaben.
Eine Möglichkeit, aber dies wäre wieder inkonsequent zu meinem Restlichen Code, ja im Endeffekt habe ich die Methode umbenannt...
hustbaer schrieb:
Sind das nun selbstgeschriebene Makros ("in house" Code), oder sind es Makros von einer 3rd-party-library?
Alles 3rd-party, ja zumindest bei der Großschreibung für Makros sind wir uns einig...
hustbaer schrieb:
Für sowas nimmt man Visual Assist X oder ein ähnliches Tool...
Es mag für einen der beiden Compiler/IDE's die wir verwenden tatsächlich noch entsprechende Tools geben, aber für einen anderen ist jede Hoffnung vergeblich
Mit letzteren muss ich mich meist rumärgern.Aber dennoch danke
cu André