18
acz0903
11d

What's wrong with this code?

std::pair<float, float> foo() { return { 0, 0 }; }

"Nothing," would you say.

That's because you're normal.

But the most stupid C++ compiler ever (M$ VS)
issues an ERROR that converting 0 to float incurs possible "loss of data". So you have to write "0.f".

BTW, "0." is a double, so you really have to write "0.f". Or "static_cast<float>(0)" if you like ugly, impossible-to-read code.

Comments
  • 1
    Does it still complain if you explicitly write
    std::make_pair<float, float>(0, 0)
    ?

    Edit: gcc doesn't seem to complain about this, haven't tried it with clang but it does seem to be a ms thing
  • 0
    I write JS, don’t ask these stupid questions. /s
  • 1
    I feel you. I feel you soooo much.

    You can write

    return {float(0), float(0)}

    which in my opinion makes it a little less ugly.
  • 7
    I immediately thought of .f as I read that line, so I guess my brain has been sufficiently broken by now.

    Where's that shotgun?
  • 0
    The pair default constructor gives you 2 default initialised values (ie 0.0, 0.0). Or you can write an explicit float value, ie 0.0
  • 0
    Somebody explain to me again please why c++ doesn't issue accuracy warnings on constexpr based on evaluating the expression and seeing if a precision error actually occurs?
  • 1
    @homo-lorens define "loss of accuracy". Does 1/3 result in loss of accuracy? I think basically its part of the definition of the language. If you need that level of precision, there are rational classes that are essentially lossless.
  • 0
    I fail to see why I couldn't assign 0.125 to a float at compile time, especially since it's evaluated as part of the compilation process anyway so it doesn't even require extra steps other than converting back and comparing with the user-provided value.
  • 0
    @atheist 1/3 is 0. The expression 1/3 may be treated as a floating point operation if the result is assigned to a float (I think) in which case it takes on the precision of the result and there's no loss of precision to begin with.
  • 0
    According to C++ a loss of precision occurs only when you convert a wide number to a narrower number.
  • 0
    @atheist 0.0 is double, 0.0f is float. But a float should accept a double.
  • 1
    @LotsOfCaffeine

    With «std::make_pair<float, float>», it works because the <float, float> tells the compiler to expect a float, so it constructs a pair of floats.

    With «{0, 0}», the compiler first applies the pair template with int because it assumes that 0 is an int, and then it tries to return a pair of ints where a pair of floats is wanted, and that's where it finds it's appropriate to pester me about data loss.

    What bugs me is that the compiler obviously has the intelligence to infer from the function's signature that it has to construct a pair, but it's apparently too stupid to infer that the arguments of that pair are floats and to interpret those literals as floats. Especially, if that literal is 0. 0 is 0 always, however you cast it. Always 0x00...00!
  • 0
    @acz0903 I wonder if it doesnt like int(0) because the compiler doesn't want to make the assumption that int(0) == float(0.0f) in memory.
  • 2
    @acz0903 well I personally prefer the make_pair (and make_optional) all the time, so I never ran into this issue.

    But it does make sense, a literal 0 is an integer and the constructed pair is one of two ints.

    What bugs me more is that 0f is not a valid float, but 0.f is
  • 0
    @LotsOfCaffeine Oh, yeah! There is no acceptable reason why 0f is not a valid float.
  • 0
    @Demolishun 0 is always All-0 in memory. That was precisely my point. I expect the compiler to be smart enough to consider that.
Add Comment