
Boost : 
Subject: Re: [boost] [Math.Constants] Help needed with the preprocessor
From: Lorenzo Caminiti (lorcaminiti_at_[hidden])
Date: 20111216 18:33:18
On Fri, Dec 16, 2011 at 3:26 PM, Jeffrey Lee Hellrung, Jr.
<jeffrey.hellrung_at_[hidden]> wrote:
> On Fri, Dec 16, 2011 at 10:23 AM, John Maddock <boost.regex_at_[hidden]>wrote:
>
>> Folks we have a problem: rather late in the day I've discovered that our
>> Math.Constants code doesn't compile on anything except VC++, and the
>> problem is preprocessor token pasting. So I'm hoping we have some experts
>> around here that can help!
>>
>> The issue is we currently construct the constants from a macro invocation
>> such as:
>>
>> BOOST_DEFINE_MATH_CONSTANT(**half, 5.**000000000000000000000000000000**000000,
>> 000000000000000000000000000000**000000000000000000000000000000**00000000000000,
>> 01);
>>
>> But the "01" part (the exponent) isn't a valid pptoken, so trying to
>> tokenpaste it fails on GCC (compiler error).
>>
>> Does anyone know if there's a way to overcome this?
>>
>
> Maybe include the "e" in that 4th argument? E.g., "e01". If you actually
> need to recover the "01" without the e, I'm pretty sure you can do
> something like
#define BOOST_DEFINE_MATH_CONSTANT(name, x, y, exp)
Yes, as indicated by Jeff, you can have your users to always prefix
exp with e (I looked at your macro and you always CAT(e, exp)). BTW,
can x ever start with a symbol ()?
BOOST_DEFINE_MATH_CONSTANT(half, 5.000000000000000000000000000000000000,
00000000000000000000000000000000000000000000000000000000000000000000000000,
e01); // OK
Otherwise it seems you can use PP_SEQ_CAT:
#include <boost/preprocessor/seq/cat.hpp>
#include <boost/preprocessor/stringize.hpp>
#define BOOST_DEFINE_MATH_CONSTANT(name, x, y, exp)\
template <class T> inline T name(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE(T))\
{\
static const T result = ::boost::lexical_cast<T>(BOOST_PP_STRINGIZE( \
BOOST_PP_SEQ_CAT( (x) (y) (e) (exp) )));\
return result;\
}\
template <> inline float
name<float>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(float))\
{ return BOOST_PP_SEQ_CAT( (x) (e) (exp) (F)); }\
template <> inline double
name<double>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(double))\
{ return BOOST_PP_SEQ_CAT( (x) (e) (exp) ); }\
template <> inline long double name<long
double>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(long double))\
{ return BOOST_PP_SEQ_CAT( (x) (e) (exp) (L) ); }
BOOST_DEFINE_MATH_CONSTANT(half, 5.000000000000000000000000000000000000,
00000000000000000000000000000000000000000000000000000000000000000000000000,
01); // ok but no e
This seems to work even with x = 1.0:
BOOST_PP_SEQ_CAT( (1.0) (123) (e) (10) ) // 1.0123e 10
But I'm not sure how this actually works inside Boost.Preprocessor...
HTH,
Lorenzo
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk