Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Preprocessor

0 views
Skip to first unread message

buc...@gmail.com

unread,
Jul 31, 2009, 7:53:20 AM7/31/09
to
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?

Pascal J. Bourguignon

unread,
Jul 31, 2009, 8:07:23 AM7/31/09
to
"buc...@gmail.com" <buc...@gmail.com> writes:

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__

buc...@gmail.com

unread,
Jul 31, 2009, 10:45:44 AM7/31/09
to
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.

James Kanze

unread,
Aug 1, 2009, 4:35:55 AM8/1/09
to
On Jul 31, 2:07 pm, p...@informatimago.com (Pascal J. Bourguignon)
wrote:
> "buch...@gmail.com" <buch...@gmail.com> writes:

> [BODY]

> and write:

> WITH_TIMER_BEGIN(Minute(3)){
> 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:james...@gmail.com
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

Pascal J. Bourguignon

unread,
Aug 3, 2009, 5:43:00 AM8/3/09
to
James Kanze <james...@gmail.com> writes:

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__

0 new messages