Konstante bei Klassentemplate?
-
Hallo,
noch eine kleine Frage zu Konstanten bei Klassentemplates. Meine Matrixklasse soll eine Methode setIdentity() haben, die die Matrix zu einer Einheitsmatrix macht:
template <class T> void Matrix<T>::setIdentity() { assert(n == m); for(uint i=0; i < n*m; i++) data[i] = i % (n+1) ? 0 : 1; // Zeile A }Das Problem sind die Konstanten 0 und 1. Wenn ich eine int Matrix anlege (Matriy<int>), dann passt natürlich alles. Wenn ich allerdings eine float Instanz erzeuge, kriege ich folgendes Warning beim Kompilieren von Zeile A:
warning C4244: '=' : conversion from 'int' to 'float', possible loss of data
Kann man dieses Problem irgendwie lösen, dass ich keine Warnungs mehr kriege, egal ob ich eine int, long, float oder double Matrix anlege?
-
Du kannst ein static_cast davorsetzen. Deine Loesung ist aber nicht gut. Angenommen ich moechte die Klasse mit komplexen Zahlen verwenden (in der Physik Standard). Da weiss ich nicht, ob static_cast<complex>( 1 ) funktioniert.
Alternativ kannst du einen anderen Compiler verwenden, der g++ mit -Wall -ansi -pedantic bringt diese Warnung nicht (habe ich aber nicht ausprobiert).
-
Dass meine Lösung nicht gut ist, weiß ich. Drum frage ich ja hier

Die Frage ist: Wie geht es besser?
-
Für die eingebauten Typen ist das wohl übertrieben. Solche Warnungen sind zum Teil recht nervig und oft unnötig, zumal C++ implizite Konvertierungen zwischen arithmetischen Typen ausdrücklich erlaubt. Du kannst zum Beispiel
static_cast<T>nehmen oder die Warnung deaktivieren.Aber falls du plötzlich noch komplexere Typen hast, könntest du eine Art Traits erstellen, mit "leerem" (0) oder "Standard-" (1) Wert, ähnlich wie bei
std::numeric_limits. Nicht dass du das jetzt implementierst, das lohnt sich wirklich kaum. Aber um dir grundsätzlich mal so eine Möglichkeit zu zeigen, die auch in anderen Situationen praktisch sein kann...
Edit: Ich hab wohl etwas lange für meinen Beitrag gebraucht...
-
hmmmm,
spontan fällt mir eine "Konvertierungsfunktion"(stemplate) ein ...
template <typename T> T f(bool is); template <> int f<int>(bool is) { return is ? 0 : 1; } template <> double f<double>(bool is) { return is ? 0lf : 1lf; } template <> float f<float>(bool is) { return is ? 0f : 1f; } template <class T> void Matrix<T>::setIdentity() { assert(n == m); for(uint i=0; i < n*m; i++) data[i] = f<T>(i % (n+1)); }Prinzipiell musst Du Dir überlegen, was "0" und "1" eigentlich zu bedeuten haben und das lagerst Du dann in die Spezialisierung von f aus - man kann ja auch Matrix<WordDokument> nutzen wollen ...
Gruß,
Simon2.
-
Danke euch beiden! Ich sehe das wie Nexus und werde die 1 und 0 einfach auf T casten, da ich absolut NIE eine Matrix mit complex oder was anderem "freakigen" brauchen werde.
Ehrlich gesagt finde ich das Warning auch ziemlich dumm. Ich dachte ich kann 1 und 0 problemlos in alle Zahlentypen casten. Wie soll denn bitte Genauigkeit beim casten von 1 in einen float verloren gehen? oO
-
Verwirrter schrieb:
Ehrlich gesagt finde ich das Warning auch ziemlich dumm. Ich dachte ich kann 1 und 0 problemlos in alle Zahlentypen casten. Wie soll denn bitte Genauigkeit beim casten von 1 in einen float verloren gehen? oO
Ich hab zu Konversionen zwischen arithmetischen Typen in C++ gerade einen Diskussionsthread gestartet.

-
Verwirrter schrieb:
...da ich absolut NIE ...brauchen werde....
Das steht schon auf vielen Grabsteinen. :p

Mal im Ernst: Dann würde ich eher mit den Warnungen leben.
Gruß,
Simon2.
-
Simon2 schrieb:
Mal im Ernst: Dann würde ich eher mit den Warnungen leben.
Mit ihnen leben finde ich grundsätzlich schlecht. So gewöhnt man sich an, Warnungen nicht mehr zu beachten, zudem gehen andere Warnungen oder Fehler leicht unter.
In MSVC++ kann man Warnungen zum Beispiel nur lokal deaktivieren:
#pragma warning(push) #pragma warning(disable: 4244) // Alle Warnungen vom Typ 4244, die aus // dem Code hier resultieren, werden ignoriert. #pragma warning(pop)Aber beim Beispiel von hier fände ich einen Cast okay.
-
Nexus schrieb:
Simon2 schrieb:
Mal im Ernst: Dann würde ich eher mit den Warnungen leben.
Mit ihnen leben finde ich grundsätzlich schlecht. So gewöhnt man sich an, Warnungen nicht mehr zu beachten, zudem gehen andere Warnungen oder Fehler leicht unter....
Also bei mir (und in meiner Situation) hat das den gegenteiligen Effekt: Sie sind mir ein steter Dorn im Fleisch und mahnen mich ständig daran, dass da noch etwas zu beachten und möglicherweise zu verbessern ist.
Ich spreche aber von (m)einer bestimmten Situation: Im Rahmen der Programmentwicklung merze ich alle Fehler und Warnings aus .... bis dann "diese 2" übrigbleiben. Habe ich entschieden, diese Warnings "stehen zu lassen" (z.B. aus Termingründen oder weil die Nachteile aller (mir einfallenden) Alternativen überwiegen), geht das Modul irgendwann in Produktion.
Fällt es mir dann wieder in die Hand (wg. Wartung/Weiterentwicklung), springen mir beim ersten Compile die beiden Warnings wieder ins Auge und ich überlege erneut, ob es nicht doch Mittel und Wege gibt, sie loszuwerden.
Ganz wesentlich dabei natürlich: Das mache ich nicht mit 100 Warnings - so ein Programm würde ich "nie"* in Produktion geben.Bei mir hat ein cast genau den von Dir beschriebenen Effekt: Die Sache taucht nie wieder auf.
Allerdings muss ich auch sagen, dass ich relativ viel unter zOS mit reinem C/89 arbeiten muss, was bedeutet:
- keine qualifizierten Casts und
- Sourcen nur in einem 72x40-Zeichen-Texteditor anzusehen.
Außerdem gibt es eine Menge Code, der plattform- und compilerübergreifend genutzt wird, weswegen ich mit pragmas so gut wie gar nicht arbeiten kann.Da ist es hilfreicher, den Compiler die "schwammige Stelle" anzeigen zu lassen.
*: Sag niemals nie

Gruß,
Simon2.
-
In diesem Fall sehe ich kein Problem mit einem cast. Wenn der hier nicht funktioniert, dann ist es wahrscheinlich auch nicht möglich eine Einheitsmatrix mit diesem Typen zu basteln. Da ist eine Fehlermeldung wohl korrekt.