static_cast<double>(x) vs double(x)



  • 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.



  • HumeSikkins schrieb:

    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?

    Mein Punkt ist, dass 2 nicht in vector umgewandelt werden kann.

    Dieser Code:

    template<typename To, typename From>
    To convert(From value)
    {
      return To(value);
    }
    

    sieht zwar OK aus - tut aber nicht das gewünschte.
    Und genau das ist beim functional style cast die Gefahr.

    Und? Der Punkt ist doch das explizit nicht cast.
    int i;
    double(i) ist der Art offensichtlich, dass ich irgendwie nicht das Problem sehe.

    für builtins ist es ja OK - aber die Gefahr ist, dass aus den builtins mal ne Klasse wird (Ich würde builtins und Objekte nicht unterschiedlich behandeln)

    Und wie wir bereits festgestellt haben ist double(x) äquivalent zu static_cast<double>(x). Da zerbricht die von dir gezogene Konsequenz doch.

    solange es bei double bleibt: ja.

    Aber kannst du garantieren dass double nicht später durch eine Klasse für große Gleitkommazahlen ersetzt wird? Dann ist Double(x) nämlich nicht mehr äquivalent zu static_cast<Double>(x).

    Die Seitenzahl aus C++ Templates weiss ich auch nicht. Hab den code von http://www.josuttis.com/tmplbook/details/implicit.cpp.html - und da ist mir gleich aufgefallen dass meine erinnerung falsch war - denn der code ging doch etwas anders... Aber die Probleme die implicit_cast hat, sind leider zu groß 😞 siehe auch boost-mailingliste



  • Shade Of Mine schrieb:

    solange es bei double bleibt: ja.
    Aber kannst du garantieren dass double nicht später durch eine Klasse für große Gleitkommazahlen ersetzt wird? Dann ist Double(x) nämlich nicht mehr äquivalent zu static_cast<Double>(x).

    Ähm, wenn ich der Klasse nen schönen Konstruktor verpasse, kann ich die Syntax doch beibehalten oder? Wenn mich nicht alles täuscht dürfte das mit dem static_cast sogar schwieriger werden.
    Insofern finde ich den Stil so sogar einheitlicher. Objektkonstruktion geht mit nem Konstruktor, und nur weil die beiden Typen halt eingebaut und sogar ineinander umwandelbar sind mache ich da auch keinen Unterschied.
    Das müßte demnach doch eigentlich in Deinem Sinne sein.


Anmelden zum Antworten