From: Chris Fairles (chris.fairles_at_[hidden])
Date: 2007-09-15 11:19:51


I was browsing through the math-toolkit and noticed a neat way of
type-a-fying mathematical constants. I had been doing something
similar but with static constants in a struct which required
definitions to be linked into each translation unit.

Here's a simplified version:

#define DEFINE_MATH_CONSTANT(name, x, exp)\
   template <class T> inline T name()
   {
      static const T result =
::boost::lexical_cast<T>(STRINGIZE(JOIN(x, JOIN(e, exp))));
      return result;
   }
   template <> inline float name<float>()
   { return JOIN(JOIN(x, JOIN(e, exp)), F); }
   template <> inline double name<double>()
   { return JOIN(x, JOIN(e, exp)); }
   template <> inline long double name<long double>()
   { return JOIN(JOIN(x, JOIN(e, exp)), L); }

But then I went to do something like:

DEFINE_MATH_CONSTANT(h, 6.62606896, -34)

And got:
error: pasting "e" and "-" does not give a valid preprocessing token
error: exponent has no digits
error: invalid suffix "F" on integer constant
...

etc. etc.

So I modified it to this:

#define DEFINE_MATH_CONSTANT(name, x, sign, exp)\
   template <class T> inline T name()\
   {\
      static const T result =
::boost::lexical_cast<T>(STRINGIZE(JOIN(x, JOIN(JOIN(0e, sign),
exp))));\
      return result;\
   }\
   template <> inline float name<float>()\
   { return JOIN(JOIN(x, JOIN(JOIN(0e, sign), exp)), F); }\
   template <> inline double name<double>()\
   { return JOIN(x, JOIN(JOIN(0e, sign), exp)); }\
   template <> inline long double name<long double>()\
   { return JOIN(JOIN(x, JOIN(JOIN(0e, sign), exp)), L); }

and now:
DEFINE_MATH_CONSTANT(h, 6.62606896, -, 34)

works as expected.

If its not too complicated, can someone walk through the substitution
process that the preprocessor is performing and highlight why pasting
'e' and '-' gives rise to an error where '0e' and '-' does not? I took
a brief look at the standard and I'm guiessing it has to do with ##
resulting in an invalid preprocessing token (with "e-" being invalid
where "0e-" isn't??).

The author of math-toolkit might want to implement such a solution as
well if negative exponents could potentially be used in defining math
constants.

Cheers,
Chris