Problem mit Klassen-Template



  • Hallo,
    ich habe ein Problem eine normale Klasse in eine Template Klasse umzuschreiben. Es handelt sich dabei um eine Aufgabe aus der Hochschule und zwar soll man eine eigene Klasse Set die std::list verwendet um eine Menge an floats zu speichern, in ein Template umschreiben, so das ich auch andere Datentypen damit verwenden kann.

    Die nicht-Template Klasse SetOfFloats funktioniert einwandfrei, jedoch nachdem ich meine Finger daran hatte leider nicht mehr 😃

    Hier erstmal die normale SetOfFloats Klasse:

    /*
     * File:   SetOfFloats.h
     * Author: Prof. Dr. R. C. Moore (Fb I, h-da.de)
     *
     * Created on June 20, 2012, 8:22 PM
     */
    
    #ifndef SETOFFLOATS_H
    #define SETOFFLOATS_H
    
    #include <string>
    #include <sstream>
    #include <list>
    
    class SetOfFloats {
    public:
    
        SetOfFloats() { // default constructor - creates empty set
    
        }
    
        ~SetOfFloats() { // destructor
    
        }
    
        int size() { // returns number of elements
            return this->list_.size();
        }
    
        bool is_in_set(float number) {
            std::list<float>::iterator it;
            for (it = this->list_.begin(); it != this->list_.end(); it++) {
                if (*it == number)
                    return true;
            }
            return false;
        }
    
        void insert(float number) { // insert number - if not already there
            if (this->is_in_set(number) == false) {
                this->list_.push_back(number);
            }
        }
    
        void remove(float number) { // remove number - if already there
            if (this->is_in_set(number) == true) {
                this->list_.remove(number);
            }
        }
    
        std::string to_string() { // convert set to string - for debug print!
            std::list<float>::iterator it;
            std::ostringstream out;
            std::string print;
            for (it = this->list_.begin(); it != this->list_.end(); it++) {
                out << *it << " ";
            }
            print = out.str();
            return print;
        }
    
    private:
        std::list<float> list_;
        // Diese Klasse soll (muss, darf) erweitert bzw. geändert werden.
    
    };
    
    #endif  /* SETOFFLOATS_H */
    

    Und hier nun mein verzweifelter Versuch es in ein Template zu schreiben 😃

    /*
     * File:   Set.h
     * Author: Prof. Dr. R. C. Moore (Fb I, h-da.de)
     *
     * Created on June 20, 2012, 8:22 PM
     */
    
    #ifndef SET_H
    #define SET_H
    
    #include <string>
    #include <sstream>
    #include <list>
    
    template <class T>
    class Set {
    public:
    
        Set() { // default constructor - creates empty set
    
        }
    
        ~Set() { // destructor
    
        }
    
        int size() { // returns number of elements
            return this->list_.size();
        }
    
        bool is_in_set(T number) {
            std::list<T>::iterator it;
            for (it = this->list_.begin(); it != this->list_.end(); it++) {
                if (*it == number)
                    return true;
            }
            return false;
        }
    
        void insert(T number) { // insert number - if not already there
            if (this->is_in_set(number) == false) {
                this->list_.push_back(number);
            }
        }
    
        void remove(T number) { // remove number - if already there
            if (this->is_in_set(number) == true) {
                this->list_.remove(number);
            }
        }
    
        std::string to_string() { // convert set to string - for debug print!
            std::list<T>::iterator it;
            std::ostringstream out;
            std::string print;
            for (it = this->list_.begin(); it != this->list_.end(); it++) {
                out << *it << " ";
            }
            print = out.str();
            return print;
        }
    
    private:
        std::list<T> list_;
        // Diese Klasse soll (muss, darf) erweitert bzw. geändert werden.
    
    };
    
    #endif  /* SET_H */
    

    Als Fehlermeldungen bekomme ich folgendes:

    Set.h:30:15: Fehler: Deklaration von �class T�
    Set.h:15:11: Fehler: �berdeckt Templateparameter �class T�
    Set.h:32:9: Fehler: �typename� vor �std::list<T>::iterator� erforderlich, da �std::list<T>� ein abh�ngiger G�ltigkeitsbereich ist
    Set.h:32:32: Fehler: expected �;� before �it�
    Set.h:33:14: Fehler: �it� wurde in diesem G�ltigkeitsbereich nicht definiert
    Set.h:53:9: Fehler: �typename� vor �std::list<T>::iterator� erforderlich, da �std::list<T>� ein abh�ngiger G�ltigkeitsbereich ist
    Set.h:53:32: Fehler: expected �;� before �it�
    Set.h:56:14: Fehler: �it� wurde in diesem G�ltigkeitsbereich nicht definiert

    Ich danke euch schonmal vielmals für eure Hilfe!

    MfG Xarsis


  • Mod

    Xarsis schrieb:

    Set.h:32:9: Fehler: �typename� vor �std::list<T>::iterator� erforderlich, da �std::list<T>� ein abh�ngiger G�ltigkeitsbereich ist
    Set.h:53:9: Fehler: �typename� vor �std::list<T>::iterator� erforderlich, da �std::list<T>� ein abh�ngiger G�ltigkeitsbereich ist



  • Ich versteh leider nicht ganz was damit gemeint ist.
    Könntest du mir das ein wenig genauer erläutern?
    Was genau soll denn vor den std::list<T>::iterator? Nochmal template<class T> ? template<typename T> (Ka wo da der unterschied ist)?
    Bin gerade ein bisschen verwirrt.



  • Schon

    template <typename T>
    

    probiert? Immerhin ist float doch ein Typ und keine Klasse (ich hoffe, ich habe grade keinen peinlichen Denkfehler gemacht^^).

    Ansonsten kann ich dir heute abend ein bisschen Hilfe anbieten, solltest du welche bedeuten. Muss jetzt allerdings los.


  • Mod

    typename std::list<T>::iterator it;
    

    std::list<T>::iterator ist ein vom Templateparameter abhängiger Bezeichner. Der Compiler kann bei der Templatedefinition nicht wissen, ob es sich bei diesem Namen um einen Typnamen oder etwas anders handelt. Ohne explizite Angabe wird angenommen, dass es sich nicht um einen Typnamen handelt. Die Unterscheidung ist wichtig für den Parser

    TT<T>::foo*bar; // Ausdruck (Multiplikation)
    typename TT<T>::foo*bar; // Deklaration eines Zeigers
    

    In

    std::list<T>::iterator it;
    

    geht der Compiler davon aus, dass es sich um einen Ausdruck handelt. Weil aber ein geeigneter Operator fehlt, wird angenommen, dass ein Semikolon vergessen wurde. Daraus resultiert dann die zweite - nicht so hilfreiche - Fehlermeldung. Außerdem wurde it nicht zuvor definiert (was ja der Fall sein müssen, wenn dort ein Ausdruck stünde) => Fehler Nr. 3. Danach gibt der Compiler offenbar auf.



  • Xarsis schrieb:

    Die nicht-Template Klasse SetOfFloats funktioniert einwandfrei, ...

    /*
     * File:   SetOfFloats.h
     * Author: Prof. Dr. R. C. Moore (Fb I, h-da.de)
     *
     * Created on June 20, 2012, 8:22 PM
     */
    
    #ifndef SETOFFLOATS_H
    #define SETOFFLOATS_H
    
    #include <string>
    #include <sstream>
    #include <list>
    
    class SetOfFloats {
    ...
        // Diese Klasse soll (muss, darf) erweitert bzw. geändert werden.
    
    };
    

    Hallo Xarsis,

    allen Anschein nach ist das eine Klasse, die Dein Prof. Euch quasi als Referenz zur Verfügung gestellt hat. Die mag funktionieren, hat aber Verbesserdungsbedarf.
    nach Scott Meyers 'Effektiv C++' verstößt der Code gegen die Item
    4 - C-Kommentar
    12 - fehlende Initialisierungsliste
    21 - const correctness
    32 - Variablen so spät wie möglich deklarieren
    49 - mangelnde Kenntnis der C++-Standard-Library (sowohl bei remove, als auch bei to_string)
    nach Scott Meyers 'Mehr Effektiv C++' kommt noch dazu
    6 - Unterschied prefix und postfix operatoren

    Jedes Item für sich ist vielleicht eine Kleinigkeit (obwohl - const correctness finde ich schon wichtig), aber alles zusammen, bei so wenig Code, lässt mangelnde Professionalität erkennen.

    dazu kommen noch drei - ich sage mal - Stilbrüche
    - Verwendung von 'this->'
    - bool-Vergleich mit false
    - überflüssiger Destruktor

    da kann man drüber diskutieren, müsste man aber gar nicht, wenn man es jeweils einfach weg gelassen hätte.

    Irgendwie traurig, wenn so was an einer Uni oder FH gelehrt wird.

    Gruß
    Werner


Anmelden zum Antworten