static_cast<double>(x) vs double(x)
-
Welche der 2 Varianten ist besser?
int x = 16; double a = static_cast<double>(x) / 10; double b = double(x) / 10;
Ich finde die erste Variante zwar sauberer, aber umständlich und schwer zu lesen.
Welche Variante benutzt ihr normalerweise?
-
x/10.
-
@a=a->next:
Ich würde die zweite Variante bevorzugen. Was ist denn an der ersten bitte sauberer?
@davie:
Was willst Du uns mit x/10 sagen?MfG Jester
-
er findet wohl
int x = 16; double b = x/10.;
am besten. das ist auch die variante zu der ich neige. ausser es gibt einen grund warum man besonders signalisieren will, dass hier eine umwandlung durchgeführt wird.
-
Ups... hab den Punkte nicht richtig gedeutet.
Das halte ich allerdings für keine so dolle Lösung. Dann wenigstens ein 10.0, das wäre dann wohl mein Favorit. Aber einfach nur den Punkt finde ich zu wenig. Das sieht man nicht gut genug.MfG Jester
-
war etwas zu kurz gefasst
ja, die null nehme ich auch noch meistens dazu, sonst sieht es so unintuitiv aus
-
Hi,
ich nehme normalerweise immer den static_cast, da ich so am besten sehe, wo eine Konvertierung durchgeführt würde (wobei int -> double ja nicht kritisch ist, weil dabei ja nichts verloren kann, anders würde es z.B. bei double -> int aussehen!).
Ansonsten einfach die Variante mit .0, denn int / double = double.
ChrisM
-
Jester schrieb:
Ich würde die zweite Variante bevorzugen. Was ist denn an der ersten bitte sauberer?
naja, die erste kann machen was sie will. du kannst ihr ne erdbeere geben und per functional style cast kannst du dir daraus einen elefanten zaubern - finde ich nicht gerade sinnvoll.
einfache Regel:
benutze den schwächsten cast, der gerade noch das macht, was du brauchst.
-
Naja, die Logik rechtfertigt IMHO aber auch keinen static_cast.
template<typename To, typename From> inline To make(From arg) { return arg; } doubleVar = make<double>(intVar) / 10;
Struppi schlägt sowas wimni als "implicit_cast<>" vor, und wenn es sowas standardisiert gäbe, würde ich es auch lieber verwenden als static_cast... Warum es Konstruktor-Style-Casts überhaupt gibt bzw. warum sie so gefährlich sind, ist mir ehrlich gesagt ein Rätsel. Habe ich das schonmal gefragt? Steht das in D&E drin?
-
operator void schrieb:
Naja, die Logik rechtfertigt IMHO aber auch keinen static_cast.
Logisch. Aber es gibt nichts besseres (im Standard).
die 10.0 Variante ist natürlich am besten - aber gehen wir einmal davon aus, dass 10.0 eine Variable vom Typ int ist.Struppi schlägt sowas wimni als "implicit_cast<>" vor, und wenn es sowas standardisiert gäbe, würde ich es auch lieber verwenden als static_cast...
Habe das zwar noch nicht von Struppi gehört, aber von Josuttis und Vandevoorde:
template <typename To, typename From> To implicit_cast (From const& value) { return value; }
so was ähnliches findet sich in 'C++ Templates'
Warum es Konstruktor-Style-Casts überhaupt gibt
Wegen:
string foo() { char* s="Hallo"; return string(s); }
es ist einfach ein Ctor aufruf
bzw. warum sie so gefährlich sind, ist mir ehrlich gesagt ein Rätsel.
Das explicit von Ctors wird umgangen.
zB istreturn string(2);
erlaubt.
2 gibt die größe des zu allokierenden speichers an.
Das ist nicht das was der autor des codes wollte - aber der compiler beschwert sich nicht.
-
allerdings: wenn ichs mir recht überlege dann kann implicit_cast nicht funktionieren...
deshalb wird boost vermutlich auch kein implicit_cast haben
-
Die Parallelen zu "normalen" Konstruktoren habe ich gesehen, aber normale Konstruktoren sind eben nicht gefährlich (normalerweise). string(5.34) geht nicht, int(&errno) aber schon. Warum erlaubt man nicht einfach nur int-Pseudokonstruktoren für Typen, die man int auch zuweisen kann? Dann wäre an double(5) nichts Verwerfliches.
Warum sollte implicit_cast btw nicht funktionieren? Ich sehe da gerade kein Problem, allerdings *auf die Uhr zeig*
-
operator void schrieb:
Dann wäre an double(5) nichts Verwerfliches.
AFAIK ist double(5) äquivalent zu static_cast<double>(5)
Ctors sind eben DOCH gefährlich. Denn wenn du einen Ctor als explicit deklarierst, sagst du ja: bitte nicht für Typ-Konvertierungen verwenden -> und genau das hebelt der functional style cast aus.
Warum sollte implicit_cast btw nicht funktionieren? Ich sehe da gerade kein Problem, allerdings *auf die Uhr zeig*
Angenommen der cast wäre 'richtig' geschrieben:
template<typename T> struct its { typedef T type; }; template<typename T> T implicit_cast(its<T>::type value) { return value; }
dann würde folgendes ziemlich fatal sein:
double const& r = implict_cast<double const&>(1); double d=r; //UB
denn 1 ist ein temporary - und das wird gekillt
folglich referenziert r eine nicht vorhandene variable...wenn du damit leben kannst, ist der implicit_cast OK - ich finde es aber zu riskant.
btw: in letzter Zeit gehen mir rvalues und temporaries gewalt auf die nerven... irgendwie scheinen die nicht für templates geeignet zu sein.
-
Shade Of Mine schrieb:
[Ctors sind eben DOCH gefährlich. Denn wenn du einen Ctor als explicit deklarierst, sagst du ja: bitte nicht für Typ-Konvertierungen verwenden -> und genau das hebelt der functional style cast aus.
Das sehe ich nicht so. Ein explicit deklarierter CTor sagt: bitte nicht für implizite Umwandlungen verwenden. Wollte ich auch noch explizite Typumwandlungen verhindern würde ich den Konstruktor wegmachen. Insofern sehe ich auch nicht, wo ein function style cast irgendwas aushebelt. Ich wandle damit nur einen Typen in einen anderen um. Und zwar von einem, aus dem man gefahrlos ein double konstruieren kann.
MfG Jester
-
Hallo,
da möchte ich mich Jester doch mal ganz wehement anschließen. Ein Konstruktor ist dazu da ein Objekt zu erstellen. Wenn man nicht will, dass ein Objekt mit bestimmten Parametern erstellt werden kann, dann sollte man keinen Konstruktor dafür anbieten.AFAIK ist double(5) äquivalent zu static_cast<double>(5)
Das AFAIK kannst du streichen und durch "laut Standard" ersetzen.
-
Jester schrieb:
Das sehe ich nicht so. Ein explicit deklarierter CTor sagt: bitte nicht für implizite Umwandlungen verwenden. Wollte ich auch noch explizite Typumwandlungen verhindern würde ich den Konstruktor wegmachen.
Ein Ctor ist ja nicht nur für Umwandlungen da.
Nimm zB mal den Ctor von vector:explicit vector::vector<size_type n, T const& = T());
ein vernünftiger Ctor. Man kann den vector gleich von beginn an mit zB 70 Ts füllen. Ich finde dies durchaus praktisch, sinnvoll und effizient.
Wenn wir diesen Ctor nun wegmachen, da er ja eine Umwandlung size_type > vector erlaubt, wäre der Code nicht mehr so schön. Denn dann müsste ich ja
vector vec;
vec.assign(70);schreiben. dh ich habe einen DefaultCtor call, den ich nicht brauche. Mir persönlich dreht sich bei sowas der Magen um...
alternative Lösung:
default Parameter wegnehmen. Dan müsste ich
vector vec(70, T());
schreiben - das ist auch nicht gerade ideal. Denn in 90% der Fälle brauche ich ja nur T(), da ich standardwerte will.Was würdest du also vorschlagen wie vector designt werden sollte?
btw: check mal das:
#include <iostream> using namespace std; int main() { int i=10; int const& ir=i; typedef int& ref; ref dr=ref(ir); dr=5; cout<<i<<' '<<ir<<' '<<dr<<'\n'; }
stichwort: const_cast
-
Ich finde vector schön, so wie er ist.
Aber Du sagtst die double(x) Schreibweise sei gefährlich, weil man damit sozusagen ne implizite Konvertierung durchführen kann... und das will mir irgendwie nicht so richtig in den Kopf, wie soll ich denn bitte noch expliziter hinschreiben, daß ich da jetzt ein double draus machen will. Also ist es doch eine explizite Umwandlung, oder nicht? Daher mein Argument, wenn Du die verhindern willst, dann mach den Konstruktor weg.Der Zusammhang zwischen der Konvertierung von Zahlen und dem Referenzen-Beispiel ist mir nicht ganz klar.
Ich habe ja nicht gesagt, daß man grundsätzlich functional style casts machen sollte. Aber für Konvertierung von Zahlenwerten finde ich sie deutlich angenehmer als ein static_cast...MfG Jester
-
Jester schrieb:
Also ist es doch eine explizite Umwandlung, oder nicht? Daher mein Argument, wenn Du die verhindern willst, dann mach den Konstruktor weg.
Explizite Umwandlung? Naja, ich würde nicht von Umwandlung sprechen, sondern von Konstruierung. Es wird explizit ein Objekt vom Typ vector erstellt, der 1 int als Param nimmt. Und nicht: int wird nach vector gecastet...
vector(1);
Der Zusammhang zwischen der Konvertierung von Zahlen und dem Referenzen-Beispiel ist mir nicht ganz klar.
In C++ gibt es Templates - und mir ist es schon sehr oft passiert, dass ich eine non-Template Funktion später in eine Template Funktion umgewandelt habe.
Ich habe ja nicht gesagt, daß man grundsätzlich functional style casts machen sollte. Aber für Konvertierung von Zahlenwerten finde ich sie deutlich angenehmer als ein static_cast...
Ich habe es lieber einheitlich... Nicht einmal functional style cast und dann wieder static_cast. Irgendwie gefällt es mir nicht wenn man das dauernd ändert.
Ich halte mich an die alte Weisheit:
Nimm den schwächsten Cast, der gerade noch das macht, was du willst.Hier static_cast ist wie wenn ich mit einer Kanone auf Spatzen schiesse, aber der functional style cast greift die Spatze mit Cruise Missiles an
Aber erklär mir mal die Vorteile vom functional style cast, ausser die geringer Schreibarbeit.
-
Ja, stimmt Konstruktion ist der bessere Ausdruck.
Und double(x) spricht irgendwie deutlich: konstruiere mir aus dem x bitte nen passenden double.
Eigentlich sehr schade, daß dieser Cast so "mächtig" ist.
Ob es davon jetzt konkrete Vorteile gibt kann ich nicht sagen, aber mir gefällt die Schreibweise halt. Und für so gefährlich, wie es hier teilweise dargestellt ist ist der Cast auch nicht. Insbesondere wenn ich ihn nur zum umwandeln von Zahlen in Zahlen verwende.
-
@Shade
Also ich verstehe deinen Punkt im Moment überhaupt nicht.Was würdest du also vorschlagen wie vector designt werden sollte?
Genauso wie es ist. Nämlich mit explicit Ctor. Ich kann den Ctor nicht für implizite Umwandlungen verwenden, ich kann also nicht schreiben 2 und schwups habe ich einen Vektor. Ich kann natürlich aber einen Vektor erzeugen und 2 als Argument übergeben: vector(2). Was ist dein Punkt?
Explizite Umwandlung? Naja, ich würde nicht von Umwandlung sprechen, sondern von Konstruierung. Es wird explizit ein Objekt vom Typ vector erstellt, der 1 int als Param nimmt. Und nicht: int wird nach vector gecastet...
Und? Der Punkt ist doch das explizit nicht cast.
int i;
double(i) ist der Art offensichtlich, dass ich irgendwie nicht das Problem sehe.Ich halte mich an die alte Weisheit:
Nimm den schwächsten Cast, der gerade noch das macht, was du willst.Und wie wir bereits festgestellt haben ist double(x) äquivalent zu static_cast<double>(x). Da zerbricht die von dir gezogene Konsequenz doch.
Hier static_cast ist wie wenn ich mit einer Kanone auf Spatzen schiesse, aber der functional style cast greift die Spatze mit Cruise Missiles an
Seit wann sind Spatzen äquivalent zu Cruise Missiles?
Aber erklär mir mal die Vorteile vom functional style cast, ausser die geringer Schreibarbeit
Beide sind hier äquivalent. Ergo:
erklär mir den Vorteil von persönlichem Geschmack.
-
Shade Of Mine schrieb:
Habe das zwar noch nicht von Struppi gehört, aber von Josuttis und Vandevoorde:
template <typename To, typename From> To implicit_cast (From const& value) { return value; }
so was ähnliches findet sich in 'C++ Templates'
Kannst du mir mal die Seitenzahl geben. Ich muss zu meiner Schande gestehen, dass ich mich weder daran erinnere, noch das ich die Stelle jetzt auf die Schnelle finde.