
Jeff Garland wrote:
Robert Ramey wrote:
Besides all that, eliminating NaNs from the serialization problem space is really impossible. Even if we struck them from the C++ language, someone would effectively recreate them using optional<float> or the equivalent.
Actually that would be an improvement in that the "union" would be explicit, visible and modifiable. In fact I could see the utility right now of a "safe_float" which would look something like
#ifndef NDEBUG BOOST_STRONG_TYPE(float, safe_float) safe_float operator/(safe_float x, safe_float y){ if(y < epsilon) // machine dependent epsilon throw overflow_exception return x / y; } ... #else #define safe_float float #endif
Robert -- I believe that thinking of floats as a "union" is the wrong analogy. In date_time there's -inf, +inf, and not_a_date_time. There's no union internally used to represent them. These values are extremely useful for writing real programs and have obvious mappings into the real world -- trust me, I've used them in a real world scheduling system. In fact, since date_time uses integers internally the special values are simply implemented as a reserved number value. nadt is essentially max_int, +inf == max_int - 1 and -inf == min_int. I believe you can think if floating point number special values in the same way -- although the internal implementation may be in hardware ultimately, the special values are really just certain bit patterns that are defined to represent these logical states.
In my view, your usage above is logically and functionally equivalent to something like class dt { enum { a, b, c } state; int value; }; Since value can be of different "types" it pretty equivalent to a C union. The fact that its not an C union is really just an implementation detail. I'm using the word union as a short hand for all these types of constructions. Used in this way the current float behavior is a union. Perhaps a better word would have been "multi-type" of which the C union would be an example.
A program which produces an undefined result is "broke"
I guess all of 'math' is broken then too? The only way to deal with singularities in math is to effectively 'bail-out' -- say, well don't do that.
That's how math works - I think C++ should work the same way.
If you try to do a divide by zero in a program it's the same -- some external logic needs to deal with that case. The fact that the floating point type tells you that you divided by zero by giving and infinite result is actually a well defined and correct interface.
Not in any portable way. Page 132 of my reference "The C++ Programming Language" by Stroustrup says "the effect of dividing by zero is undefined but doing so usually causes abrupt termination of the program." In fact, when running under the debugger, my VC++ IDE permits me to trap or ignore and continue when this occurs. Intel chips have a floating point unit which throws a hardware exception when this occurs. C++ is designed to not handle these cases. I don't know what other processors do - I suppose it varies. In any case - its undefined.
BTW - as far as the serialization system is concerned ...
I think the whole thing that started this thread is to fix the standard so that these values can be correctly and portably serialized.
I only mentioned it because someone expressed the notion that this is only a problem for serialization. I don't think its a serialization problem. I think its a problem which manifests itself when one tries to implement serialization - among other places.
But it seems that we are now distracted from that purpose. In my view, it's terribly flawed when a language like JavaScript can correctly serialize NaNs and Infinites and C++ can't.
Well, of course that's true if one believes that NaNs and +/-Inf, +/-0 etc have legitimate uses. But I'm not convinced.
We need to help Paul fix the standard, it just isn't that difficult a problem...
I'll bet that given the variety of handling things now - it will be a lot more difficult than it first appears. Robert Ramey