[math-toolkit] DEFINE_BOOST_MATH_CONSTANT errors with -'ve exponents

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

Chris Fairles wrote:
<snip>
Thankfully no negative exponents at present: interestingly VC8 handles negative exponents perfectly well with the existing code, but not gcc. If I'm reading 16.3.3 of the std correctly then it's undefined behaviour if the result of token pasting with ## is not itself a valid token, and I don't think it can if there is a "-" in it anywhere at all :-( Perhaps someone could clarify this? If I reorder the BOOST_JOIN's a bit so that adding the exponent is the last step, then the gcc preprocessor stops complaining, but... if the exponent is -34 then it gets converted to "- 34" in the final output: that's right gcc actually splits it apart and inserts a few random spaces, Arhhh !!! Based on this I'm going to conclude that your solution worked "by accident", but if there is a truely portable solution that's fully supportable by the std, then I'm all ears ! :-) BTW I also tried the obvious: #define BOOST_DEFINE_MATH_CONSTANT(val, exp) val##exp##F But this too separated the exponent from it's sign in gcc. I also can't help wondering if this might pose problems when the value is negative as well :-( Regards, John.
participants (2)
-
Chris Fairles
-
John Maddock