This has happened to me several times. Especially in combination with the fact that C++ does not guarantee floating point operations happen the same every time... Argh. So it is unwise to do things like
bool operator()(Foo const& a, Foo const& b) const {
return a.some_float_func() < b.some_float_func();
}
if some_float_func does floating point operations rather than just returning a stored value.
For example, a function might be inlined at some call sites and not inlined at others. Inlined versions might carry 80 bits through the result, but non-inlined version are truncated to 64. So in:
I'm not sure how the example could make the assertion fail; I think that the point is that if 3.3 is treated as a long double by the compiler, then the result of x*3.3 will be a long double, which is more precise than the double returned by foo; but, regardless of how bar1 and bar2 are compiled, they both make a call to foo() which returns a double. Is it the case then that the behavior depends on how foo is compiled? I don't see how else the 80-bit result could propagate to the test for equality.
returning a double can be optimized into returning an 80-bit result in a register. If this happens with bar1 but not bar2, then you get different results.
There are situations where the order of evaluation is not guaranteed. The big one that I've seen is evaluation of expressions as arguments in a function call, but there are others. It is easy to create floating point expressions where because of rounding, the results will differ depending on the order of evaluation. I'm not aware of situations where the order of operation differs from one execution to the next. However, I could see a compiler generating different code for the same expression when it appears in more than one place in the source code because of optimization.