#ifdef -> einrücken oder nicht?



  • @Badestrand:
    jetzt bau in dein system mal bitte eine variante mit Qt und eine mit gtk ein.

    und wenn wir lustig sind noch jeweils einmal mit boost::thread und einmal mit nativen threads.

    Du kannst natuerlich jetzt
    src/win
    src/qt
    src/gtk
    src/lin
    src/lin_threads
    src/win_threads
    src/boost_threads

    machen. nur wie kompilierst du dann? klar, kann man ueber das build script sagen was man will, aber wie komplex wird das abfragen und das setzen der jeweiligen defines? das ist ja das interessante.
    ein
    build USE_NATIVE_THREADS USE_LINUX USE_GTK
    waere echt super zum builden. geht das mit vernuenftigen aufwand?

    das problem ist naemlich ploetzlich: was sind native threads? je nach plattform wieder etwas anderes...

    wuerde mich echt interessieren wie das vernuenftig geht



  • Shade Of Mine schrieb:

    jetzt bau in dein system mal bitte eine variante mit Qt und eine mit gtk ein.

    Bloß nicht 😃 Ne, ich kenne mich mit Makefiles und Buildsystemen kaum aus und ich schrieb ja auch, dass meine Variante ein "Spezialfall" war.

    Nur mal in's Blaue: Für die Auswahl
    src/lin_threads
    src/win_threads
    src/boost_threads
    könnte man doch ein kleines Bash-Skript schreiben, welches für jeden Parameter den enstprechenden Ordner kompiliert. Oder so. Oder nicht?



  • ich vermute, daß das, was ich brauche, einfach nur ein makefile ist, das an sich nur vor hat, die main.cpp zu compilieren. und außerdem bei jedem inkludierten header foo.hpp falls eine foo.cpp existiert, die auch noch. und halt alle, die davon inkludiert werden...



  • Danke erneut.

    Ich hab leider knivils Ansatz immer noch nicht verstanden. Er zeigte zwar das Makefile aber die Ordnerstruktur bzw. ein kleines Beispiel nicht...sind da die #ifdefs einfach zwischen dem code ? Oder ist der code meist doppelt vorhanden ? Evtl. war das bei badestrand so bei der cross-plattform-lösung?

    ich vermute, daß das, was ich brauche, einfach nur ein makefile ist, das an sich nur vor hat, die main.cpp zu compilieren. und außerdem bei jedem inkludierten header foo.hpp falls eine foo.cpp existiert, die auch noch. und halt alle, die davon inkludiert werden...

    😕

    bitte was? Bzw. in welchem zusammenhang?

    Und noch eine Frage an Shade:
    so wie ich das verstanden habe hast Du ja jetzt nur ein einziges #ifdef welches in einer separaten datei liegt und welches die flag-abhängige datei aus dem Ordern X/xyz.hpp includiert. Somit musst Du ja in jedem File/Klasse die Zugriff auf eine Funktion aus xyz.hpp hat das komplette file includieren. Damit ist doch dann immer das komplette file includiert und nicht nur die spezielle funktionsdeklaration die gerade in der klasse z.B. verwendet werden soll. Habe ich das richtig verstanden?



  • *push



  • Nochmal an Shade:

    Das heißt du hast in einem Ordner variante1 ein file namens variante1.hpp liegen und in einem ordner variante2 ein file variante2.hpp liegen.
    Dort wo deine hauptsourcen also die ifdef-freien sourcen liegen liegt auch ein verzweigungsfile xyz.hpp welches das eine ifdef hat und entweder variante1/variante1.hpp includiert oder eben variante2/variante2.hpp.

    Somit stehen in variante1.hpp ALLE Fuktionen die du durch bedingte kompilierung verwendest. Umgekehrt auch in variante2.

    Frage: Jetzt wird doch aber immer eines der beiden files komplett eingebunden. Nehmen wir an variante1.hpp hat 10 verschiedene funktionsdefinittionen und du brauchst in der main.cpp nur eine davon. Dann werden ja trotzdem alle 10 oben eingebunden oder?
    Sehe ich das richtig? So wird in jedem file das auf die eine variante zugreift das komplette variante1-file includiert. ist doch bissal zu viel des guten doer nicht?



  • die trennung mit #ifdef/#include nach verwendeten implemetierungen und die trennung nach zweck durch verschiedene dateinamen sind völlig unabhängig voneinander.



  • die trennung mit #ifdef/#include nach verwendeten implemetierungen und die trennung nach zweck durch verschiedene dateinamen sind völlig unabhängig voneinander.

    sorry ich versteh dich net volkard, kannst des nochmal anders sagen? danke



  • Er meint, dass du zwei unabhängige Probleme vermischst:

    1. Bedingte Kompilierung, also je nach Konfiguration soll anderer Code kompiliert werden
    2. Ob eine Header-Datei evtl in mehrere aufgesplittet werden sollte

    Oder andersrum:

    Jetzt wird doch aber immer eines der beiden files komplett eingebunden. Nehmen wir an variante1.hpp hat 10 verschiedene funktionsdefinittionen und du brauchst in der main.cpp nur eine davon.
    Die Situation hast du bei fast jeder Header-Datei und hat nüscht mit der bedingten Kompilierung (#ifdef/..) zu tun.



  • hmm ok...

    auf diese art und weise muss ich aber wenn ich z.B. nur eine einzelne variable holen will die z.B. in der parallelen umgebung über eine spezielle lib-funktion realisiert wird schon eine ganze funktion schreiben.

    D.H. also ich muss für auch nur eine anweisung eine funktion schreiben. Wenn die funktion jetzt im programm vielleicht 10 mal gebraucht wird macht es doch nicht sinn die als inline zu setzen oder? Oder "darf" bzw. sollte ich das in dem fall sogar?

    Wenn ich jetzt für 100e anweisungen die ich NICHT zusammenfassen kann funktionen habe, bremst das ja etwas... versteh ich das richtig?



  • und dann versteh ich nicht warums mir gerade alles um die ohren haut.

    folgendes in pseudocode:

    //xyz.hpp
    
    #ifdef MYFLAG
    #    include xyz1/xyz.hpp
    #else
    #    include xyz2/xyz.hpp
    #endif
    
    #include "xyz.hpp"
    #include "classA.hpp"
    
    int main()
    {
    
    }
    
    //classA.hpp
    
    #include "xyz.hpp"
    

    er sagt multiple definitions of <einer funktion>. Also irgendwie funktioniert die header-einbindung nicht. warum denn? ich habe die include-guards überall drin. mein xyz.hpp sieht z.B. so aus:

    #ifndef IMPL_xyz_H
    #define IMPL_xyz_H
    
    void
    Init(int& n, int& m)
    {
        m = 1;
        n = 0;
    }
    
    #endif
    


  • ich bräuchte hier nochmal Hilfe. Ich dachte Deklaration und Definition sollten im Header stehen. So bekomme ich aber Konflikte mit multiple definitions...



  • gruppa schrieb:

    ich bräuchte hier nochmal Hilfe. Ich dachte Deklaration und Definition sollten im Header stehen. So bekomme ich aber Konflikte mit multiple definitions...

    Ich kenn jetzt nicht den ganzen Thread, aber das hört sich nach Linker-Fehler an. Normalerweise packt man die Deklaration in den Header, die Definition/Implementation in das cpp-File...



  • Ja ich verstehe das Problem und auch Deine Antwort. Ich frage mich nur wie "Shade Of Mine" es jetzt gemeint hat weil er irgendwo geschrieben hat dass er alles in einen header packt...oder meinte er nur die deklaration?



  • gruppa schrieb:

    Ja ich verstehe das Problem und auch Deine Antwort. Ich frage mich nur wie "Shade Of Mine" es jetzt gemeint hat weil er irgendwo geschrieben hat dass er alles in einen header packt...oder meinte er nur die deklaration?

    Du hast eine ODR Verletzung. Du musst inline verwenden.



  • ah vielen dank - jetzt ists mir klar



  • wollte mich etwas einlesen bezüglich inline und ich lese immer wieder von leuten:

    pumuckl schrieb: Alles in allem ist Inlining eine Optimierung, und frühzeitige Optimierungen sind Mist

    gilt es jetzt nur darum die ODR zu erzwingen durch inline? wenn ja und inline unter umständen was langsamer machen könnte wäre es viellecht sinnvoller da doch in header und implementierung zu splitten?

    Mir ist einfach folgendes nicht klar: Warum sagt der eine es ist Mist, wenn der andere sagt er benutzt es regelmässig.



  • gruppa schrieb:

    Mir ist einfach folgendes nicht klar: Warum sagt der eine es ist Mist, wenn der andere sagt er benutzt es regelmässig.

    inline hat 2 bedeutungen. inlining von funktionen ist das was pumuckl meint.
    das schlüsselwort inline ist aber dazu da um die ODR zu umgehen.

    siehe: http://fara.cs.uni-potsdam.de/~kaufmann/?page=GenCppFaqs&faq=ODR#Answ



  • @shade:

    wie löst du wenn du ganze code-teile (funktionen) flag-abhängig haben willst in einer klasse...z.B. sowas?

    //implementation der klassen-funktionen von class MyClass
    
    void MyClass::foo()
    {
      // do something
    }
    
    #ifdef MYFLAG
    
    void MyClass::bar()
    {
       //do something
    }
    
    #endif
    


  • gruppa schrieb:

    wie löst du wenn du ganze code-teile (funktionen) flag-abhängig haben willst in einer klasse...z.B. sowas?

    Ne, ich trenne nur auf Klassen Ebene, nicht innerhalb einer Klasse.

    Maximal wenn eine Funktion mit einer bestimmten Konfiguration nicht funktioniert dass ich ein static_assert in die Funktion einbaue.

    Aber im Prinzip versuche ich auf sehr abstrakter Ebene zu trennen und lebe durchaus auch mit code verdopplung.

    was du aber zB machen koenntest: in der header datei je nach flags andere header dateien inkludieren die die gewuenschte funktionalitaet bereitstellen...

    im prinzip ist das ziel, mit #if immer nur #includes zu schachteln und keinen direkten code.

    bedenke dass #include nur dumme textersetzung ist, du kannst zB:

    class MyClass {
    #include "myclass_interface_a.hpp"
    #include "myclass_interface_b.hpp"
    #include "myclass_interface_c.hpp"
    };
    

    schreiben..


Anmelden zum Antworten