template-spezialisierung auf std::string schlägt fehl



  • gut, dass ich die operatoren << bzw. >> für string extra überladen habe, war unnötig, allerdings wundere ich mich doch, warum es da zu solchen komplikationen kommt. war der code etwa fehlerhaft?

    @ Mr. N:
    das mit der expl. spezialisierung wär dann auch wieder in mein hirn gebrannt 😉 auf den priv. kontruktor / destruktor verzichte ich, da ich mal mit typeid rumspielen wollte 🤡 außerdem bin ich geil auf die exception 😃

    würdet ihr mir noch kurz auf die sprünge helfen, warum die eingabe per cin nicht funktioniert (siehe kommentare im code)?



  • @Kräüterkundestudent:
    Zu dem cin>> hab ich dir bereits gesagt, was du versuchen sollst damits besser geht. Btw. wäre sowas eh schöner (imho):

    template<class T> class Test {
      void read(istream &is);
    };
    
    template<class T> istream &operator>>(istream &is, Test<T> &x) {
      x.read(is);
      return is;
    }
    


  • danke, ich glaube so krieg ichs hin 🙂

    edit: ich hab es jetzt, wie von Mr. N vorgeschlagen gelöst.

    einmal die friend-deklaration gelöscht und
    stattdessen eine read-methode ergänzt:

    void read(istream& in)
    	{
    		in >> m_Value;
    	}
    //...
    
    template <class T>  
    istream& operator>>(istream& in, Test<T>& testit)  
    {   
    	testit.read(in);   
    
        return in;   
    }
    

    nochmal danke.



  • nur mal aus purer neugier:
    mach die read funktion mal privat und schreibe in die klasse Test:

    friend istream &operator>>(istream &, Test &);
    

    wenns dann geht weißt du auch wies geht, wenn nicht, dann weiß ich, wies nicht geht 🤡



  • du weißt jetzt, wies nicht geht 😉

    noch eine letzte sache. ich hab mir gestern schon einige zeit den kopf zerbrochen, wieso ich die methode

    getValue()
    

    nicht als

    T& getValue() { return m_Value;}
    

    deklarieren kann, also eine referenz zurückgeben lasse.

    dann kriege ich gleich wieder einen fehler der art:

    error C2662: 'getValue' : this-Zeiger kann nicht von 'const class Test<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >' in 'class Test<
    class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > &' konvertiert werden



  • überladen du musst (manche leute würden das polymorphie nennen aber egal):

    T const &getValue() const;
    T &getValue();
    

    dass du das tun musst kann man übrigens aus der fehlermeldung erkennen



  • gut, das klappt...und ich weiß sogar, warum 🤡

    danke!



  • Mr. N schrieb:

    das was ich als ganz anders bezeichnet hab is eine explizite spezialisierung ... wenn du nun schreibst Test<string> dann nimmt er die damit beschriebene klasse.
    und wenn nun diese klasse private konstruktoren hat, dann meldet bereits der compiler, dass Test<string> verboten ist.

    er meldet bestimt sowas wie "class Test<basic_string<T ..>>> ctor ist nicht zugreifbar.. xyz " das kapiert aber kein mensch, schöner fände ich ein static assert oder änliches (habe schon zu lange kein c++ gemacht boost::static_assert ist doch dafür geeignet?)



  • Dimah schrieb:

    habe schon zu lange kein c++ gemacht

    darf ich neugierig sein und fragen was dann bzw. wie das gemeint ist?



  • hallo nochmal 🙂

    ich wollte meine übung jetzt so zu ende bringen, indem ich einen std::vector auf meine klasse Test<T> (die inzwischen etwas erweitert wurde (siehe quellcode)) spezialisiere. seltsamerweise tauchen genau dann, wenn ich in das programm den vector einbaue fehler auf.

    der quellcode ist etwas länger als die meisten anderen hier geposteten. ich würde es also sehr schätzen, wenn sich diesem einer annehmen würde. da ich die fehlermeldungen überhaupt nicht zuordnen kann, fällt es mir auch schwer das programm auf das wesentliche zu reduzieren 😕 . daher sei gesagt, dass mir der debugger meldet, dass der fehler vermutlich irgendwo beim konstruktor von Test<T>, der einen wert vom typ T entgegennimmt, auftaucht.

    die fehlermeldungen bzw. warnungen lauten:

    warning C4786: 'std::reverse_iterator<Test<std::basic_string<char,std::char_traits<char>,std::allocator<char> > > const *,Test<std::basic_string<char,std::char_traits<char>,std
    ::allocator<char> > >,Test<std::basic_string<char,std::char_traits<char>,std::allocator<char> > > const &,Test<std::basic_string<char,std::char_traits<char>,std::allocator<char> > > const *,int>' : Bezeichner wurde auf '255' Zeichen in den Debug-Inf
    ormationen reduziert

    warning C4786: 'std::reverse_iterator<Test<std::basic_string<char,std::char_traits<char>,std::allocator<char> > > *,Test<std::basic_string<char,std::char_traits<char>,std::allo
    cator<char> > >,Test<std::basic_string<char,std::char_traits<char>,std::allocator<char> > > &,Test<std::basic_string<char,std::char_traits<char>,std::allocator<char> > > *,int>' : Bezeichner wurde auf '255' Zeichen in den Debug-Informationen reduziert

    error C2059: Syntaxfehler : '<' Bei der Kompilierung der Member-Funktion '__thiscall Test<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >::Test<class std::basi
    c_string<char,struct std::char_traits<char>,class std::allocator<char> > >(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)' der Klassenvorlage

    #include <iostream>     
    #include <fstream>   
    #include <string>   
    #include <exception>   
    #include <typeinfo> 
    #include <vector>   
    
    using namespace std; 
    
    /////////////////////////////////////   
    ////    class memberOfTest<T>    ////  
    ///////////////////////////////////// 
    template <class T> 
    class memberOfTest 
    { 
        public: 
            memberOfTest() { m_Pointer = new T;} 
    
            memberOfTest(T value); 
    
            memberOfTest(const memberOfTest<T>& right); 
    
            const memberOfTest<T>& operator=(const memberOfTest<T>& right); 
    
            virtual ~memberOfTest() { delete m_Pointer;} 
    
            T* getPointer() const { return m_Pointer; } 
    
        private: 
            T* m_Pointer; 
    }; 
    
    //############################################################################### 
    template<class T> 
    memberOfTest<T>::memberOfTest(T value) 
    {  
        m_Pointer = new T; 
    
        *m_Pointer = value; 
    } 
    //############################################################################### 
    template<class T> 
    memberOfTest<T>::memberOfTest(const memberOfTest<T>& right) 
    { 
        m_Pointer = new T; 
        *m_Pointer = *(right.getPointer()); 
    } 
    //############################################################################### 
    template<class T> 
    const memberOfTest<T>& memberOfTest<T>::operator=(const memberOfTest<T>& right) 
    { 
        *m_Pointer = *(right.getPointer()); 
    
        return *this; 
    } 
    //############################################################################### 
    /////////////////////////////////////   
    //  END class memberOfTest<T> END  //   
    ///////////////////////////////////// 
    
    //############################################################################### 
    //############################################################################### 
    //############################################################################### 
    //############################################################################### 
    
    /////////////////////////////////////   
    ////////    class Test<T>    ////////  
    ///////////////////////////////////// 
    template<class T>   
    class Test : public memberOfTest<T>   
    {    
    public:    
        Test(const Test<T>& right);  
    
        Test(); 
    
        Test(T value) : m_Value(value), m_secValue(value), memberOfTest(value) {}   
    
        virtual ~Test() {} 
    
        T getValue() const { return m_Value; }   
    
        memberOfTest<T> getsecValue() const { return m_secValue; } 
    
        const Test<T>& operator=(const Test<T>& right);   
    
        void save(string name); 
    
        void load(string name); 
    
        void read(istream& in) { getline(in, m_Value); } 
    
    private:    
        T m_Value; 
        memberOfTest<T> m_secValue; 
    
    }; 
    
    //############################################################################### 
    template<class T> 
    Test<T>::Test(const Test<T>& right) : m_secValue(right.getsecValue()), memberOfTest<T>(right) 
    {   
        m_Value = right.getValue();   
    
        if((m_Value != right.getValue()) || (m_secValue != right.getsecValue()))   
            throw("ERROR. PROCESS INTERRUPTED.");   
    }  
    //###############################################################################  
    template<class T> 
    Test<T>::Test() : m_secValue<T>(), memberOfTest<T>()   
    {   
        if(typeid(T).name() == typeid(string).name()) 
            throw("DIFFERENT TYPE THAN STD::STRING IS REQUIRED.");   
    }   
    //############################################################################### 
    template<class T> 
    const Test<T>& Test<T>::operator=(const Test<T>& right)   
    {   
        if(this == &right) 
            return *this; 
    
        m_Value = right.getValue(); 
    
        m_secValue.operator=(right.getsecValue()); 
    
        memberOfTest<T>::operator=(right); 
    
        return *this;   
    }   
    //############################################################################### 
    template<class T> 
    void Test<T>::save(string name)   
    {   
        ofstream DATEI(name.c_str());   
    
        if(DATEI)   
            DATEI << m_Value << "\n" << *(m_secValue.getPointer()) << endl;   
    
        else throw("CAN'T SAVE DATA. CAN'T CREATE FILE. PROCESS INTERRUPTED.");   
    }   
    //############################################################################### 
    template<class T> 
    void Test<T>::load(string name)   
    {   
        ifstream DATEI(name.c_str());   
    
        if(DATEI) 
        { 
            string tempValue; 
            m_Value = ""; 
    
            for(; getline(DATEI, tempValue);) 
            {
    			m_Value += tempValue + "\n"; 
            } 
        } 
    
        else throw ("CAN'T LOAD DATA. FILE DAMAGED OR DOES NOT EXIST. PROCESS INTERRUPTED.");   
    }   
    //############################################################################### 
    /////////////////////////////////////  
    //////    END class Test END    /////   
    ///////////////////////////////////// 
    
    template <class T>   
    ostream& operator<<(ostream& out, const Test<T>& right)   
    {    
        out << right.getValue();    
    
        return out;    
    }    
    
    template <class T>   
    istream& operator>>(istream& in, Test<T>& right)   
    {    
        right.read(in);    
    
        return in;    
    }      
    
    int main()    
    {    
        try   
        { 
            vector<Test<string> > test; 
    
            test.push_back(Test<string>("tada")); 
    
            cin >> test[0];  
    
            cout << test[0] << endl;    
    
            test[0].save("d:\\TEST.txt");   
            test[0].load("d:\\TEST.txt");   
    
            cout << test[0] << endl; 
        }   
    
        catch(const char* a)   
        {   
            cout << a << endl;   
        }   
    
        return 0;    
    }
    

    schon jetzt danke 🙂 👍

    ps: wirklich mein letztes anliegen in dieser sache (versprochen ;)).



  • Test(T value) : m_Value(value), <T>m_secValue(value), memberOfTest<T>(value) {}
    

    Was soll da das <T>?



  • Mr. N schrieb:

    Test(T value) : m_Value(value), <T>m_secValue(value), memberOfTest<T>(value) {}
    

    Was soll da das <T>?

    naja, ich dachte, dass der konstruktor den template-typ extra wissen muss um das objekt zu erstellen.

    andererseits: lasse ich das <T> weg, so bleiben doch die fehlermeldungen 😞
    lasse ich beim m_secValue das <T> weg, so bekomme ich aufeinmal acht weitere fehlermeldungen, lasse ich das zweite <T> weg, so sind es zwei und lasse ich gar beide weg, so sind es auch zwei.



  • sorry, aber die anzahl fehlermeldungen hilft wenig. nenne sie.



  • ok,
    wenn ich im genannten konstruktor aus "<T>m_secValue(value)" "m_secValue(value)" mache und den rest unverändert lasse, bekomme ich folgende fehlermeldungen:

    :\Dokumente und Einstellungen\Kräuterkundestudent\Desktop\dd.cpp(207) : warning C4786: 'std::reverse_iterator<Test<std::basic_string<char,std::char_traits<char>,std::allocator<char> > > const *,Test<std::basic_string<char,std::char_traits<char>,std
    ::allocator<char> > >,Test<std::basic_string<char,std::char_traits<char>,std::allocator<char> > > const &,Test<std::basic_string<char,std::char_traits<char>,std::allocator<char> > > const *,int>' : Bezeichner wurde auf '255' Zeichen in den Debug-Inf
    ormationen reduziert
    C:\Dokumente und Einstellungen\Kräuterkundestudent\Desktop\dd.cpp(207) : warning C4786: 'std::reverse_iterator<Test<std::basic_string<char,std::char_traits<char>,std::allocator<char> > > *,Test<std::basic_string<char,std::char_traits<char>,std::allo
    cator<char> > >,Test<std::basic_string<char,std::char_traits<char>,std::allocator<char> > > &,Test<std::basic_string<char,std::char_traits<char>,std::allocator<char> > > *,int>' : Bezeichner wurde auf '255' Zeichen in den Debug-Informationen reduzie
    rt
    C:\Dokumente und Einstellungen\Kräuterkundestudent\Desktop\dd.cpp(105) : error C2784: 'bool __cdecl std::operator !=(const class std::vector<_Ty,_A> &,const class std::vector<_Ty,_A> &)' : Vorlagenargument fuer 'const class std::vector<_Ty,A> &' vo
    n 'class memberOfTest<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >' konnte nicht hergeleitet werden
    c:\programme\microsoft visual studio\vc98\include\streambuf(103) : Bei der Kompilierung der Member-Funktion '__thiscall Test<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >::Test<class std::basic_str
    ing<char,struct std::char_traits<char>,class std::allocator<char> > >(const class Test<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > &)' der Klassenvorlage
    C:\Dokumente und Einstellungen\Kräuterkundestudent\Desktop\dd.cpp(105) : error C2784: 'bool __cdecl std::operator !=(const class std::basic_string<_E,_Tr,_A> &,const _E *)' : Vorlagenargument fuer 'const class std::basic_string<_E,_Tr,_A> &' von 'cl
    ass memberOfTest<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >' konnte nicht hergeleitet werden
    c:\programme\microsoft visual studio\vc98\include\streambuf(103) : Bei der Kompilierung der Member-Funktion '__thiscall Test<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >::Test<class std::basic_str
    ing<char,struct std::char_traits<char>,class std::allocator<char> > >(const class Test<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > &)' der Klassenvorlage
    C:\Dokumente und Einstellungen\Kräuterkundestudent\Desktop\dd.cpp(105) : error C2784: 'bool __cdecl std::operator !=(const _E *,const class std::basic_string<_E,_Tr,_A> &)' : Vorlagenargument fuer 'const *' von 'class memberOfTest<class std::basic

    string<char,struct std::char_traits<char>,class std::allocator<char> > >' konnte nicht hergeleitet werden
    c:\programme\microsoft visual studio\vc98\include\streambuf(103) : Bei der Kompilierung der Member-Funktion '__thiscall Test<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >::Test<class std::basic_str
    ing<char,struct std::char_traits<char>,class std::allocator<char> > >(const class Test<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > &)' der Klassenvorlage
    C:\Dokumente und Einstellungen\Kräuterkundestudent\Desktop\dd.cpp(105) : error C2784: 'bool __cdecl std::operator !=(const class std::basic_string<_E,_Tr,_A> &,const class std::basic_string<_E,_Tr,_A> &)' : Vorlagenargument fuer 'const class std::ba
    sic_string<_E,_Tr,_A> &' von 'class memberOfTest<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >' konnte nicht hergeleitet werden
    c:\programme\microsoft visual studio\vc98\include\streambuf(103) : Bei der Kompilierung der Member-Funktion '__thiscall Test<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >::Test<class std::basic_str
    ing<char,struct std::char_traits<char>,class std::allocator<char> > >(const class Test<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > &)' der Klassenvorlage
    C:\Dokumente und Einstellungen\Kräuterkundestudent\Desktop\dd.cpp(105) : error C2784: 'bool __cdecl std::operator !=(const class std::allocator<_Ty> &,const class std::allocator<_U> &)' : Vorlagenargument fuer 'const class std::allocator<_Ty> &' von
    'class memberOfTest<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >' konnte nicht hergeleitet werden
    c:\programme\microsoft visual studio\vc98\include\streambuf(103) : Bei der Kompilierung der Member-Funktion '__thiscall Test<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >::Test<class std::basic_str
    ing<char,struct std::char_traits<char>,class std::allocator<char> > >(const class Test<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > &)' der Klassenvorlage
    C:\Dokumente und Einstellungen\Kräuterkundestudent\Desktop\dd.cpp(105) : error C2784: 'bool __cdecl std::operator !=(const class std::istreambuf_iterator<_E,_Tr> &,const class std::istreambuf_iterator<_E,_Tr> &)' : Vorlagenargument fuer 'const class
    std::istreambuf_iterator<_E,_Tr> &' von 'class memberOfTest<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >' konnte nicht hergeleitet werden
    c:\programme\microsoft visual studio\vc98\include\streambuf(103) : Bei der Kompilierung der Member-Funktion '__thiscall Test<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >::Test<class std::basic_str
    ing<char,struct std::char_traits<char>,class std::allocator<char> > >(const class Test<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > &)' der Klassenvorlage
    C:\Dokumente und Einstellungen\Kräuterkundestudent\Desktop\dd.cpp(105) : error C2784: 'bool __cdecl std::operator !=(const class std::reverse_iterator<_RI,_Ty,_Rt,_Pt,_D> &,const class std::reverse_iterator<_RI,_Ty,_Rt,_Pt,_D> &)' : Vorlagenargument
    fuer 'const class std::reverse_iterator<_RI,_Ty,_Rt,_Pt,_D> &' von 'class memberOfTest<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >' konnte nicht hergeleitet werden
    c:\programme\microsoft visual studio\vc98\include\streambuf(103) : Bei der Kompilierung der Member-Funktion '__thiscall Test<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >::Test<class std::basic_str
    ing<char,struct std::char_traits<char>,class std::allocator<char> > >(const class Test<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > &)' der Klassenvorlage
    C:\Dokumente und Einstellungen\Kräuterkundestudent\Desktop\dd.cpp(105) : error C2784: 'bool __cdecl std::operator !=(const struct std::pair<_T1,_T2> &,const struct std::pair<_T1,_T2> &)' : Vorlagenargument fuer 'const struct std::pair<_T1,_T2> &' vo
    n 'class memberOfTest<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >' konnte nicht hergeleitet werden
    c:\programme\microsoft visual studio\vc98\include\streambuf(103) : Bei der Kompilierung der Member-Funktion '__thiscall Test<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >::Test<class std::basic_str
    ing<char,struct std::char_traits<char>,class std::allocator<char> > >(const class Test<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > &)' der Klassenvorlage
    C:\Dokumente und Einstellungen\Kräuterkundestudent\Desktop\dd.cpp(105) : error C2676: Binaerer Operator '!=' : 'class memberOfTest<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >' definiert diesen Operator o
    der eine Konvertierung in einen fuer den vordefinierten Operator geeigneten Typ nicht
    c:\programme\microsoft visual studio\vc98\include\streambuf(103) : Bei der Kompilierung der Member-Funktion '__thiscall Test<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >::Test<class std::basic_str
    ing<char,struct std::char_traits<char>,class std::allocator<char> > >(const class Test<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > &)' der Klassenvorlage

    wenn ich hingegen nur das <T> von memberOfTest<T>(value) weglasse, so ändert sich nichts. ich bekomme die besagte fehlermeldung + die zwei warndungen vom posting drüber. wenn ich beide <T> weglasse, so bekomme ich folgende meldungen:

    warning C4786: 'std::reverse_iterator<Test<std::basic_string<char,std::char_traits<char>,std::allocator<char> > > const *,Test<std::basic_string<char,std::char_traits<char>,std
    ::allocator<char> > >,Test<std::basic_string<char,std::char_traits<char>,std::allocator<char> > > const &,Test<std::basic_string<char,std::char_traits<char>,std::allocator<char> > > const *,int>' : Bezeichner wurde auf '255' Zeichen in den Debug-Inf
    ormationen reduziert

    warning C4786: 'std::reverse_iterator<Test<std::basic_string<char,std::char_traits<char>,std::allocator<char> > > *,Test<std::basic_string<char,std::char_traits<char>,std::allo
    cator<char> > >,Test<std::basic_string<char,std::char_traits<char>,std::allocator<char> > > &,Test<std::basic_string<char,std::char_traits<char>,std::allocator<char> > > *,int>' : Bezeichner wurde auf '255' Zeichen in den Debug-Informationen reduziert

    rror C2955: 'memberOfTest' : Fuer die Verwendung einer Vorlagenklasse ist eine Vorlagen-Argumentliste erforderlich
    C:\Dokumente und Einstellungen\Kräuterkundestudent\Desktop\dd.cpp(31) : Siehe Deklaration von 'memberOfTest'
    C:\Dokumente und Einstellungen\Kräuterkundestudent\Desktop\dd.cpp(77) : Bei der Kompilierung der Member-Funktion '__thiscall Test<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >::Test<class std::basi
    c_string<char,struct std::char_traits<char>,class std::allocator<char> > >(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)' der Klassenvorlage

    error C2614: 'Test<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >' : Unzulaessige Elementinitialisierung: 'memberOfTest' ist weder Bas
    is noch Element
    C:\Dokumente und Einstellungen\Kräuterkundestudent\Desktop\dd.cpp(77) : Bei der Kompilierung der Member-Funktion '__thiscall Test<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >::Test<class std::basi
    c_string<char,struct std::char_traits<char>,class std::allocator<char> > >(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)' der Klassenvorlage
    Fehler beim Ausführen von cl.exe.


Anmelden zum Antworten