Problem mit templates



  • Folgende Situation

    Ich habe zwei Funktionen f, g mit derselben Signatur. Ich will nun bewerkstelligen, dass ich mit templates die eine oder die andere aufrufen kann:

    template <????>
    void foo()
    {
      // hier soll abhängig von ???? f oder g aufgerufen werden
    }
    

    Wie mache ich das?



  • Eine mögliche Variante:

    struct call_f_tag {};
    struct call_g_tag {};
    template<> void foo<call_f_tag>() { f(); }
    template<> void foo<call_g_tag>() { g(); }
    
    // Aufruf:
    foo<call_f_tag>();
    foo<call_g_tag>();
    

    (ungetestet)

    Die iterator_tags funktionieren auf ähnliche Art und Weise.



  • Geht es auch so, dass ich die Funktion foo nur einmal definiere?



  • Ich würde die Funktionen als Funktoren anlegen, dann ist das recht einfach:

    class f
    {
        void operator() (void)    
        {
        /*
         *
         */
        }
    };
    
    class g
    {
        void operator() (void)
        {
        /*
         *
         */
        }
    };
    
    template<typename T>
    void foo()
    {
        T funk;
        funk();
    }
    
    // Aufruf:
    foo<g>();
    foo<f>();
    


  • Warum soll es denn ein template sein? Übergib doch einen Funktionszeiger. Oder einen bool "call_f".

    void foo(bool call_f) {
      if(call_f) f();
      else g();
    }
    

    Das ganze geht auch als template 😛

    template <bool call_f>
    void foo() {
      if(call_f) f();
      else g();
    }
    

    Ansonsten ist Spezialisierung (wie von templater gezeigt) ein üblicher Weg.



  • Man kann auch Funktionszeiger oder -referenzen als Template-Parameter verwenden.
    Ich ziehe allerdings die Funktor-Variante vor, wenn sonst nichts dagegen spricht.

    p.S.:
    Die "tag" Variante von "templater" macht IMO Sinn, wenn man das Template "zumachen" will, also dem User die Möglichkeit nehmen jeden beliebigen Funktor/Funktionszeiger zu übergeben.


Anmelden zum Antworten