C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Comment ecrire une macro qui "mangent" un argument de type "

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ (French)
View previous topic :: View next topic  
Author Message
mderie
Guest





PostPosted: Wed Apr 26, 2006 8:06 am    Post subject: Comment ecrire une macro qui "mangent" un argument de type " Reply with quote



En deux mots, j'ai un tout petit bout de code pour sortir des traces
via le port reseau (voici la seule fonction a utilisee Smile :

Fichier udplog.h :

#define LOGGER udplog
void udplog(char *message, ...)

LOGGER etant un simple alias pour ne pas specifier le type de
"transport" pour les logs. Or donc je voudrais arriver a cette
situation :

Fichier logger.h :

// Warning : there can be only one !

// Serial Logger
//#include ...

// UDP Logger
//#include "udplog.h"

// NOP Logger
#define LOGGER noplog
inline void noplog(char *message, ...) {}

//TODO: How ?
// Ultra Quiet Logger
//#define LOGGER(?)
//#define LOGGER0(msg)
//#define LOGGER1(msg,x)
//#define LOGGER2(msg,x, y)
//...

Mon probleme est donc comment ecrire une MACRO qui puisse
avoir une impacte nulle pour du code en "release" ! Bien sur le NOP
Logger
est deja assez leger... Mais bon il y a surement moyens de faire mieux
non ?

Bien a vous
Back to top
Aurelien Regat-Barrel
Guest





PostPosted: Wed Apr 26, 2006 8:06 am    Post subject: Re: Comment ecrire une macro qui "mangent" un argument de ty Reply with quote



mderie a écrit :

Quote:
Mon probleme est donc comment ecrire une MACRO qui puisse
avoir une impacte nulle pour du code en "release" ! Bien sur le NOP
Logger
est deja assez leger... Mais bon il y a surement moyens de faire mieux
non ?

C'est le nombre variable d'argument qui te pose problème si j'ai bien
compris. Y'a des compilos qui permettent de faire de telles macros, mais
c'est pas standard. Tu peux parenthéser l'appel à LOGGER:

#define LOGGER(x) printf x

LOGGER( ("hello %s", "world!" ) );

ou bricoler un truc à base de if(0) peut être...

#define LOGGER if ( 0 ) noplog

enfin, plutôt:

#define LOGGER if ( 1 ) {} else noplog

d'après mes souvenirs sur la bonne manière d'écrire des macros.

--
Aurélien Regat-Barrel
Back to top
Patrick 'Zener' Brunet
Guest





PostPosted: Wed Apr 26, 2006 8:06 am    Post subject: Re: Comment ecrire une macro qui "mangent" un argument de ty Reply with quote



Bonjour.

Je réponds à mderie <mderie (AT) gmail (DOT) com>
qui dans 1146037058.944748.240710 (AT) e56g2000cwe (DOT) googlegroups.com a écrit :
Quote:
En deux mots, j'ai un tout petit bout de code pour sortir des traces
via le port reseau (voici la seule fonction a utilisee Smile :

Fichier udplog.h :

#define LOGGER udplog
void udplog(char *message, ...)

LOGGER etant un simple alias pour ne pas specifier le type de
"transport" pour les logs.

J'ai eu le problème dans une telle application.
A priori les macros à liste variable ça n'existe pas, sauf effets de bords
bizarres.

J'ai donc procédé ainsi:

#define COMMA ,

LOGGER( "Une %s à %u euros", "astuce" COMMA 2);

Ca ne couvre qu'un niveau d'imbrication bien sûr.

Cordialement,

--
/***************************************\
* Patrick BRUNET
* E-mail: lien sur http://zener131.free.fr/ContactMe
\***************************************/
Back to top
kanze
Guest





PostPosted: Thu Apr 27, 2006 7:06 am    Post subject: Re: Comment ecrire une macro qui "mangent" un argument de ty Reply with quote

Aurelien Regat-Barrel wrote:
Quote:
mderie a écrit :

Mon probleme est donc comment ecrire une MACRO qui puisse
avoir une impacte nulle pour du code en "release" ! Bien sur
le NOP Logger est deja assez leger... Mais bon il y a
surement moyens de faire mieux non ?

C'est le nombre variable d'argument qui te pose problème si
j'ai bien compris. Y'a des compilos qui permettent de faire de
telles macros, mais c'est pas standard.

Ça dépend. Il faut d'abord savoir s'il fait du C ou du C++. Les
macros variadiques existent bien en C, voir __VA_ARGS__. Et en
C++, il n'y a aucun problème à écrire quelque chose du genre :

LOGGER( "x = " << x ) ;

avec :
#define LOGGER( msg ) log << msg
ou :
#define LOGGER( msg )

Quote:
Tu peux parenthéser l'appel à LOGGER:

#define LOGGER(x) printf x

LOGGER( ("hello %s", "world!" ) );

ou bricoler un truc à base de if(0) peut être...

#define LOGGER if ( 0 ) noplog

enfin, plutôt:

#define LOGGER if ( 1 ) {} else noplog

d'après mes souvenirs sur la bonne manière d'écrire des macros.

En effet, Loïc a proposé quelque chose de ce genre dernièrement.
On a soit :
#define LOGGER getlog( __FILE__, __LINE__ )
soit
#define LOGGER if ( true ) ; else dummy
(Note bien que dans ce cas-ci, même avec les logs désactivés
lors de la compilation, il faut bien que ton programme contient
un object dummy.)

Ici aussi, on écrit ensuite :
LOGGER << "x = " << x ;

(Au fond, je me démande si:
#define LOGGER false && dummy
ne serait pas mieux pour supprimer le log. Ça permettrait
d'introduire des logs dans un initialisateur dans un
constructeur, par exemple :
Toto::Toto(
int titi )
: myTiti( ((LOGGER << "titi = " << titi), titi) )
// ...
..)

--
James Kanze GABI Software
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
Back to top
Aurelien Regat-Barrel
Guest





PostPosted: Thu Apr 27, 2006 9:06 am    Post subject: Re: Comment ecrire une macro qui "mangent" un argument de ty Reply with quote

kanze a écrit :

Quote:
En effet, Loïc a proposé quelque chose de ce genre dernièrement.
On a soit :
#define LOGGER getlog( __FILE__, __LINE__ )
soit
#define LOGGER if ( true ) ; else dummy
(Note bien que dans ce cas-ci, même avec les logs désactivés
lors de la compilation, il faut bien que ton programme contient
un object dummy.)

C'est à peu près ce que j'ai dans mon appli, sauf que getlog() renvoie
un stream qui wrapp std::cout/ofstream/... ou qui ne fait rien du tout.
J'ai pas cherché à évaluer si le compilateur supprimait son utilisation,
vu que jusque là je n'en n'ai pas éprouvé le besoin.

Quote:
Ici aussi, on écrit ensuite :
LOGGER << "x = " << x ;

(Au fond, je me démande si:
#define LOGGER false && dummy
ne serait pas mieux pour supprimer le log. Ça permettrait
d'introduire des logs dans un initialisateur dans un
constructeur, par exemple :
Toto::Toto(
int titi )
: myTiti( ((LOGGER << "titi = " << titi), titi) )
// ...
..)

Actuellement, dans mon cas, les logs sont supprimés en recompilant
(uniquement) getlog.cpp pour que getlog() renvoie un wrapper "nul". Je
réalise qu'on pourrait aisément avoir la même chose avec un :

#define LOGGER if ( !log_are_enabled ) ; else dummy

et ainsi avoir un comportement dynamique, pour le coût d'un if(). Je ne
sais pas vraiment pourquoi, mais utiliser

#define LOGGER log_are_enabled && dummy

me parrait plus risqué.

--
Aurélien Regat-Barrel
Back to top
kanze
Guest





PostPosted: Thu Apr 27, 2006 10:06 am    Post subject: Re: Comment ecrire une macro qui "mangent" un argument de ty Reply with quote

Aurelien Regat-Barrel wrote:
Quote:
kanze a écrit :

En effet, Loïc a proposé quelque chose de ce genre dernièrement.
On a soit :
#define LOGGER getlog( __FILE__, __LINE__ )
soit
#define LOGGER if ( true ) ; else dummy
(Note bien que dans ce cas-ci, même avec les logs désactivés
lors de la compilation, il faut bien que ton programme contient
un object dummy.)

C'est à peu près ce que j'ai dans mon appli, sauf que getlog()
renvoie un stream qui wrapp std::cout/ofstream/... ou qui ne
fait rien du tout. J'ai pas cherché à évaluer si le
compilateur supprimait son utilisation, vu que jusque là je
n'en n'ai pas éprouvé le besoin.

Tout à fait. Je n'ai jamais eu besoin de supprimer la
configuration dynamique du log non plus -- correctement écrit et
utilisé, les tests consument vraiment peu de temps. Mais la
possibilité de pouvoir le faire a souvent été essentiel pour
faire accepter politiquement le logging.

Quote:
Ici aussi, on écrit ensuite :
LOGGER << "x = " << x ;

(Au fond, je me démande si:
#define LOGGER false && dummy
ne serait pas mieux pour supprimer le log. Ça permettrait
d'introduire des logs dans un initialisateur dans un
constructeur, par exemple :
Toto::Toto(
int titi )
: myTiti( ((LOGGER << "titi = " << titi), titi) )
// ...
..)

Actuellement, dans mon cas, les logs sont supprimés en
recompilant (uniquement) getlog.cpp pour que getlog() renvoie
un wrapper "nul". Je réalise qu'on pourrait aisément avoir la
même chose avec un :

#define LOGGER if ( !log_are_enabled ) ; else dummy

et ainsi avoir un comportement dynamique, pour le coût d'un
if(). Je ne sais pas vraiment pourquoi, mais utiliser

#define LOGGER log_are_enabled && dummy

me parrait plus risqué.

C'est cependant plus ou moins ce qui se trouve dans la plupart
des macros pour assert. L'intérêt, comme j'ai dit, c'est que
c'est une expression, et qu'il peut servir (avec l'opérateur
virgule) dans des contextes où seulement une expression est
permise. La risque, évidemment, c'est aussi que c'est une
expression, ce qui donne davantage de possibilités à le faire
foirer : true || LOGGER << ..., par exemple,

Dans la pratique, je ne travaille pas avec des programmeurs qui
cherchent à détourner ce que j'ai fait à ce point-là, et je n'ai
pas vu des « accidents » avec l'expression qui n'ont pas
provoqué des erreurs de compilation.

--
James Kanze GABI Software
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
Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ (French) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.