$include_dir="/home/hyper-archives/boost-users/include"; include("$include_dir/msg-header.inc") ?>
From: Tobias Schwinger (tschwinger_at_[hidden])
Date: 2007-06-19 06:06:03
Server Levent Yilmaz wrote:
> Take a look at this:
> 
> #define SPECIAL
> #define IS_SPECIAL(x) BOOST_PP_IS_EMPTY(BOOST_PP_EMPTY() x)
> 
> #define MACRO(i,z,array) IS_SPECIAL( BOOST_PP_ARRAY_ELEM(i, array) )
> #define ENUM( n, tuple ) BOOST_PP_ENUM( n, MACRO, (n, tuple) )
> 
> ENUM( 3, ( arg1,        , arg3) ) //1
> ENUM( 3, ( arg1, SPECIAL, arg3) ) //2
> 
> 
> In this context, can we safely say that 2 complies with standards more 
> than 1?
No, because the argument to IS_SPECIAL (within MACRO) might expand to 
emptiness, anyway.
     #define MACRO(z,i,array) BOOST_PP_IS_EMPTY(BOOST_PP_EMPTY() \
         BOOST_PP_ARRAY_ELEM(i,array) )
Is better, though still not correct: SPECIAL within 'array' expands to 
nothing before 'array' is passed to PP_ARRAY_ELEM. Now the problem 
occurs within the PP library.
Now we'd have to know the exact number of expansions to defer the 
expansion of SPECIAL so many times that the final expansion to emptiness 
happens just within PP_IS_EMPTY:
     #define E()      // Empty
     #define X(x) x   // eXpand
     // demonstrate expansion gets deferred
            E E E E()()()()     // E E E ()()()
     X(     E E E E()()()()  )  // E E ()
     X(X(   E E E E()()()() ))  // E ()
     X(X(X( E E E E()()()() ))) //
     #define SPECIAL E E E E E E E E E E E E E E E E E E E E E \
         ()()()()()()()()()()()()()()()()()()()()()
     //#define MACRO(z,i,array) \
     //    BOOST_PP_IS_EMPTY( BOOST_PP_ARRAY_ELEM(i, array) )
     #define MACRO(z,i,array) BOOST_PP_ARRAY_ELEM(i, array)
     #define ENUM( n, tuple ) BOOST_PP_ENUM( n, MACRO, (n, tuple) )
     ENUM(3, (arg1, SPECIAL, arg3)) // arg1 , E () , arg3
This code works as expected with the GNU preprocessor. You can't rely on 
the number of expansions to be the same for another PP, since Boost.PP 
might have to correct PP misbehavior, taking a different "control path", 
for things to work at all.
It's quite easy to cross the line messing with emptiness
     #define FOO(x) _ ## x
     #define BAR(x) FOO(x)
     FOO(BOOST_PP_EMPTY()) // OK, expands to _BOOST_PP_EMPTY()
     BAR(BOOST_PP_EMPTY()) // -undefined behavior-
so ideally one finds a way not to have to mess with it at all, e.g:
     #define SAFE(optional) optional()
     #define STILL_SAFE(optional) SAFE(optional)
     SAFE(BOOST_PP_EMPTY) // expands to nothing
     SAFE(BOOST_PP_IDENTITY(xyz)) // xyz
     STILL_SAFE(BOOST_PP_EMPTY) // expands to nothing
Regards,
Tobias