Lets look at the following code:
template<double D> int f(){
static int i=0;
++i;
return i;
}
...
#define D1=...
#define D2=...
cout << f<D1>()<<endl; // returns 1
cout << f<D1-D2+D2>()<<endl; // may return 1 or 2, depending on many things
See, D1-D2+D2
may be equal to D1
for some values but not equal for others.
More importantly - they may be equal or not depending on the rounding settings
And finally, they may be equal or not depending on compilers / architectures / many other things.
The point is, floating point operations are not well enough defined for template use (they are well defined, but there is a lot of possible variance depending on various options)