Teilspezialisierung von Funktions-Templates



  • Abend.

    //Funktions-Template
    template< int N, class T >
    void test()
    {
    }
    
    //Spezialisierung 1
    template< >
    void test< 3, float>()
    {
    }
    

    Soweit funktioniert das ja ganz gut. Bekomme ich jetzt auch irgendwie eine Teilspezialisierung t< 3, T[variabel] > hin?


  • Mod

    krabbels schrieb:

    Abend.

    //Funktions-Template
    template< int N, class T >
    void test()
    {
    }
    
    //Spezialisierung 1
    template< >
    void test< 3, float>()
    {
    }
    

    Soweit funktioniert das ja ganz gut. Bekomme ich jetzt auch irgendwie eine Teilspezialisierung t< 3, T[variabel] > hin?

    nein. Partielle Spezialisierung ist nur mit Klassentemplates möglich. Du könntest also das Funktionstemplate dazu nutzen, einen Funktor aufzurufen, und diesen dann entsprechend partiell spezialisieren.



  • Auch sehr häufig sieht man die Methode aus "Modernes C++ Design" (k.A. wo es erfunden wurde):

    template <typename T>
    struct type2type
    {
        typedef T type;
    };
    
    template <typename T>
    void do_something (T const& p)
    {
        do_something (type2type<T> (), p);
    }
    
    void do_something (type2type<double>, double param);
    
    void do_something (type2type<int>, int param);
    

    Ist letztlich aber dasselbe.



  • .filmor schrieb:

    Auch sehr häufig sieht man die Methode aus "Modernes C++ Design" (k.A. wo es erfunden wurde):...

    Sorry, magst Du das kurz erläutern ?
    Ich verstehe nicht, was es mit der 2Parameter-version von do_something() auf sich hat ....

    Gruß,

    Simon2.



  • Könnte man nicht auch einfach eine statische Methode einer Klasse benutzen (die man ja partiell spezialisieren kann)?

    //Funktions-Template
    template<int N, class T>
    class Wrapper
    {
        public:
        static void test()
        {
        }
    };
    
    //Spezialisierung
    template<class T>
    class Wrapper<3, T>
    {
        static void test()
        {
        }
    }
    

    Das hätte halt den Nachteil, dass bei Klassen die Template-Argumente nicht aus irgendwelchen Argumenten bestimmt werden können...

    Die Methode von .filmor verstehe ich aber auch nicht...

    Felix



  • Simon2 schrieb:

    Ich verstehe nicht, was es mit der 2Parameter-version von do_something() auf sich hat ....

    Das ist in etwa die Methode, die man auch bei Iterator"spezialisierungen" nutzt: Eine (hypothetische) Funktion advance mit zwei Parametern ruft eine zweite Funktion advance_impl auf, und übergibt ihr als dritten Funktionsparameter eine Instanz des Iteratoren-Tag. Nun überlädt man advance_impl für das allgemeinste Iterator-Tag, sowie für jedes Tag, für das man Optimierungen anbieten kann. Da beim Lookup einer Funktion die Überladung mit den am besten passenden Parametern genommen wird, wird diese dann aufgerufen.

    template< typename It >
    void advance( It& it, size_t off )
    {
        advance_impl( it, off, typename It::iterator_category() );
    }
    
    template< typename It >
    void advace_impl( It& it, size_t off, std::forward_iterator_tag )
    {
        while (off--) ++it;
    }
    
    template< typename It >
    void advance_impl( It& it, size_t off, std::random_access_iterator_tag )
    {
        it += off;
    }
    

    Ergänzung: Der Typ des Zusatzparameters muss natürlich nicht in einer Vererbungshierarchie stecken, das sichert hier zusätzlich nur ab, dass z.B. bidirectional Iteratoren auf die Forward-Funktion zurückfällt.



  • Phoemuex schrieb:

    ...
    Das hätte halt den Nachteil, dass bei Klassen die Template-Argumente nicht aus irgendwelchen Argumenten bestimmt werden können...

    ... aber das geht bei argumentlosen Funktionstemplates sowieso nicht. 😉

    Aber das bringt mich auf eine andere Idee: Wie wär's mit einen template-Member ?

    template <int N>
    struct Wrapper {
       template <typename FType>
       static void f(FType);
    };
    
    template <>
    struct Wrapper<3> {
       template <typename FType>
       static void f(FType) {
          // hier "3-spezifisches" und FType-generelles
       }      
    };
    

    Damit kann man wenigstens einen Typen (FType) beim Aufruf automatisch bestimmen lassen...

    LordJaxom schrieb:

    ...

    Ahaaa !! 💡
    Danke, das hatte mir noch gefehlt! 😋 👍

    Gruß,

    Simon2.


Anmelden zum Antworten