Problem mit Templates in Templates



  • Hi erstmal,

    ich kann mir irgendwie nicht vorstellen, dass so etwas simples wie
    Das hier nicht funktionieren kann:

    struct Allocator
    {
    	template<class T>
    	static T* alloc(int size){ return new T[size]; }
    
    	template<class T>
    	static void free(T* data){ delete[] data; }
    };
    
    template<class T, class TAllocator>
    struct Class
    {
    	 Class(){ data = TAllocator::alloc<T>(20); } // syntaxfehler hier
    	~Class(){ TAllocator::free<T>(data);       } // und hier
    	T* data;
    };
    
    int main()
    {
    	Class<float,Allocator> cl;
    }
    

    Der gcc sagt mir hier "error: expected primary-expression before ‘>’ token"
    Hab ich irgendwas vergessen oder geht das wirklich nicht 😕

    Danke
    Plassy



  • Ist das wirklich der Original-Code? Also copy und paste?

    Der MSVC 8 meckert nicht.



  • Ich habs rausgefunden... sieht schon etwas befremdend aus:

    template<class T, class TAllocator>
    struct Class
    {
    	 Class(){ data = TAllocator::template alloc<T>(20); }
    	~Class(){ TAllocator::template free<T>(data);       }
    	T* data;
    };
    

    Nachdem ich etwas mit "typename" rumgespielt hab, hat mir der gcc gesagt, dass ichs doch bitte so schreiben soll.
    Ich benutze den gcc 4.1.0.

    Ist das wirklich die korrekte c++ syntax... weiß das jemand??

    Danke
    Plassy



  • Ja ist es.



  • Könntest das auch so machen, damit gibst du quasi am Anfang bekannt, dass deine benutzte Klasse wiederum ein Template ist:

    template<typename T, template <typename> class TAllocator>
    struct Class
    {
         Class(){ data = TAllocator::alloc<T>(20); }
        ~Class(){ TAllocator::free<T>(data);       }
        T* data;
    };
    


  • Das behebt den Fehler nicht, damit sagst du, dass Allocator, also die Klasse, einen Template-Parameter besitzt.
    Genaugenommen führt das zu nem weiteren Fehler, denn jetzt kann man Allocator nicht mehr an Class übergeben.

    Der einzige richtige Weg hier ist das template-Schlüsselwort. Denn nur damit kann man dem Compiler sagen, dass hier ne Template-Funktion aufgerufen wird.



  • Warum machst du nicht die struct zum template? Wirst ja wohl immer beide Methoden als Paar brauchen:

    template<class T>
    struct Allocator
    {
        static T* alloc(int size){ return new T[size]; }
    
        static void free(T* data){ delete[] data; }
    };
    
    template<typename T, template <typename> class TAllocator>
    struct Class
    {
         Class(){ data = TAllocator<T>::alloc(20); }
        ~Class(){ TAllocator<T>::free(data);       }
        T* data;
    };
    
    int main()
    {
        Class<float,Allocator> cl;
    }
    


  • Hmm, ich finde das Design sowieso komisch. Ist es wirklich erforderlich, TAllocator als Template zu betrachten? IMHO ergäbe folgende Umsetzung mehr Sinn (aufbauend auf THX' Vorschlag, 'Allocator' zu einem Template umzuschreiben):

    template<typename T>
    struct Allocator {
        static T* alloc(int size){ return new T[size]; }
    
        static void free(T* data){ delete[] data; }
    };
    
    template<typename T, typename TAllocator>
    struct Class {
         Class(){ data = TAllocator::alloc(20); }
        ~Class(){ TAllocator::free(data);       }
        T* data;
    };
    
    int main()
    {
        Class<float,Allocator<float> > cl;
    }
    


  • und jetzt mach mal

    int main()
    {
        Class<int,Allocator<float> > cl;
    }
    

    Kann nach mehreren Änderungen ja passieren, und schon hast du nen tollen Fehler.
    Darum template template parameter, kann man nicht falsch instanzieren.


  • Mod

    THX 1138 schrieb:

    und jetzt mach mal

    int main()
    {
        Class<int,Allocator<float> > cl;
    }
    

    Kann nach mehreren Änderungen ja passieren, und schon hast du nen tollen Fehler.
    Darum template template parameter, kann man nicht falsch instanzieren.

    Das ist nicht sehr überzeugend. Es ist kaum anzunehmen, dass jeder spezielle Allokator, den man schreiben will, so allgemein ist, dass man ihn als Template schreiben kann und will. Zudem kann ein solcher Templateallokator keine zusätzlichen Parameter haben. Im Zusammenhang mit den Klassentemplates der Standardbibliothek (bei denen das noch erlaubt ist) hat das zur Folge, dass diese normalerweise nicht als Templatetemplateparameter dienen dürfen. Ein kurzer Blick in die Standardbibliothek zeigt uns, dass der Allokatorparamter dort ein einfacher Typ ist. Wenn ein Kontainer andere Objekte allokieren will, muss der Umweg über rebind gegangen werden - und das wohl nicht deshalb, weil Templatetemplateparameter bei der Entwicklung der STL völlig unbekannt waren.



  • THX 1138 schrieb:

    Warum machst du nicht die struct zum template? Wirst ja wohl immer beide Methoden als Paar brauchen:

    Das hatte ich übersehen. Bin davon ausgegangen, dass die Klasse selbst ein Template war 😉
    Vorher lieber einmal mehr gucken 😕 *merk*



  • camper schrieb:

    Das ist nicht sehr überzeugend. Es ist kaum anzunehmen, dass jeder spezielle Allokator, den man schreiben will, so allgemein ist, dass man ihn als Template schreiben kann und will. Zudem kann ein solcher Templateallokator keine zusätzlichen Parameter haben. Im Zusammenhang mit den Klassentemplates der Standardbibliothek (bei denen das noch erlaubt ist) hat das zur Folge, dass diese normalerweise nicht als Templatetemplateparameter dienen dürfen. Ein kurzer Blick in die Standardbibliothek zeigt uns, dass der Allokatorparamter dort ein einfacher Typ ist. Wenn ein Kontainer andere Objekte allokieren will, muss der Umweg über rebind gegangen werden - und das wohl nicht deshalb, weil Templatetemplateparameter bei der Entwicklung der STL völlig unbekannt waren.

    Naja, er wollte es als template zum laufen bringen. Habs nur als Tipp gemeint. Die Situation mag man anders lösen, aber mit Konrads Vorschlag kann man schon Mist bauen und darauf wollt ich bloss hinweisen.
    Ich bin bislang sowieso noch nie in die Situation gekommen, dass ich nen eigenen Allokator schreiben musste, daher hab ich da keine Erfahrung. Mir gings um das template Problem.
    Aber wie würdest du es denn machen ohne template? Würd mich schon auch interessieren. 🙂


Log in to reply