sind templates von template-spezialisierungen möglich?



  • hallo, also der titel sagt schon was die frage ist. aber nochmal in codezeilen etwas abstrahiert:

    template<class t>
    class foo
    {/*...*/};
    
    template<class t>
    t foo_func(t src){/*...*/};
    

    und ich möchte jetzt gerne sowas haben:

    template<class t>
    template<>
    foo<t> foo_func(foo<t> src){/*...*/};
    

    wenn ich es aber wie oben schreibe, meckert der kompiler rum, daher die frage ob es überhaupt möglich ist.



  • Die Frage ist, warum du überhaupt eine Spezialisierung einer Fukntion haben willst. Funktionen kann und sollte man überladen, denn Spezialisierungen werden bei der Überladungsauflösung nicht berücksichtigt, d. h. der Compiler sucht zuerst die passendste Überladung unter den konkreten Funktionen und Funktionstemplates und erst danach wird die passendste Spezialisierung des ausgewählten Funktionstemplates gesucht.



  • zum beispiel wenn ich einen allgemeinen algorithmus habe und den mit templates implementiere. nun habe ich für einen speziellen typ eine andere implementierung, die besser ist, dann kann ich das doch über die templatespezialisierung lösen oder nicht? dann wird immer der besser algoirthmus genommen, anstatt des allgemeinen. und wenn dieser spezielle typ auch wieder ein template ist dann brauch ich sowas wie eingangs beschrieben.



  • Du suchst nach partiellen Spezialisierungen. Diese gibt es aber für Funktionstemplates nicht. Überhaupt ist das Spezialisieren von Funktionstemplates im Allgemeinen eine schlechte Idee. Lies Dir den Text "Why Not Specialize Function Templates?" durch. Nutze Überladung statt Spezialisierung. Du darfst ruhig ein zweites Funktionstemplate mit demselben Namen definieren und das erste damit überladen.



  • In Modern C++ Design wird das Problem behandelt. Stichwort: Type2Type



  • template<class t>
    foo<t> foo_func(foo<t> src){/*...*/};
    

    Wie wär's damit?



  • FreakyBKA schrieb:

    hallo, also der titel sagt schon was die frage ist. aber nochmal in codezeilen etwas abstrahiert:

    template<class t>
    class foo
    {/*...*/};
    
    template<class t>
    t foo_func(t src){/*...*/};
    

    und ich möchte jetzt gerne sowas haben:

    template<class t>
    template<>
    foo<t> foo_func(foo<t> src){/*...*/};
    

    wenn ich es aber wie oben schreibe, meckert der kompiler rum, daher die frage ob es überhaupt möglich ist.

    Wie wärs mit:

    template<class t>
    t foo_func(t src)
    { 
        t myType=t(); 
        return foo_func( src, myType)
    };
    
    template<class t>
    t foo_func(t src, t type){/*dein nicht spezialisierter code*/};
    
    template<class t>
    t foo_func(t src, foo<t> type){/*deine spezialisierung*/};
    
    t foo_func
    

    Etwas umständlich, aber macht im Endeffekt genau was du wolltest... 🙂



  • Der Code ist unschön, abgehackt, unnötig und die dritte Funktion wird nie aufgerufen.



  • Wurde die "Standardvariante" schon erwähnt?
    Also ein Klassen-Template mit einer statischen Memberfunktion statt eines Funktionstemplates zu machen?

    template <class T>
    class foo_impl
    {
        static void do_foo(T t) { ... }
    };
    
    // spezialisierung
    template <class T>
    class foo_impl<vector<T> >
    {
        static void do_foo(vector<T> t) { ... }
    };
    
    // leitet nur weiter, wird nicht spezialisiert
    template <class T>
    void foo(T t)
    {
        foo_impl::do_foo(t);
    }
    


  • Ich hab' mich jetzt gerade gefragt, was man denn machen kann, wenn man eine Funktion ohne Argument hat, mit der z.B. der Typ der Variable abgefragt werden soll? Also etwas wie: is<int>()
    Da kann ich ja zuerst nichts mehr überladen. Ist da etwas in der Form wie's somec++ geschrieben hat die einzige Möglichkeit? Also ein Objekt von T zu instanzieren und dann so zu überladen?

    template<class T>
    class Foo
    {
      public:
        template<class B>
        bool is()
        {
          B valueType;
          return is(valueType);
        }
    
        template<class B>
        bool is( B )
        {
          return false;
        }
    
        bool is( T )
        {
          return true;
        }
    };
    

    Ne Funktion is<T>() gibts doch glaubs z.B. inner Boost Library, hab das mal innem Code Snippet gesehn, aber keine Ahnung wie die implementiert ist.



  • Vielleicht so etwas:

    template<typename T1, typename T2> clsas TypeCmpClass
    {
        public:
        enum
        {
            is_equal = false
        }
    }
    
    template<typename T> clsas TypeCmpClass<T, T>
    {
        public:
        enum
        {
            is_equal = true
        }
    }
    
    template<typename T> class foo
    {
        public:
        template<typename CmpT> bool is_type()
        {
            return TypeCmpClass<T, CmpT>::is_equal;
        }
    }
    

    Aber wozu brauchst du das?



  • wxSkip schrieb:

    Aber wozu brauchst du das?

    Nice! Beispielsweise für nen Container, in dem Objekte verschiedenen Typs gespeichert und abgerufen werden können über ein gemeinsames Interface, um sicherzustellen, dass die Zuweisungen zu richtigen Typen erfolgen und entsprechende Fehlermeldungen auszugeben falls nicht.



  • also es geht hier ehr weniger um eine spezialisierung von der klasse foo, viel mehr um die spezialisierung der funktion foo_func für eine template klasse, also in dem fall foo<t>. foo und foo_func haben primär nichts mit einander zu tun, war vllt etwas ungünstige bezeichnung. foo_func nimmt halt irgendeine klasse entgegen, aber für die speziellisierung das der template-typ irgendeine klasse der art foo<t> ist, soll halt die spezialisierung genommen werden, weil das zum beispiel dann schneller oder so geht.
    vllt ein kleines beispiel:

    template<class t>
    class array
    {/*halt nen container*/}
    
    template<class t>
    class vertex
    {/*...*/}
    
    //allgmeine sortierung
    template<class t>
    array<t> sort(array<t> const &src)
    {/*...*/};
    
    //spezielle sortierung für vertex-array
    template<t>
    template<>
    array<vertex<t> > sort(array<vertex<t> > const &src)
    {/*...*/};
    

    wenn ich die spezialisierung wie oben machen will, meckert er halt rum.



  • Und immer noch lautet die einfachste Antwort überladen statt spezialisieren...



  • nagut



  • FreakyBKA schrieb:

    nagut

    Was stört dich an der Lösung mit Überladung?


Anmelden zum Antworten