1

Recently I came across the fact that floating point types and integer types are treated quite differently in C++.

Example 1 from: Why are floating point types invalid template parameter types for template functions?

template <double x>
double func() {
  return x;
}

is invalid, whereas with int it is valid.

Example 2 from: How to initialize private static members in C++?

class foo
{
    private:
        static float const i = 42;
};

is invalid, whereas with int it is valid.


In the first linked question there is a Versuch of an answer. It states that types like float and double don't have a defined implementation in C++. But, the same can be said about a lot of other places in C++, and in particular about integer types (1-complement vs. 2-complement).

Thus, is there a deeper reason why floats and integers are treated that differently?

tommsch
  • 582
  • 4
  • 19

1 Answers1

2

The underlying issue is that 1 and 2 always have different values, regardless of how those values are represented. 3.111111111115 and 3.111111111114 might or might not have different values on different systems, depending on how the values are represented, and might have different runtime values on the same system, depending on how the rounding mode is set. The former is the fundamental issue for writing portable code: on one system, x<3.111111111115> and x<3.111111111114> could be two different types and on another the same type. The latter isn't an issue for the type system, but would set a trap for users, because equality tests on those values could produce different results from type comparisons on their template instantiations.

One practical consequence of this type uncertainty is that

void f(x<3.111111111115>) {} 
void f(x<3.111111111114>) {}

could be legal on one platform, but illegal on another.

Pete Becker
  • 74,985
  • 8
  • 76
  • 165
  • While I was struggling with the fact that the compiler should be able to justice whether two floating points are equal or not (if not at least by comparing their bit patterns), I completely overlooked that I've to tell the compiler the floating point values in decimal notation somehow. :-) (Actually, I could use the hex-digit notation instead but that's probably a lame excuse - not too mention that's hard to read for humans.) – Scheff's Cat Apr 21 '21 at 12:54
  • @Scheff -- hex-digit notation doesn't solve the underlying problem. Different systems can have different sizes for the same type, so hex digits won't necessarily produce the same value. And even if the sizes are the same, the underlying representation can be different, so you'd be talking about two different floating-point values. Of course, if the actual value doesn't matter, you can just use those hex digits as an integer type... – Pete Becker Apr 21 '21 at 13:04
  • Isn´t the format of the floating point numbers determined at compile time? – tommsch Apr 21 '21 at 14:38
  • @tommsch -- yes. But different systems don't necessarily use the same format. The hex representation isn't necessarily the same on different systems. – Pete Becker Apr 21 '21 at 15:05
  • @PeteBecker But then the argument is not architectural one ("it does not work") but rather a: "people could use it wrongly, so we forbid id". – tommsch Apr 21 '21 at 15:19
  • @tommsch -- the argument is that the standard can't specify consistent semantics across systems. As I said, `x<3.111111111115>` and `x<3.111111111114>` can be two different types on one system and the same type on another. – Pete Becker Apr 21 '21 at 15:51
  • @PeteBecker But I dont understand why this is a problem. On a system where these two numbers are the same, the templates would be the same, and on a system where these two numbers are not the same, the templates would not be the same. Thats just a portability problem. The same problem already exists when computations are done using floating point numbers, and still, floating point numbers are allowed to be used in C++. – tommsch Apr 21 '21 at 21:13
  • @tommsch — I don’t know how to write robust code when `void f(x<3.111111111115>) {} void f(x<3.111111111114>) {}` is legal on one platform and illegal in another. – Pete Becker Apr 22 '21 at 00:55
  • @PeteBecker Now I got it. Thanks for beeing so patient.I added your last argument to your answer (Redo it if you think it does not fit there). – tommsch Apr 22 '21 at 07:10
  • @tommsch -- I modified your change just a bit. – Pete Becker Apr 22 '21 at 12:37