Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Preprocessor

Reply
Thread Tools

Preprocessor

 
 
buchtak@gmail.com
Guest
Posts: n/a
 
      07-31-2009
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?
 
Reply With Quote
 
 
 
 
Pascal J. Bourguignon
Guest
Posts: n/a
 
      07-31-2009
"(E-Mail Removed)" <(E-Mail Removed)> 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__
 
Reply With Quote
 
 
 
 
buchtak@gmail.com
Guest
Posts: n/a
 
      07-31-2009
Thx Pascal. I guess that determining whether particular non-
preprocessor variable exists in the scope, which would elegantly solve
the problem, is impossible via the preprocessor. The problem with your
solution is, that the timer couldn't be stopped in an if-block for
example. I don't know about boost::foreach, but using it in this
particular case seems to undermine the basic reason of using macros,
which is to simplify things. But thx anyway for ideas.
 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      08-01-2009
On Jul 31, 2:07 pm, (E-Mail Removed) (Pascal J. Bourguignon)
wrote:
> "(E-Mail Removed)" <(E-Mail Removed)> writes:


> > 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;


Putting mismatched braces in a macro is a nice trick to render
the code unreadable. There are very few cases where it is
justified (although admittedly, this may be one). Why not just
use a class, which reads the timer in the constructor and the
destructor? (Presumably, you'll also want to capture the
results somewhere, so the constructor needs a reference to
that.)

Having said that... All his macro gains him is one line, that
which declares the variable. IMHO, it's not worth it.

--
James Kanze (GABI Software) email:(E-Mail Removed)
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
 
Reply With Quote
 
Pascal J. Bourguignon
Guest
Posts: n/a
 
      08-03-2009
James Kanze <(E-Mail Removed)> writes:

> On Jul 31, 2:07 pm, (E-Mail Removed) (Pascal J. Bourguignon)
> wrote:
>> 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;

>
> Putting mismatched braces in a macro is a nice trick to render
> the code unreadable. There are very few cases where it is
> justified (although admittedly, this may be one). Why not just
> use a class, which reads the timer in the constructor and the
> destructor? (Presumably, you'll also want to capture the
> results somewhere, so the constructor needs a reference to
> that.)
>
> Having said that... All his macro gains him is one line, that
> which declares the variable. IMHO, it's not worth it.


Yes, I must admit that if there is only this functionality to abstract
away, such a couple of macro may be overdoing it. However, the
technique is still useful in more complex cases.


Notice that we are not after the line count, but after a syntactic
abstraction: we want to hide what is inside the macro.


Sometimes functional abstraction or data abstraction (objects) is
enough to hide the details, but unfortunately, there are occurences
where functional abstraction is not enough (for example, when you have
to remind using try/catch around every occurences of your functional
abstraction), and were a good macro makes miracle in readability and
bug avoidance.



But given the need the OP expressed later, to stop the timer inside
the body, in his case indeed a RAII pattern would be better.

try{
Timer timer(Minute(3));
doSomethingSlow();
if(needMoreTime){
timer.stop();
doSomethingEvenSlower();
}
}catch(Timeout& e){
notEnoughTimeToCompleteTheTask(e);
}

--
__Pascal Bourguignon__
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Compiler error occurred when try to use a flexible template expression in preprocessor definesCompiler error occurred when try to use a flexible template expression in preprocessor defines snnn C++ 6 03-14-2005 04:09 PM
C# Preprocessor =?Utf-8?B?SSBhbSBTYW0=?= ASP .Net 2 03-13-2005 02:47 PM
preprocessor, token concatenation, no valid preprocessor token Cronus C++ 1 07-14-2004 11:10 PM
VHDL Preprocessor The Weiss Family VHDL 2 07-14-2004 05:51 AM
Preprocessor conditional compilation variable not being saved Chris P ASP .Net 0 10-28-2003 08:48 PM



Advertisments