Re: Preprocessor
 
"buchtak@gmail.com" <buchtak@gmail.com> writes:
Hi,
is there a way to test if a variable is defined by a preprocessor
directive? Suppose, for example, I want to simplify this code by using
two macros:
Timer t1;
t1.start();
... // some action
t1.stop();
std::cout << "..." << endl;
#define TIMER_START(x) // defines timer tx and starts timing
#define TIMER_STOP(x) // stops timer tx and prints out the elapsed
time
However, the problem arises when I try to call TIMER_START(1) twice in
the same block since there's redefinition of t1. Is there a way to
extend the TIMER_START(x) macro such that it would first test if the
timer tx exists to avoid compiler errors?
It would be better if you defined a scoping couple of macros.
Assume you want expanded code such as:
   {
      Timer tXYZ;
      try{
         tXYZ.start();
         [BODY]
         tXYZ.stop();
       }catch(...){
         tXYZ.stop();
         throw;
       }
    }
Then it wouldn't matter if you used the same name in an embedded version:
   {
      Timer tXYZ;
      try{
         tXYZ.start();
        {
           Timer tXYZ;
           try{
              tXYZ.start();
              [BODY]
              tXYZ.stop();
            }catch(...){
              tXYZ.stop();
              throw;
            }
         }
         tXYZ.stop();
       }catch(...){
         tXYZ.stop();
         throw;
       }
    }
you would still have two different timers, and the references to each
are well scoped, lexically.
#define WITH_TIMER_BEGIN(TIMEOUT) \
   do{ \
      Timer CURRENT_TIMER; \
      try{ \
         CURRENT_TIMER.start(TIMEOUT); \
         { \
           int CURRENT_TIMER=0; /* hides the real timer */
#define END_WITH_TIMER \
         } \
         CURRENT_TIMER.stop(); \
       }catch(...){ \
         CURRENT_TIMER.stop(); \
         throw; \
       } \
    }while(0)
and write:
    WITH_TIMER_BEGIN(Minute(3)){
        do_something_slow();
    }END_WITH_TIMER;
    WITH_TIMER_BEGIN(Minute(3)){
        do_something_slow();
        WITH_TIMER_BEGIN(Second(15)){
          do_something_not_too_slow();
        }END_WITH_TIMER;
        do_something_slow();
    }END_WITH_TIMER;
(There's also a way to play tricks with for and if to avoid having to
define a END_XYZ macro, see for example boost::foreach, but it's
rather tricky and not always feasible.)
-- 
__Pascal Bourguignon__