Spezialisierung von Methoden in Templates
-
Zeile 48:
( *(right.daten) != 0 || *(this->daten) != 0) )Offenbar instantiierst du vielleicht mit std::string.
Das heißt *this->daten ist ein std::string. std::string hat aber keinen Vergleichsoperator der einen std::string und ein int annimmt.
Das sagt dir auch die Fehlermeldung.
Was die Lösung ist, kann ich dir nicht sagen, dafür weiß ich nicht genug von deinem Problem bzw. was du machen willst.
-
Falsche Signatur der Spezialisierung, daher passt sie nicht. Sie muss lauten:
template<> Vielleicht<std::string> Vielleicht<std::string>::operator/(const Vielleicht<std::string>&)
-
SeppJ schrieb:
Falsche Signatur der Spezialisierung, daher passt sie nicht. Sie muss lauten:
template<> Vielleicht<std::string> Vielleicht<std::string>::operator/(const Vielleicht<std::string>&)Verdammt, hab ich auch übersehen.
Edit: Übrigens schlechter Ansatz. std::string geht nicht. std::wstring dann auch nicht. std::vector dann vermutlich auch nicht. Genauso wenig wie std::exception. Oder std::function. Und std::istream. Und std::wistream. Und std::ostream. ...
Merkste was?
Du verlangst für den operator/, dass für den Typen operator!= auf int und operator/= implementiert ist.
Vorschlag:template <typename T, typename = decltype(std::declval<T>() != 0), typename = decltype(std::declval<T>() /= std::declval<T>())>Bei der Deklaration von operator/ anfügen.
Und dann ggf. noch ein catch-it-all, was das Fehlerobjekt gibt.
-
asfdlol schrieb:
der fehler ist in der zeile 48. eine instanziierung "Vielleichtstd::string" und ein aufruf dieser methode geht schief, weil das ducktyping gewisse anforderungen hat (auf ungleichheit mit einem int prüfbar sein), welche ein std::string nicht erfüllen kann. erklär vielleicht was dieses klassentemplate überhaupt bewirken soll, damit man dir weiter helfen kann...
Das Template soll für "alle" Datentypen funktionieren, d.h für alle Ganzzahlen und Gleitkommazahlen funktioniert das wie gewünscht...
Nun ist es so wie du gesagt hast, ich instnziere die Template Klasse mit std::string, weil aber "string / string" undefiniert ist, wollte ich eine Spezialisierte Methode für strings haben die mir ein leeres Objekt von Typ Vielleichtstd::string zurückgibt.
int main(int argc, char** argv) { Vielleicht<string> hallo("Hallo"); Vielleicht<string> welt; //welt = 25; cout << hallo.text() << endl; cout << welt.text() << endl; welt = string("Welt"); cout << welt.was() << endl; Vielleicht<string> cut; cut = hallo + string(" ") + welt; cout << cut.text() << endl; cut = hallo / welt; cout << cut.text() << endl; return 0; }
-
SeppJ schrieb:
Falsche Signatur der Spezialisierung, daher passt sie nicht. Sie muss lauten:
template<> Vielleicht<std::string> Vielleicht<std::string>::operator/(const Vielleicht<std::string>&)
danke das war die Lösung, jetzt habe ich meine gewünschte Ausgabe
-
Mein Edit kam ein wenig spät...
-
Wenn die Klasse nur für Ganzzahltypen Sinn macht, wieso machst du dann eine Spezialisierung für eine andere Klasse? Das verbirgt doch nur den Fehler, dass die Aktion keinen Sinn macht. Das ist ein Fall für einen Compilezeitfehler, keinen Laufzeitfehler! Das finde ich ganz schlechtes Design.
Weitere Designfehler:
-manuelle Speicherverwaltung in einer Klasse, deren Aufgabe das nicht ist. Halte die Daten in einer auf manuelle Speicherverwaltung spezialisierten Klasse. Hier scheinen sich dafür die fertigen Standardklassen vector oder valarray anzubieten. Zumindest unter der Annahme, dass da später mal mehr als ein Wert verwaltet werden soll. Denn warum man einen Wrapper um einen einzelnen arithmetischen Wert haben sollte wäre mir total rätselhaft.
-A propos valarray: Kann's sein, dass du gerade valarray nachprogrammierst?
-
SeppJ schrieb:
Wenn die Klasse nur für Ganzzahltypen Sinn macht, wieso machst du dann eine Spezialisierung für eine andere Klasse? Das verbirgt doch nur den Fehler, dass die Aktion keinen Sinn macht. Das ist ein Fall für einen Compilezeitfehler, keinen Laufzeitfehler! Das finde ich ganz schlechtes Design.
Weitere Designfehler:
-manuelle Speicherverwaltung in einer Klasse, deren Aufgabe das nicht ist. Halte die Daten in einer auf manuelle Speicherverwaltung spezialisierten Klasse. Hier scheinen sich dafür die fertigen Standardklassen vector oder valarray anzubieten. Zumindest unter der Annahme, dass da später mal mehr als ein Wert verwaltet werden soll. Denn warum man einen Wrapper um einen einzelnen arithmetischen Wert haben sollte wäre mir total rätselhaft.
-A propos valarray: Kann's sein, dass du gerade valarray nachprogrammierst?Nein das ist eine Praktikum Aufgabe, ich denke mal das soll auf evtl. auftretende Fehler hindeuten bzw. das diverse Operationen nicht für alle Datentypen definiert sind...aber wenn wir schon beim Sinn von Templates sind, wie kann man den eine Template so definieren das sie z.B "nur" für Ganzzahlen kompatible ist?
Also wie bei java mit "extends Number"
-
DKlay schrieb:
SeppJ schrieb:
Wenn die Klasse nur für Ganzzahltypen Sinn macht, wieso machst du dann eine Spezialisierung für eine andere Klasse? Das verbirgt doch nur den Fehler, dass die Aktion keinen Sinn macht. Das ist ein Fall für einen Compilezeitfehler, keinen Laufzeitfehler! Das finde ich ganz schlechtes Design.
Weitere Designfehler:
-manuelle Speicherverwaltung in einer Klasse, deren Aufgabe das nicht ist. Halte die Daten in einer auf manuelle Speicherverwaltung spezialisierten Klasse. Hier scheinen sich dafür die fertigen Standardklassen vector oder valarray anzubieten. Zumindest unter der Annahme, dass da später mal mehr als ein Wert verwaltet werden soll. Denn warum man einen Wrapper um einen einzelnen arithmetischen Wert haben sollte wäre mir total rätselhaft.
-A propos valarray: Kann's sein, dass du gerade valarray nachprogrammierst?Nein das ist eine Praktikum Aufgabe, ich denke mal das soll auf evtl. auftretende Fehler hindeuten bzw. das diverse Operationen nicht für alle Datentypen definiert sind...aber wenn wir schon beim Sinn von Templates sind, wie kann man den eine Template so definieren das sie z.B "nur" für Ganzzahlen kompatible ist?
Also wie bei java mit "extends Number"
- duck typing, wenn man etwas mit einem typen T instanziiert wobei der typ T gewisse voraussetzungen nicht erfüllt, gibt es compilererrors.
- enable_if: (mit vorbehalt da ich keine ahnung von c++11 habe)#include <type_traits> template<typename T> class VielleichtImpl { // ... }; template<typename T> using Vielleicht = VielleichtImpl<typename std::enable_if<std::is_integral<T>::value, T>::type>;
-
DKlay schrieb:
Nein das ist eine Praktikum Aufgabe, ich denke mal das soll auf evtl. auftretende Fehler hindeuten bzw. das diverse Operationen nicht für alle Datentypen definiert sind...aber wenn wir schon beim Sinn von Templates sind, wie kann man den eine Template so definieren das sie z.B "nur" für Ganzzahlen kompatible ist?
So direkt leider (noch) gar nicht. Aber das ergibt sich eben ganz von alleine, da es ansonsten zu Compilerfehlern kommt, wenn der Typ nicht passt. Und wenn es doch passt, dann ist wohl alles in Ordnung, selbst wenn du von dem Typen noch nie gehört hast und beim Programmieren gar nicht an diese Möglichkeit gedacht hast (zum Beispiel meine eigene Ganzzahlklasse).
Ich werfe auch mal boost::enable_if als Stichwort in den Raum.
-
SeppJ schrieb:
DKlay schrieb:
Nein das ist eine Praktikum Aufgabe, ich denke mal das soll auf evtl. auftretende Fehler hindeuten bzw. das diverse Operationen nicht für alle Datentypen definiert sind...aber wenn wir schon beim Sinn von Templates sind, wie kann man den eine Template so definieren das sie z.B "nur" für Ganzzahlen kompatible ist?
So direkt leider (noch) gar nicht. Aber das ergibt sich eben ganz von alleine, da es ansonsten zu Compilerfehlern kommt, wenn der Typ nicht passt. Und wenn es doch passt, dann ist wohl alles in Ordnung, selbst wenn du von dem Typen noch nie gehört hast und beim Programmieren gar nicht an diese Möglichkeit gedacht hast (zum Beispiel meine eigene Ganzzahlklasse).
Ich werfe auch mal boost::enable_if als Stichwort in den Raum.
Naja das beste Beispiel wäre ja die max funktion, die den größten wert zurückgibt...scheitert aber an char*, da sie die Adressen vergleich und somit ja nicht zufriedenstellend arbeitet. Hier ist ja eine Spezialisierung notwendig.
-
Ich werfe auch mal boost::enable_if als Stichwort in den Raum.
Weil
std::enable_ifes nicht tut? Da braucht man nicht Boost ins Projekt einzubinden, um eine kleine Spezialisierung zu schreiben...
-
DKlay schrieb:
SeppJ schrieb:
DKlay schrieb:
Nein das ist eine Praktikum Aufgabe, ich denke mal das soll auf evtl. auftretende Fehler hindeuten bzw. das diverse Operationen nicht für alle Datentypen definiert sind...aber wenn wir schon beim Sinn von Templates sind, wie kann man den eine Template so definieren das sie z.B "nur" für Ganzzahlen kompatible ist?
So direkt leider (noch) gar nicht. Aber das ergibt sich eben ganz von alleine, da es ansonsten zu Compilerfehlern kommt, wenn der Typ nicht passt. Und wenn es doch passt, dann ist wohl alles in Ordnung, selbst wenn du von dem Typen noch nie gehört hast und beim Programmieren gar nicht an diese Möglichkeit gedacht hast (zum Beispiel meine eigene Ganzzahlklasse).
Ich werfe auch mal boost::enable_if als Stichwort in den Raum.
Naja das beste Beispiel wäre ja die max funktion, die den größten wert zurückgibt...scheitert aber an char*, da sie die Adressen vergleich und somit ja nicht zufriedenstellend arbeitet. Hier ist ja eine Spezialisierung notwendig.
ich weiss, dass ich mir mit dieser aussage keine freunde mache, jedoch finde ich noch immer, dass char* oder char const* keine typen sind für zeichenketten (das wäre std::string) sondern einfach pointer-typen. std::max für std::string funktioniert hingegen auch.
-
asfdlol schrieb:
ich weiss, dass ich mir mit dieser aussage keine freunde mache, jedoch finde ich noch immer, dass char* oder char const* keine typen sind für zeichenketten (das wäre std::string) sondern einfach pointer-typen. std::max für std::string funktioniert hingegen auch.
std::string ist leider auch nicht der ultimative Typ für Zeichenketten. std::string bedeutet "String mit eigenem Memory-Management (und zwar pro Instanz)". Für alles andere braucht man eigene Typen. Es wird Zeit, dass es eine string_ref-Klasse gibt, die wäre dann der echte String-Typ.