Boost logo

Boost :

From: Ed Brey (edbrey_at_[hidden])
Date: 2001-10-25 08:20:54


From: "Greg Colvin" <gcolvin_at_[hidden]>

> namespace constants {
>
> // an example constant, suitable for everyday abuse
> static const struct pi_ {
> pi_(){}
> inline operator long double() const {
> return 3.141592653589793238462643383279502884197L;
> }
> } pi;
>
> // a generic constant generator
> template<typename T, typename V> inline T constant(const V& v) {
> return static_cast<T>(v);
> }
>
> // example specializations of the constant generator
> template<> inline float constant(const pi_&) {
> return 3.141593F;
> }
> template<> inline double constant(const pi_&) {
> return 3.14159265358979;
> }
> template<> inline long double constant(const pi_&) {
> return 3.141592653589793238L;
> }
> }

Very interesting. It shows promise of a single interface for specific and generic use.

But alas, I can't make it work. The compiler complains about multiple functions named "constant" that differ only by return type.

There is also the same constructor issue that Michael's pattern has. Here's the summary:
- With the constructor, VC generates code for each constant, whether referenced or not.
- Without the constructor, g++ complains that "pi" is uninitialized.

There are a few possible solutions, however. If VC is the only compiler that becomes inefficient in the face of the constructor, conditionally compile it away for VC. If other compilers prefer to not see the constructor, change the definition of "pi" to

double const pi_ pi = {};

However, the {} notation breaks VC, so it would have to conditionally compiled out in that case. I don't know what the notation does to the efficiency on other compilers.

Of course, there is still the option of simply providing a bunch of simple double constants for non-generic uses, and then a separate simple function interface for generic uses, like this

template<typename T>
struct constants {}

template<>
struct constants<double> {
    static double pi() {return 3.14;}
}

Given the pitfalls with the fancy template magic, I'm starting lean towards the simpler approach. This would cover the common cases quite well. It doesn't provide for fanciness such as hand-crafted binary constants in the initial implementation, but I question the value of such items that are opaque to the compiler anyway (e.g. they are not subject to constant folding).

If the interface is kept restrained, the implementation for the non-generic constants could be tweaked at any time. Of course, we may find it more valuable to allow taking pointers and references to constants than to allow tweaking the implementation. The former doesn't seem to be valuable very often, but then again, neither does the latter.


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