Funktionstemplate mit beliebig vielen Parametern



  • GmbH schrieb:

    ...Sind Ellipsen bei Templateparametern nicht aber schöner/sicherer?...

    Ob sie schöner sind ist Geschmackssache, sicherer wenn du wirklich Elipsen meinst, sind sie nicht.

    Wenn wir aber nicht von Elipsen, sondern von Funktionen die zur Compilezeit vollständig aufgelöst werden reden (Über Variadic Templates in C++0x, soweit dies geht), und zur Laufzeit aber keine Elipsen mehr sind, magst du recht haben.

    cu André


  • Mod

    GmbH schrieb:

    Schade das dies im aktuellen Standard wohl nicht geht.

    Jedenfalls nicht ohne einigen Schreibaufwand, wobei man mit boosts preprocessor-Bibliothek wahrscheinlich viel einsparen kann - auf Kosten der Lesbarkeit: Man könnte für jeden Fall N=0,1,... des Funktionstyps mit N Parametern spezialisieren:

    template<typename T> class foo;
    template<typename R> class foo< R() >;
    template<typename R, typename P1> class foo< R (P1) >;
    template<typename R, typename P1, typename P2> class foo< R (P1,P2) >;
    template<typename R, typename P1, typename P2, typename P3> class foo< R (P1,P2,P3) >;
    template<typename R, typename P1, typename P2, typename P3, typename P4> class foo< R (P1,P2,P3,P4) >;
    // usw.
    

    Dabei muss es nicht unbedingt notwendig sein, das gesamte Template zu spezialisieren, wenn der Unterschied nur bei Memberfunktionen besteht, könnte man die Spezialisierung, resp. Überladung auch an dieser Stelle durchführen, ggf. Unterstützung durch SFINAE per enable_if.
    Ansonsten hilft tatsächlich nur das Warten auf den nächsten Standard oder, wenn es noch nicht Produktionscode sein muss, kann man auch mit g++ 4.3 experimientieren:

    template<typename T> class foo;
    template<typename R, typename ... P> class foo< R (P...) >;
    // usw.
    

    Was leider auch im nächsten Standard nicht möglich sein wird, ist eine derartige Flexibilität mit anderen Dingen als Typen zu ermöglichen. Mir würde zum Beispiel so ein einfacher "Funktorisierer" gefallen (Funktionen schreiben ist nun mal bequemer):

    template<auto /* meine Erfindung: soll jedes beliebige non-type-Argument akzeptieren */> struct Functor;
    template<typename R, typename ... P> struct Functor< R (*F)(P...) >
    {
        typedef R result_type;
        template<typename ... Args>
        R operator()(Args&&... args) const
        {
            return F( std::forward< Args >( args ) ... );
        }
    };
    

    Sehr viele Templates, die mit non-type-Parametern arbeiten, haben die Form

    template<typename T, T x> ...
    

    Dabei wäre die explizite Nennung des Typs eigentlich überflüssig - die notwendigen Mechanismen zur Typdeduktion besitzt der Compiler sowieso.


Anmelden zum Antworten