#ifdef -> einrücken oder nicht?



  • ja und ja.



  • Danke erneut für die Antwort. Könnte man das auch irgendwie über Makros realisieren. Also ein Makro setzen in der main z.B. und dann die verzweigung in separatem file oder so ähnlich? Ginge das und wenn ja - wie?



  • gruppa schrieb:

    Danke erneut für die Antwort. Könnte man das auch irgendwie über Makros realisieren. Also ein Makro setzen in der main z.B. und dann die verzweigung in separatem file oder so ähnlich? Ginge das und wenn ja - wie?

    Dafür hast du ja die proxy dateien.
    foo.cpp sieht zB so aus:

    #ifdef X
    #  include "X/foo.cpp"
    #elif Y
    #  include "Y/foo.cpp"
    ...
    


  • bitte nicht wundern warum ich so nachbohre...es interessiert mich einfach:

    zu schadeofmine: hmm...meinst Du jetzt dass das so gesehen das gleiche ist? Über Makros und über die auslagerung der ifdefs?

    Ich würde gerne noch folgendes wissen und hoffe auf die Geduld der Leser 🙂

    * Wenn ich jetzt über eine bedingte Kompilierung eine leere Methode einbinde (wie z.B. das finalize() vom vorigen post) - ist das von der Performance her bremsed. Natürlich nur unwesentlich aber wenn es z.B. sehr oft vorkommen würde...? Nur aus Interesse die Frage...

    * Würde man vielleicht sowas auch über function-pointer lösen - also über ein if-else einen function-pointer zur laufzeit definieren und dann über diesen in die richtige methode switchen? Oder wäre das von der performance her langsamer oder gar unübersichtlicher?



  • gruppa schrieb:

    * Wenn ich jetzt über eine bedingte Kompilierung eine leere Methode einbinde (wie z.B. das finalize() vom vorigen post) - ist das von der Performance her bremsed. Natürlich nur unwesentlich aber wenn es z.B. sehr oft vorkommen würde...? Nur aus Interesse die Frage...

    ja, bremst, wenn finalize() nicht inline ist und in einer anderen cpp-datei wohnt und der compiler sie nicht einfach wegoptimieren kann.
    wenn sie in einem header wohnt und inline ist, kostet das gar nix.



  • und wenn ich über -O3 kompiliere - werden da nicht alle funktionen als inline behandelt? Oder red ich jetzt völligen quatsch?



  • gruppa schrieb:

    und wenn ich über -O3 kompiliere - werden da nicht alle funktionen als inline behandelt? Oder red ich jetzt völligen quatsch?

    inline bedeutet nicht das der code schneller wird, er kann auch langsamer werden...

    was volkard aber gemeint hat ist, wenn der compiler die funktion inlinen kann und sieht dass die funktion leer ist und spart es sich code zu generieren.

    je nachdem wie clever ein compiler ist, desto mehr funktionen könnte er inlinen. der vc++ zB kann funktionen über mehrere .cpp Dateien hinweg inlinen - was aber jeder kann ist wenn die funktion in einem header steht.



  • ah ok- danke für die Antwort.

    jetzt mal wieder ne blöde frage: eine funktion im header - damit ist gemeint sie soll einfach roh in einem header-file (z.B. variante1.hpp) liegen?

    Wo kann eine Funktion noch liegen wenn nicht im header? Als methode einer Klasse?



  • gruppa schrieb:

    Wo kann eine Funktion noch liegen wenn nicht im header? Als methode einer Klasse?

    Die funktions definition muss im header liegen damit die compiler problemlos geinlined werden können. die deklaration muss sowieso im header stehen.

    definition:
    void foo() {}

    deklaration:
    void foo();



  • Shade Of Mine schrieb:

    Dafür hast du ja die proxy dateien.
    foo.cpp sieht zB so aus:

    #ifdef X
    #  include "X/foo.cpp"
    #elif Y
    #  include "Y/foo.cpp"
    ...
    

    Sowas wuerde ich nie machen, da ich es als viel sauberer empfinde, es ueber entsprechende Build-/Linkeinstellungen (Skripte, what ever) zu steuern. Ich finde es einfach haesslich.



  • knivil schrieb:

    Sowas wuerde ich nie machen, da ich es als viel sauberer empfinde, es ueber entsprechende Build-/Linkeinstellungen (Skripte, what ever) zu steuern. Ich finde es einfach haesslich.

    dh du musst dauernd die build scripte anpassen...?

    das wäre zB für mich ein no-go.
    der vorteil von meiner #include variante ist, das alles transparent abläuft. du kompilierst die foo.cpp und die flags definieren was genau passiert.

    denn wozu muss man wissen dass foo.cpp in wirklichkeit 3 unterschiedliche implementierungen hat? und vorallem wann diese verwendet werden. diese logik würde ich zB nie in ein buildscript packen. da sie sich nämlich konstant ändern kann. und build scripte sind in meinen augen etwas konstantes woran man nicht unnötig viel herum manipulieren sollte...



  • dh du musst dauernd die build scripte anpassen...?

    Sagen wir mal "erweitern" und sollte nicht schwerer sein als ein weiteres #ifdef in deiner cpp-Datei hinzuzufuegen (kommt auf die Flexibilitaet deines Buildsystems an, k.A. was Visual Studio da so anbietet). Die Buildskripte musst du bei deiner Variante auch anfassen, denn wo soll X, Y etc definieren werden, wenn nicht als Compileroption.

    wissen dass foo.cpp in wirklichkeit 3 unterschiedliche implementierungen hat?

    Ja, musst du auch sonst, steht ja in deiner cpp-Datei. Musst du aber auch wieder nicht, da ja das Buildskript alles macht. Wenn foo 3 unterschiedliche Implementierungen fuer 3 unterschiedliche Plattformen (oder Features) hat, dann steht in den Buildskripten das drin, welche uebersetzt und gelinkt werden soll. Und ob es nun in einer cpp-Datei drin steht oder im Buildskript ist erstmal vom Aufwand egal. Ist es aber ausserhalb definiert, besteht eine klare Trennung zwischen Code und Build-/Linkoptionen. Bestehenden Code moechte ich nicht anfassen, wenn ich z.B. eine Plattform unterstuetzen moechte (zumindestens in einer idealen Welt).



  • @knivil: kannst du ein minimales beispiel bringen wie du das machen würdest - interessiert mich... wäre nett danke



  • Dieses minimale Beispiel zeigt ein makefile, wie es aussehen koennte (prinzipiell). Mittels "make ogl" wuerde man die Version bauen, deren Rendererimplementation OpenGl benutzt, mittels "make directx" halt fuer DirectX. Das dargestellte ist sehr vereinfacht. Auch sieht man hier 2 Zeilen, die fast gleich aussehen -> "Codeduplikate" -> eher schlecht. Das kann alles umgangen werden, mit zusaetzlichen Variablen etc.

    Auch ist make ein eher krudes Tool, so dass damit Arbeiten nicht wirklich Spass macht. Andere Alternativen sind autoconf (das makefiles fuer die ensprechende Plattform/Features erzeugt) oder Apache Ant. Es gibt viele verschiedene Tools. Ein Vorteil ist z.B. dass man mit einem Aufruf auch Dokumentation, Bilddaten ... erzeugen lassen, automatische Tests starten kann etc. Fuer den Heimeinsatz ist das aber ueberdimensioniert, auch sollte man sich ueberlegen, ob es einem Arbeit abnimmt. Deswegen bleibe ich bei make, obwohl es eher hoelzern und kryptisch ist. Z.B. nutze ich make insbesondere beim Schreiben von Texten mit Latex.

    OBJECTS = ... many .o files
    
    ogl: $(OBJECTS) RendererOpenGl.o
      g++ $(OBJECTS) RendererOpenGl.o -o app_ogl
    
    directx: $(OBJECTS) RendererDirectX.o
      g++ $(OBJECTS) RendererDirectX.o -o app_direct
    


  • danke kniviel aber leider versteh ichs noch nicht.

    So muss man doch komplett doppelten code schreiben oder nicht? Ich muss doch sowohl für opengl also auch directx dann eine funktionsfähige codebasis haben?

    kannst du das auf unser minimalbeispiel übertragen?



  • da ich meine makefiles nicht dauernd pflegen will, werde ich Shades vorschläge übernehmen.



  • knivil schrieb:

    dh du musst dauernd die build scripte anpassen...?

    Sagen wir mal "erweitern" und sollte nicht schwerer sein als ein weiteres #ifdef in deiner cpp-Datei hinzuzufuegen (kommt auf die Flexibilitaet deines Buildsystems an, k.A. was Visual Studio da so anbietet). Die Buildskripte musst du bei deiner Variante auch anfassen, denn wo soll X, Y etc definieren werden, wenn nicht als Compileroption.

    Ich definiere einfach einen ordner in dem die .cpp Dateien liegen. Wenn neue hinzukommen, kommen eben neue hinzu, dafür muss ich kein build script anpassen.

    vorallem wenn ich mit VStudio arbeite, einfach nur die .cpp Datei zum Projekt hinzufügen und fertig. Das ist das tolle an proxy dateien: 0 aufwand.

    wissen dass foo.cpp in wirklichkeit 3 unterschiedliche implementierungen hat?

    Ja, musst du auch sonst, steht ja in deiner cpp-Datei. Musst du aber auch wieder nicht, da ja das Buildskript alles macht. Wenn foo 3 unterschiedliche Implementierungen fuer 3 unterschiedliche Plattformen (oder Features) hat, dann steht in den Buildskripten das drin, welche uebersetzt und gelinkt werden soll.

    Bei mir eben nicht da ich mich nicht auf 2-3 targets limitiere. ich könnte zB 5 sets haben (openMP ja/nein, directX/openGL/GDI, zielplattform OS X/Windows/Linux,..) und mit meiner variante kann ich einfach sagen:
    OpenMP + Linux + OpenGL und das wars.
    oder eben
    Windows + DirectX und das wars.

    kann das deine variante auch? 😉

    Bestehenden Code moechte ich nicht anfassen, wenn ich z.B. eine Plattform unterstuetzen moechte (zumindestens in einer idealen Welt).

    du fasst nur die proxy datei an.
    aber das ist natürlich witzlos, weil für eine neue plattform eine riesen menge an änderungen in der praxis nötig sind.



  • Shade Of Mine schrieb:

    vorallem wenn ich mit VStudio arbeite, einfach nur die .cpp Datei zum Projekt hinzufügen und fertig. Das ist das tolle an proxy dateien: 0 aufwand.

    Ja, das geht auch, diese Zeile nimmt mir viel Arbeit ab:

    .SUFFIXES: .cpp .o
    
    .cpp.o:
    	$(CC) -c $(CFLAGS) $(INCLUDE) -o $@ $<
    

    Wie gesagt, kryptisch.

    (openMP ja/nein, directX/openGL/GDI, zielplattform OS X/Windows/Linux,..) [...]
    kann das deine variante auch? 😉

    Ja.

    Wie gesagt, im Hobbybereich oder bei kleinen Projekten macht es vielleicht kaum Sinn. Genauso wenig schreibt jemand seine Unittests vorher, etc ... .

    da ich meine makefiles nicht dauernd pflegen will

    Es ist wie alles, vorher gut geplant und staendige Aenderungen sind nicht noetig.

    Ich habe nicht umsonst gesagt, dass es nur ein Minimalbeispiel ist, es ist nichts woran man make messen sollte. Ausserdem gibt es viele Alternativen.



  • knivil schrieb:

    da ich meine makefiles nicht dauernd pflegen will

    Es ist wie alles, vorher gut geplant und staendige Aenderungen sind nicht noetig.

    Ich habe nicht umsonst gesagt, dass es nur ein Minimalbeispiel ist, es ist nichts woran man make messen sollte. Ausserdem gibt es viele Alternativen.

    oder ich schreib #ifdef in die c++-headerdatei und lass das makefile einfach wie es ist. 💡 👍
    es compiliert einfach alle *.cpp-dateien durch. ich wills nähmlich auch nicht dauernd pflegen, wenn ich ne klasse hinzufüge oder lösche.



  • knivil schrieb:

    (openMP ja/nein, directX/openGL/GDI, zielplattform OS X/Windows/Linux,..) [...]
    kann das deine variante auch? 😉

    Ja.

    Und wie?

    Bedenke, du kannst jede beliebige kombination an sets verwenden. und die sets sollen beliebig erweiterbar bleiben.

    ich muss keinen gedanken an sowas verschwenden, es funktioniert automatisch. eine beschreibung wie du das bei dir implementieren würdest würde mich da sehr interessieren.

    Es ist wie alles, vorher gut geplant und staendige Aenderungen sind nicht noetig.

    neues set - neue erweiterung.
    oder wie soll das funktionieren?


Anmelden zum Antworten