Number Type Cast



  • Hi,

    I often need to convert/cast integer variables to double for multiplication/division:

    int a = 10;
    int b = 3;
    
    double c = static_cast<double>(a) / b;
    

    In general I use a static_cast, but I also think this is quite ugly to read. To convert the type there are of course multiple ways:

    int a = 10;
    int b = 3;
    
    double c = static_cast<double>(a) / b;
    double d = double(a) / b;
    double e = (double)a / b;
    

    I think the best for reading the code is double d = double(a) / b;. But I don't know if there's a difference and when to use which.


  • Qt Champions 2018

    @beecksche In C++ you should use static_cast and avoid C casts in general.
    See https://www.quora.com/What-are-the-disadvantages-of-C-style-casting-in-C++


  • Moderators

    @jsulm is of course correct

    but to add my 2 cents,

    double d = double(a) / b;

    is technically not a cast, if memory serves me right.


  • Qt Champions 2018

    @J.Hilk you are right, it's kind of constructor constructor style cast. But it's C++ and less ugly than static_cast. Qt and me prefer this for primitive types, i.e. int, float etc.

    [Edit aha_1980: incorporated comments from kshegunov]


  • Qt Champions 2017

    @aha_1980 said in Number Type Cast:

    @J.Hilk you are right, it's kind of constructor.

    There are no constructors for primitive types, thus it's no constructor. The "constructor-style cast", which is what you refer to, is of course the same as every other option performance-wise, so it's a matter of aesthetic preference.


  • Qt Champions 2018

    @kshegunov Yeah, you're right, I didn't remember the exact name.

    What I wanted to point out is, that this is C++ and has nothing to do with C casts.


  • Qt Champions 2017

    @aha_1980 said in Number Type Cast:

    What I wanted to point out is, that this is C++ and has nothing to do with C casts.

    The constructor-style cast is completely equivalent to the C-style cast. It happily casts away const for example. So there's nothing special about it semantically. That is to say:

    Type2 x;
    
    Type1 y1 = (Type1) x;
    Type1 y2 = Type1(x);
    

    are absolutely the same from the compiler's point of view.



  • @kshegunov said in Number Type Cast:

    The constructor-style cast is completely equivalent to the C-style cast. It happily casts away const for example. So there's nothing special about it semantically.

    May I ask that you elaborate a bit more this statement above. It is not clear to me what you mean with "casts away"

    Type2 x;
    
    Type1 y1 = (Type1) x;
    

    MinGW and code model would complain with a warning for the statement above.

    Type1 y2 = Type1(x);

    MinGW and code model will not throw a warning at you.

    Therefore I am using the last one.


  • Qt Champions 2017

    @koahnig said in Number Type Cast:

    May I ask that you elaborate a bit more this statement above. It is not clear to me what you mean with "casts away"

    const void * x;
    int y = int(x);
    

    compiles just fine. static_cast on the other hand should deny your stripping away the const qualifier.



  • @koahnig
    I'm surprised at what you say about MinGW warning for one and not the other. I've looked around the web and do not find anywhere mentioning possibly different compiler warning behaviour. I'd have expected to see it mentioned in e.g. https://stackoverflow.com/questions/4474933/what-exactly-is-or-was-the-purpose-of-c-function-style-casts or https://stackoverflow.com/questions/45505861/function-style-cast-vs-constructor.


  • Moderators

    @kshegunov said in Number Type Cast:

    const void * x;
    int y = int(x);
    

    compiles just fine. static_cast on the other hand should deny your stripping away the const qualifier.

    actually no,
    as int my be a smaller type than a pointer ;-)
    But, of course with int64_t it works fine.

    But I'm nitpicking ..

    Don't we have const_cast for the above mentioned cases ?



  • @JonB

    0_1551991918704_8e8a8bb4-6da9-47fe-82ad-b84b75de805d-image.png

    OK, I should have the "IIRC" there as I had before. Apparently current versions of MinGW do not.

    Anyway, I tend to get rid of warnings as much as possible. Mainly because I left warnings in the far past and a missed warning caught me later on.


  • Qt Champions 2017

    @J.Hilk said in Number Type Cast:

    actually no,

    Actually yes. Almost all errors that fall in the -fpermissive are there to prevent you from shooting yourself in the foot. The compiler can compile it just fine, hence the existence of the aforementioned flag. As a matter of fact if you try it with MSVC you're (probably with surprise) going to realize that it eats it just fine - no errors, just a warning or so.

    as int my be a smaller type than a pointer ;-)

    So? Substitute void * with long long and see what happens ... pure magic ... Truncation is unimportant here, and truncation is not an error by the way.

    Don't we have const_cast for the above mentioned cases ?

    Indeed, and some compilers may just allow you to static_cast it too depending on the types and how the compiler's implemented. However, here's a better snippet for your consideration:

    typedef void* voidp;
    
    const int * x;
    void * y = static_cast<voidp>(x); // Case 1
    void * z = voidp(x);              // Case 2
    

    Case 1 is an error, because you're trying to const_cast and static_cast at the same time, Case 2 is valid and compiles fine. Most of the time this is harmless, obviously, as with the case of primitive types, but, and I repeat again, there's no semantic difference between C-style casts and constructor-style casts; they are exactly the same thing.



  • As I often need to code in several different languages I try to make my expressions as language agnostic as possible. Unless performance is a consideration I often do this to force a type conversion:

    int a(12);
    int b(15);
    double d(a / (b + 0.0));
    

    in many lanuages there will be an implicit conversion to floating point, and I prefer my conversion in the denominator.



  • @Kent-Dorfman This is a new one on me --- try to write code in one language so it will also work in another :)



  • I have nothing significant to add to this discussion other than I still do C style casts in my C++ code. I am still not used to using all the new casting templates (they are templates right?).

    So whether you use C or C++ casts just Cast Away!


  • Qt Champions 2017

    @fcarney said in Number Type Cast:

    they are templates right?

    No, they're operators.



  • Really interesting disucssion. I'm with @jsulm and use the "constructor-style cast" for primitives types.

    int a = 10;
    double b = double(a);
    

    And for safety reasons *_cast for classes

    MyBaseClass *base;
    
    MyDerivedClass *derived = static_cast<MyDerivedClass*>(base);
    

  • Qt Champions 2018

    @beecksche I actually wrote that C style casts should be avoided in general (means: for all types including primitive types).


  • Lifetime Qt Champion

    @beecksche said in Number Type Cast:

    MyDerivedClass derived = static_cast<MyDerivedClass>(base);

    Just one note: static_cast has absolutely no notion of safety. There's no check involved so you are completely responsible to ensure that the type you are casting to is really is valid with regard to the type you are casting from.

    dynamic_cast does check and in the case of pointers return a null pointer that you can validate before continuing your code.



  • @jsulm , @SGaist

    thanks a lot. I thought I had understood the problem. But it seems to be a bit more complicated.

    Hopefully, in some time, I will understande when to use which cast explicitly and for what reason.

    Until thenI hope that these parts of the code don't make any trouble.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.