Compile-Time-Trigger



  • nwp3 schrieb:

    Ich dachte dafür gibt es enable_if.

    Nein, das ist was völlig anderes. enable_if wird auch größtenteils für SFINAE eingesetzt.

    Bashar schrieb:

    Natürlich wird das optimiert, das sind ja Konstanten.

    👍
    Das Beste ist, einfach ein if-Statement zu benutzen. Ist am lesbarsten, kürzesten und wahrscheinlich auch am schnellsten was das Kompilieren angeht (von der Laufzeit her optimiert der Compiler bei allen Varianten wahrscheinlich gleich viel weg).



  • Wenn du ein Maniac bist, noch eine Frage: Kannst du die bool-Argumente als Literale geben? Dann kannst du bestimmt was mit dem Präprozessor und Boost-PP anstellen.



  • Sowas ginge auch noch, aber auch da wäre die Kompilier-Zeit garantiert länger:

    #include <iostream>
    
    #define IF(b, ...)
    
    template<bool B, void(*ptr1)()>
    struct if_execute;
    
    template<void(*ptr1)()>
    struct if_execute<true, ptr1>
    {
    	static void(* const exec)();
    };
    
    template<void(*ptr1)()>
    void(* const if_execute<true, ptr1>::exec)() = ptr1;
    
    template<void(*ptr1)()>
    struct if_execute<false, ptr1>
    {
    	static constexpr void exec() {} // Funktion ist constexpr - existiert zur Laufzeit nicht mehr.
    };
    
    void doThat() { std::cout << "doThat!"; }
    void doThis() { std::cout << "doThis!"; }
    
    template<bool doThis_, bool doThat_>
    void manipulateNumber()
    {
    	if_execute<doThis_, doThis>::exec();
    	if_execute<doThat_, doThat>::exec();
    }
    
    int main()
    {
    	manipulateNumber<true, false>();
    }
    


  • Ok, danke, dann hat sich das erledigt. 🙂

    Sone:
    Präprozessor, wie das? Der kommt doch vor Template-Ebene.

    Es ist schon so, dass zur Laufzeit eine Methode aufgerufen wird, welche die Parameter analysiert und dementsprechend immer eine bestimmte Funktion mit gewissen Template-Parametern aufruft (innerhalb der Schleife ist der Template-Parameter aber konstant, darum geht's).

    Die Festlegung, welche Version aufgerufen wird, findet also durchaus zur Laufzeit statt, nur eben auf einer performance-unkritischen Ebene.



  • Präprozessor, wie das? Der kommt doch vor Template-Ebene.

    Genau. Aber wenn die Argumente vor der Template-Ebene bekannt sind, also schon direkt vom Codeäffchen gegeben sind, dann kannst du schon auf Text-Ebene entweder ein Statement da stehen haben oder nicht. Und da muss der Compiler nichts mehr machen.



  • Ok, aber ich muss eben schon Gebrauch davon machen, dass er mehrere Versionen der Funktionen automatisch generiert, die ich dann eben je nach Laufzeit-Check-Ergebnis aufrufen kann. Das vervielfältigt den intern generierten Code zwar, aber zur Compilezeit ist eben nicht so viel bekannt, dass man die Funktion auf eine Variante reduzieren könnte.

    Daher ist die Variante im OP wohl perfekt für mich. 🙂



  • Ich hab bei der ganzen Geschichte das Gefühl, dass ein Compiler das eventuell auch ohne Templates können sollte. Wäre einen Versuch wert.



  • Wie wärs mit Vererbung und klassischer Polymorphie?

    class Base
    {
    public:
    	virtual void doIt() = 0;
    };
    
    class doThis : public Base
    {
    public:
    	virtual void doIt()
    	{
    		// lets doThis shit
    	}
    };
    
    class doThat : public Base
    {
    public:
    	virtual void doIt()
    	{
    		// lets doThat shit
    	}
    };
    
    void foo(bool boolVar)
    {
    	Base * doIt;
    	if( boolVar )
    		doIt = new doThis();
    	else
    		doIt = new doThat();
    
    	doIt->doIt();
    }
    

    Wenn du es richtig machst, wäre das am Anfang eine Fallunterscheidung und dann nie mehr etwas in der Richtung, kein if kein nix (ausser der Pointerdereferenzierung).
    Die Dynamik hast du damit auch zur Laufzeit.
    Und das kann man bestimmt noch ein wenig weiter treiben mit templates.



  • Skym0sh0: Weißt du was für ein (hier unnötiger) Overhead entsteht, sobald Polymorphie im Spiel ist?
    Das ist übrigens auch leicht Offtopic, weil es ja um Compile-Zeit geht.



  • Bashar schrieb:

    Ich hab bei der ganzen Geschichte das Gefühl, dass ein Compiler das eventuell auch ohne Templates können sollte. Wäre einen Versuch wert.

    Meinst du, den boolschen Wert als Parameter? Eine Funktion wie die wird wahrscheinlich geinlined, und dann sieht der Compiler ja auch wieder ein if(true/false) .



  • Ja. Nein.

    Das Problem ist schon ein bisschen komplizierter. Er hat ungefähr sowas:

    bool b = ...;
    for (...) {
       f(b);
    }
    
    void f(bool b) {
      if (b) ...
    }
    

    Und möchte nicht, dass dieses if jedesmal ausgeführt wird. Im Prinzip muss das ganze so transformiert werden:

    bool b = ...
    if (b)
      for (...) {
        f_b_is_true();
      }
    else
      for (...) {
        f_b_is_false();
      }
    

    Das kann man mit Templates machen, so dass man die beiden f's nicht separat implementieren muss. Ich kann mir aber vorstellen, dass ein Compiler diese Transformation, die man sich ja wie das Herausfaktoriseren einer Schleifeninvariante vorstellen kann, selbst durchführen kann. Es ist nicht ganz trivial, insbesondere stell ich mir die Abwägung, ob das im Einzelfall gemacht werden soll, nicht ganz einfach vor, aber wer weiß...



  • Nennt sich Loop unswitching. Hat GCC schon in Version 3.4 eingeführt.



  • Skym0sh0:
    Teile einer Funktion sollen sich anders verhalten. Das erreiche ich hiermit nicht. Und selbst wenn, Polymorphie in einer zeitkritischen Schleife, die rasen muss wie Bolt, ist nun wirklich das Gegenteil von einer guten Lösung.

    Bashar:
    Dein Code trifft exakt das, was ich gerade tue. Mein Problem habe ich lediglich etwas reduziert dargestellt. Die eigentliche Hauptfunktion mit der Schleife ist sehr lang und ruft zwischendurch kleinere Funktionen auf. Die kleineren Funktionen benötigen die Variable zum prüfen eben auch. Es gibt somit mehrere verschachtelt aufgerufene Funktionen, die _true() oder _false() wären. Geinlined wird hier nichts, das sind keine Wenigzeiler mehr.

    Möglicherweise kann der Compiler das tatsächlich auch ohne Templateparameter auflösen, was natürlich weit besser als die Template-Lösung wäre. Aber ohne Sicherheit will ich diesen Schritt auf keinen Fall gehen.


Anmelden zum Antworten