Boost logo

Boost :

From: Daniel Frey (daniel.frey_at_[hidden])
Date: 2004-03-01 10:45:29


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_at_[hidden], web: http://www.aixigo.de

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk