
Thorsten Ottosen wrote:
With no offense intended, but that's a very simple version which doesn't work in many situations. The problems of your solution are:
- Doesn't work well for UDTs (try std::complex, some conversions are ambiguous then)
What rule of the language prohibit this conversion? My vc71 compiler can do it, como and g++ cannot.
It depends on what exactly you tried. The basic problem is, that T(pi) tries to call a ctor for T, but std::complex has several candidates available. std::complex<double>(std::complex<double>) and std::complex<double>(double) might conflict here, except you don't provide conversion to std::complex<double> for your constants. But you cannot assume this for other UDT. What happens if a UDT has ctors taking float, double and long-double? You can't use your constants any more, even a new conversion to the type directly won't help. This is (one of the reasons) why I provide .get<T>() instead of T(pi), static_cast<T>(pi) or pi.operator T(). While the alternatives all look very promising, they have some severe problem: You can't influence what they actually do. This becomes important when you think of unit-libraries, see the examples I put into the files section.
- Doesn't scale for new types (you need to know all of them in the single header that defines the constant)
You could add the overloads with eg a macro in your own header. What should hinder this?
Macro's are ugly. OK, not a very compelling reason :-) Still I would feel somewhat limited when I have to provide all of this stuff through macros. Also, I can't add values only for selected constants, once I start using macros, I have to prove them for all constants. Maybe this can - again - be fixed by some preprocessor magic, but it's well possible without the preprocessor at all.
- Doesn't work for more complex expressions (pi*pi*t instead of T(pi)*pi*t)
true, but what precision does pi*pi have? IMO, it's good to have that information in the code.
I disagree. You already found out that a certain convenience is necessary. You don't write T(pi)*t (t being of type T), just pi*t. This automatically selects the type/precision for pi in this expression. Why shouldn't this scale to pi*pi*t? Or sqrt(pi)*t. The first non-constant should select the type, no matter how the constants are used before.
- Doesn't solve the naming dilemma (how to spell the constant "pi*pi"?)
is pi_square that bad?
Yes. It clutters my brain with more names. pi*pi is a general principle I already know. Also, 1/srqt(e) is easy to remember, but what would the name be when using you scheme? It also makes the code less readable IMHO.
- Doesn't work well with unit libraries AFAICS (again not scaling well)
how?
Because they need to return a different type than what they are asked for. And casting them is not an option, as you need to know the unit and spell it out explicitly. Look at the ideal-gas-law-examples. You want to use the constant without spelling out it's type over and over again, won't you?
Is there any documentation?
Well, that's the weak point currently. I hope that I can come up with some docs in the next weeks. Currently, all I can offer is that I answer questions. Sorry.
From your example file:
std::cout << pi.get< float >() << std::endl;
which is float( pi ) spelt more elaborate.
As mentioned, this is a very important thing to note that .get<T> is free to return something else than T!
std::cout << pi + pi - pi * pi / pi + d << std::endl;
how often does such an expression occur in practice? Afterall, a single pi would do.
Look at some physical laws. There are often combinations of several constants and if possible, I don't want to limit the programmer if there isn't a compelling reason to do so. People should be able to express their thoughts as direct as possible. They shouldn't be forced to care about the language more than neccessary.
std::cout << sqrt( sqrt( two + pi ) ) + d << std::endl;
will everything left of d be a constant? If so, what would the point be?
Basically, it's not a single constant. The constants are both casts to d's type, added and sent through sqrt two times. But you can - if you want to - make it a single, fast constant if you think it's worth the effort for your program. Regards, Daniel -- Daniel Frey aixigo AG - financial solutions & technology Schloß-Rahe-Straße 15, 52072 Aachen, Germany fon: +49 (0)241 936737-42, fax: +49 (0)241 936737-99 eMail: daniel.frey@aixigo.de, web: http://www.aixigo.de