
template <class T> T pi();
I have a fixed-point class. What actually happens when I call pi<fixed>() ? Presumably the implementation just does "return 3.1415...", so fixed::fixed(double) gets called. Yes my fixed class has a constructor that takes a double, and if I'm really lucky it may do the conversion at compile time - but more likely it will happen at run time. I would get the same code if you just declared "const double pi = 3.1415" (or #defined it).
My 64-bit fixed point type can store more digits of PI than a 64-bit floating point value. But I'm not aware of any way of filling those extra digits [ignoring the existence of long double]. Similarly if I had an arbitrary precision (i.e. variable length) type, how would it be constructed from the 100-digit constants that you mention without support from the language (or maybe macros)?
(As for the actual constants, the only ones I find myself using are pi and the approximate radius of the earth.)
Currently with Boost.Math if you call: pi<my_UDT>() then internally it does a lexical_cast from a string containing ~100 decimal digits to my_UDT. The resulting value is cached for performance reasons, but of course that's not thread safe, although it could be made so (still on the TODO list though). So unless my_UDT supports an unfeasably large number of digits, you should get pi to the full precision of your type. We currently use this with both NTL::RR and mpfr_class (2 arbitrary precision types), and it works very well. Obviously there are float/double/long double specialisations that just return the numeric constant directly (with appropriate suffix). And finally don't forget that you could add user-defined full specialisations of the templates for my_UDT if my_UDT provides it's own interfaces to various constants. John.