Boost logo

Boost :

From: Ed Brey (brey_at_[hidden])
Date: 2001-04-25 15:38:18

From: "Mark Rodgers" <mark.rodgers_at_[hidden]>
> > Usage would typically be:
> > typedef boost::math::constants<float> c;
> > a = c::pi() * r * r;
> As an aside, wouldn't it be nice if we could have template namespaces?
> you could write
> using boost::math::constants<float>::pi;
> a = pi() * r * r;
> and we also be able to reopen the boost::math::constants<T> namespace
> add more members in other header files if desired.
> Anyway, back to the real world.

The real world can be surprising. At least it surprised me. The
following actually compiled (and hopefully is legal C++):

float (&pi)() = boost::math::constants<float>::pi;
a = pi() * r * r;

So in a way, you have template namespaces; only they're called

> I've been out of things for a while. Was the following option
> and if so what is wrong with it?
> #include <iostream>
> namespace boost { namespace math { namespace constants {
> template<typename T> T pi();
> template<> float pi<float>() {return 3.14F;}
> template<> double pi<double>() {return 3.14;}
> template<> long double pi<long double>() {return 3.14L;}
> } } }
> using boost::math::constants::pi;
> a = pi<float>() * r * r;

I addressed this issue briefly once before. The problems with this
usage pattern are scalability and design-time garbage collection. When
you use a lot of constants, it means having to write a lot of extra code
in the form of using declarations, and it can be difficult to determine
when you can get rid of a using declaration during program maintenance.
There don't seem to be too many math constants, and so its a so-so
problem with this library; however, I expect physical constant libraries
to have more constants that one may use, which does start posing a more
real problem.

However, the interface you propose also allows this usage:
  namespace c = boost::math::constants;
  a = c::pi<float>() * r * r;

Which gets around the scalability issue. And of course, the user can
always define a reference for any constant that he didn't want to have
to qualify with the renamed namespace and the template argument. The
one thing you can't do in this approach is get access to a bunch of
constants of the same type, with a single declaration, e.g. (using the
struct-based interface):

template<typename T>
T compute(T x, T y) {
    typedef boost::math::constants<T> c;
    T e = a * c::pi();
    T f = y * c::e();
    if (e > 0) f = -1;
    return e * f * c::sqrt2();

This functionality puts the structure-based approach over the top, for

Boost list run by bdawes at, gregod at, cpdaniel at, john at