template-spezialisierung auf std::string schlägt fehl
-
MaSTaH schrieb:
Was meldet der Compiler denn?
der compiler meldet gar nichts. das ist das problem (microsoft visual c++).
@ Mr. N:
gut, name() hab ich jetzt jeweils weggelassen. das ändert aber erstmal nichts.
- Machs doch ganz anders:
template<> class Test<std::string> { Test(); // privater Konstruktor, haha! ~Test(); // Destruktor ebenso. }
ich verstehe nicht ganz, was das bezwecken soll. könntest du ein klein wenig mehr code dazu posten? im grunde ist das doch equivalent zu
class Test{ //... string m_Value; };
oder?
edit: so schnell, wie ihr hier postet aknn ich ja gar nicht mithalten
die überarbeitete version von mastah funktioniert anscheinend. ich werde mir das mal genauer anschauen. hier schonmal vielen dank
-
@Kräuterkundestudent:
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.
und jetzt zeig ich dir eine partielle spezialisierung *hrhr*:template<class T, class Ch, class A> class Test<std::basic_string<T, Ch, A> > { Test(); }
jetzt geht das auch mit wstring.
übrigens erfordert eine spezialisierung, dass die klasse (oder auch die funktion als template bekannt ist). also erst das template<class T> class Test {....};
-
@Mastah: es wäre _sehr_ hilfreich wenn du bitte die von dir vorgenommenen änderungen markieren würdest, sonst erkennen das meine blinden augen nich
-
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 gebranntauf 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 reduziertwarning 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 reduzierterror 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 Klassenvorlagewenn 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 reduziertwarning 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 reduziertrror 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 Klassenvorlageerror 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.