This is the same issue as in this question except that one is about double instead of float and gets to the conversion through a call to stod instead of through a stream operator. The language standard allows conversion of subnormal values to underflow.
Per C++ 2020 draft N4849 29.7.4.2.2, >> for a float uses num_get. Per 28.4.2.1.2, the conversion is performed (Stage 3) by the rules for strtof from the C library. Per C 2018 7.22.1.3 paragraph 10, the result may underflow as described in 7.12.1. 7.12.1 paragraph 6 tells us “The result underflows if the magnitude of the mathematical result is so small that the mathematical result cannot be represented, without extraordinary roundoff error, in an object of the specified type.”
“Extraordinary roundoff error” is not defined in any of the standards (C++, C, or IEEE-754). However, ordinary rounding error is that which occurs for numbers in the normal range. It is limited by the precision of the floating-point significand: In the normal range, rounding to the nearest representable value never has an error greater than half the distance between representable numbers. With 24-bit significands for float, the relative error is at most one part in 2−24. Below the normal range, the full significand is not available; leading zeros in the significand are used to extend the range of the floating-point format. In this interval, the errors from rounding may exceed one part in 2−24. (In the worst case, it can be 100%, as 2−149 is rounded to 0.) Thus, the error may exceed the ordinary rounding error and can be called extraordinary roundoff error.
Therefore, a C++ implementation is allowed (but not required) by the C++ standard to underflow for subnormal values even though non-zero result could be delivered.
Which implementation is correct here?
They all conform to the C++ standard in this regard, as the standard allows but does not require underflow in this situation.
s >> f;->if (s >> f) std::cout << "GOOD\n"; else std::cerr << "BOOM\n";. And, we see when 0 is printed.float?operator>>for float is defined in terms ofnum_get; which in turn is defined in terms of the C functionstrtof. The C standard has this to say (7.22.1.3/10): "If the result underflows (7.12.1), the functions return a value whose magnitude is no greater than the smallest normalized positive number in the return type; whethererrnoacquires the valueERANGEis implementation-defined." Emphasis mine. I suspect you are observing this implementation-defined behavior propagating through layers. You could probably test this by callingstrtofdirectly.strtofhere. Match yours for clang and MSVC, but not for GCC (whereoperator>>appears to ignore the underflow).