Schwierigkeiten mit templates
-
Okay, dass ist mir bekannt..zumindest jetzt wieder in Erinnerung...

Mit Fehlerbehandlung meinst du
cin.fail()oder..?
Wie kommst du auf Datum..?
Mal so nebenbei, das Bsp. habe ich mir frei einfach so ausgedacht - war das einfach Mist..? Also ich meine wie oft würde man sowas als template anlegen, eine Funktion die Text & Zahlen verarbeiten soll..? ..deiner Erfahrung nach..?
-
weniger die fail bits von den streams sondern eher, was soll passieren wenn man zahlen und buchstaben mischt und eig eine zahl eingeben will. solche fälle halt, die müssen wohl überlegt sein
tja, mit erfahrung mangelts bei mir. dazu kann ich nur sagen, ich hab keien erfahrung...
aber ich wäre da halt ziemlich vorsichtig was die eingabe betrifft, da kann man den user mit richtig nerven, man kann die sicherheit des programms und damit des computers anfechten (guck mal den tanenbaum zum thema betriebssystem sicherheit, buffer overflow usw.)
edit: eingaben sollte man weniger generisch machen, da kann man ruhig konkreter werden
-
Skym0sh0 schrieb:
fail bits
Es gibt keine fail bits. Nur error-bits und das failbit.
Wieso machst du überhaupt die Pufferung durch den Stringstream? Gerade
std::getlinemit einem LF als Delimitter ist nicht gut, da ein überladener left-shift Operator auchstd::ostream& operator<<(std::ostream& os, T const& t) { return os << t.getThis() << '\n' << t.getThat(); }so aussehen kann (unsinnig aber möglich).
aber ich wäre da halt ziemlich vorsichtig was die eingabe betrifft, da kann man den user mit richtig nerven, man kann die sicherheit des programms und damit des computers anfechten (guck mal den tanenbaum zum thema betriebssystem sicherheit, buffer overflow usw.)

Wenn mann es richtig macht dann ist daran garnix nervig oder gefährlich...
-
Also std::array ist eine tolle Sache (ebenso std::vector), danke..!

Nur mit
std::string s; std::getline(std::cin, s); std::stringstream ss; ss << s; type x; ss >> x;klappt´s dann leider nicht, der Compiler gibt mir da
error C2678: Binärer Operator '>>': Es konnte kein Operator gefunden werden, der einen linksseitigen Operanden vom Typ 'std::stringstream' akzeptiert (oder keine geeignete Konvertierung möglich)
aus.

So wie ich die Arrays am Anfang erstellt und übergeben habe, funktioniert es so (beim testen hab ich die Array-Größe mit übergeben
)Also danke noch mal für eure (schnelle..!!) Hilfe..!

-
Ach so, ja daran hab ich im Übungsprogramm jetzt natürlich nicht gedacht, ist ja nur meins an dem ich mir das beibringe...

Du hast natürlich Recht, das ist wichtig und mir auch bekannt. In VBA habe ich schon einige Programme für meine damalige Firma geschrieben, da hab ich schon gemerkt dass die Benutzer (mich selber eingeschlossen) beim verwenden gerade die Sachen eingeben an die man selber (beim Programmieren) am wenigsten denkt... :p@Sone
Wie würdest du das lösen..?
-
Wie würde ich eine Menge von Zahlen von der Konsole einlesen?
std::vector<int> vec(5); for(size_t n(0);n < 5;++n) while(!(std::cin >> vec[n])) { std::cout << "Error! Type in a number, please!\n"; std::cin.clear(); std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); }
-
Wie würde ich eine Menge von Zahlen von der Konsole einlesen?
Hm, aber es ging ja darum eine Lösung zu finden, dass ich es in der tamplate Funktion hinbekomme int UND strings einzulesen.
Mit dem selben Code.
Und zwar so, dass das einlesen der Eingabe bei einer Zahl nach der Zahl endet, wie es cin << Var eben tut; und das Einlesen nach der Zeilenschaltung, wie es getline() eben tut.Für Zahlen funktioniert deine Methode natürlich, aber beim string hilft das wenig..oder verstehe ich daran irgendetwas nicht..?

-
Eisenspitze schrieb:
Für Zahlen funktioniert deine Methode natürlich, aber beim string hilft das wenig..oder verstehe ich daran irgendetwas nicht..?

Wunderbar funktioniert das für Strings. Probier es doch aus.
-
Natürlich hab ich das probiert bevor ich dir geschrieben hab - ich bin doch auf der Suche nach einer Lösung..!
Leider klappt es eben nicht..!
Das ist der Code:
#include <string> #include <iostream> #include <vector> using namespace std; void main() { std::vector<string> strvec(5); for(size_t n(0);n < 5;++n) { while(!(std::cin >> strvec[n])) { std::cout << "Error! Type in a number, please!\n"; std::cin.clear(); std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); } } for(size_t n(0);n < 5;++n) {cout << strvec[n] << "\n";} system("Pause"); }Also genau deiner nur eben für strings.
Wenn ich:
"Hallo Du"
"ein Test"
"und geht nicht"eingebe, kommt
Hallo
Du
ein
Test
undheraus..!
-
Ahh. Natürlich. Jetzt verstehe ich dein Problem. Der operator>> liest nur bis zum ersten Whitespace...
Vielleicht machst du eine Spezialisierung?Ach, btw:
void main()? Ist das dein ernst?
-
Okay, flags hab ich bisher nur ein paar mal so neben bei beim suchen gelesen, aber noch nie bewusst irgendwo wahrgenommen...
Kannst du mir da auf die Sprünge helfen..? Hab grad im Netz gesucht und rumgespielt, aber ich bekomm´s nicht hin...

Meinst du ios::skipws..?
Spezialisierung ist mir bekannt, nur wie muss ich´s mit ios::skipw schreiben..?
Achso, das void main hab ich nur drin weil das im Skript so stand, wobei ich irgendwo im Hinterkopf hab dass es immer int main sein MUSS.
-> stimmt das..?
-> welche Hintergründe gibt´s da..?
-
Nun, mit Flags habe ich nichts gefunden, vielleicht jemand anders.
Was du machen könntest ist eine Überladung mit einer Templatefunktion:
template<typename t> std::istream& readFrom(std::istream& is, t& toread) { return is >> toread; } std::istream& readFrom(std::istream& is, std::string &toread) { return std::getline(is, toread); }
-
ja müsste inmain() heissen. warum? weil das der standard besagt als programmeinstiegspunkt
du musst dir das so vorstellen, dein compiler bettet dein programm in eine laufzeitumgebung ein, die in etwa so aussieht:
someFunction(); // ... int returnValue = main(); if ( returnValue == ... ) ... somefunction();void main ist halt kein standardkonformes C++
bei deinem letzten programm lässt du auch nur 5 worte eingeben durch die schleifen, daher nicht wundern wenn nur 5 wieder rauskommen
-
Cool, so klappt es..!

Damit ich´s richtig verstehe:
Damit haben wir jetzt eine überladene Template-Funktion und der Compiler sucht sich die richtige raus, je nach dem ob´s ein string Vektor ist, oder ein anderer..?@Skym0sh0
Danke für die Erkärung..!
-
ja, wobei ich die funktion mit dem string als template spezialisieren würde, was Sone in seinem beitrag nicht gemacht hat
mit änderung:
template<typename T> std::istream& readFrom(std::istream& is, T & toread) { return is >> toread; } template<> std::istream& readFrom(std::istream& is, std::string & toread) { return std::getline(is, toread); }nicht dass dann probleme bei überladung oder überdeckung gibt...
-
Skym0sh0 schrieb:
template<>
std::istream& readFrom(std::istream& is, std::string & toread)
{
return std::getline(is, toread);
}
[/cpp]nicht dass dann probleme bei überladung oder überdeckung gibt...
Deine Version ist so eigentlich falsch.
template<> std::istream& readFrom<std::string>(std::istream& is, std::string & toread) { return std::getline(is, toread); }Und meine ist vollkommen korrekt und leichter zu lesen, denn es ist eine Überladung; für den Compiler stehen non-template functions an erster Stelle, danach kommen erst Template-Funktionen.
Außerdem kennt jeder die Regel: Templatefunktions-Spezialisierungen sind schlecht, sie überladen nicht.
-
..ui..da komm ich so langsam nicht mehr mit.
Könnt ihr das vielleicht näher erklären..? ..oder mir was zu lesen geben..?

Es geht um den Unterschied zwischen
std::istream& readFrom<std::string>(std::istream& is, std::string & toread)und
std::istream& readFrom(std::istream& is, std::string & toread)oder..?
Mal so nebenbei, warum ist mein eingebetteter Code eigentlich nur schwarz/weiß..?

-
jetzt in den letzten beispielen hast du keine schlüsselworte und nur die werden farblich herausgehoben, bei anderen code snippets von dir hattest du Code statt Cpp tags verwendet
ok, mit den templates komme ich langsam auch nicht mehr so mit.
ich, mit meiner intuition, würde das template so schreiben wie vorgeschlagen. und es dann für std::string weiter spezialisieren
ich habs auch grad mal getestet (VC2010 unter Win7 64), da klappt sowohl die überladung neben dem template und der spezialisierung
#include <iostream> template<typename T> T maximum(T const& a, T const& b) //template { return a<=b ? b : a; } template<> float maximum<float>(float const& a, float const& b) //spezialisiertes template // oder // float maximum(float const& a, float const& b) geht auch! { std::cout << "Template Spez" << std::endl; if ( a < b ) return b; else return a; } float maximum(float const& a, float const& b) // normale funktion { std::cout << "Non-Template" << std::endl; if ( a < b ) return b; else return a; } int main(int argc, char * argv[]) { std::cout << maximum(4355.0f, 7.0f) << std::endl; // ruft die normale funktion auf std::cout << maximum<float>(4355.0f, 7.0f) << std::endl; // ruft die template spez auf std::cout << maximum(4355.0, 7.0) << std::endl; // ruft maximum<double> auf, also das template return 0x0; }
-
template <typename T1, typename T2> auto max(T1 t1, T2 t2) -> decltype(t1 > t2 ? t1 : t2) { return t1 > t2 ? t1 : t2; }
-
hehe^^
genausowas meine ich, das kommt raus wenn wer was sagt, der ahnung hat
