2009-11-03 26 views
2

Je dois avoir quelques lignes de code "actives" en mode débogage seulement, et ignorées en mode release. Est-il possible de faire quelque chose comme ceci:Comment commenter des lignes automatiquement en mode release?

#include <iostream> 
using namespace std; 

#ifdef _TEST_ 
#define _cerr cerr 
#else 
#define _cerr // cerr 
#endif 

int main() { 
    _cerr << "TEST message" << endl; 
} 

Alors que lorsque _TEST_ n'est pas défini, certaines lignes sont commentées ou supprimées du code. Je sais que les commentaires sont traités avant le reste, donc ce code est faux. Mais comment puis-je obtenir le comportement dont j'ai besoin sans utiliser explicitement #ifdefs?

Répondre

2

ifdefs est la voie à suivre. Sinon, comment savoir si le compilateur est en mode release vs debug? Quand d'autre part pendant la phase de prétraitement cela serait-il communiqué? À quelle autre étape pourriez-vous décider de supprimer/ajouter du code (en plus de la génération de modèle). Hey peut-être que nous pouvons utiliser la génération de modèles ... mais vous devez toujours désactiver l'ifdef pour contrôler votre modèle.

Peut-être y a-t-il une façon très pratique de faire cela à laquelle je ne pense pas, mais tout le monde connaît/utilise ifdefs à cette fin. Si vous leur lancez une courbe, cela ne fera qu'augmenter drastiquement le coût humain de la maintenance de votre code.

Stick avec ifdefs.

9

Vous pouvez utiliser une macro pour cela:

#ifdef _TEST_ 
#define DEBUG_ONLY(x) x; 
#else 
#define DEBUG_ONLY(x) 
#endif 

int main() { 
    DEBUG_ONLY(cerr << "TEST message" << endl) 
} 
+0

utile macro +1 –

+4

ne pas ajouter le point-virgule dans la macro rend votre code plus C++ comme (utilisateur forces ajouter ',' après l'article 'DEBUG_ONLY') – xtofl

+0

Le seul problème que je vois avec cette macro est que vous sont limités à une déclaration. Personnellement, je préfère un 'do {x; } while (0) 'clause pour autoriser plusieurs instructions dans la macro (même si certains compilateurs se plaignent de la partie' while (0) '...: /) –

0
int main() { 
#ifdef _TEST_ 
    _cerr << "TEST message" << endl; 
#endif 
} 
4

Utilisez ceci:

#ifdef _TEST_ 
#define DEBUG_TEST(x) x 
#else 
#define DEBUG_TEST(x) 
#endif 

int main() { 
    DEBUG_TEST(_cerr << "TEST message" << endl); 
} 
0

Non, absolument, pas.

Essayer une variation sur ce point: (. Fondamentalement, vous voulez un flux qui défausse juste son entrée)

#ifdef _TEST_ 
    ostream& _cerr = cerr; 
#else 
    ostringstream _cerr; 
#endif 

+1

Tout d'abord, l'utilisation d'un nom global avec un préfixe de soulignement est réservée pour la mise en œuvre, je crois. En second lieu, un flux qui rejette son entrée n'empêchera pas l'évaluation des arguments, ce qui rendra cette approche inutile dans n'importe quel contexte sensible aux performances. – Tom

1

Ce fait ici essentiellement ce que vous demandez:

#ifdef _TEST_ 
#define _cerr cerr 
#else 
#define _cerr if (1) {} else cerr 
#endif 

Mais ne soyez pas surpris si vous obtenez par exemple des avertissements de compilateur à propos de else ambigu si vous écrivez quelque chose comme ceci:

if (something) 
    _cerr << "Why?" << std::endl; 

Vous devez toujours être conscient du fait que cette _cerr est en fait une macro non triviale. La définition de _cerr à rien échouera la compilation.

1

Vous pouvez définir à la place une macro que vous excluez en mode de publication.

Par exemple:

#ifdef _TEST_ 
#define LOG_ERROR(log) cerr << log << endl; 
#else 
#define LOG_ERROR(log) 
#endif 

Puis dans votre code:

int main() { 
    LOG_ERROR("TEST message"); 
} 
+0

Il n'essayait pas de le définir à rien. Il espérait que les barres de commentaire seraient incluses dans la macro-expansion, de sorte que le résultat serait une ligne de journalisation commentée. –

5

Si ce que vous recherchez est l'enregistrement de débogage qui est supprimé dans la version construit, vous pouvez faire quelque chose comme:

#ifdef _TEST_ 
#define LOG(x) (cerr << x << endl) 
#else 
#define LOG(x) 
#endif 

... 

int main() { 
    LOG("TEST message"); 
} 
0

Une meilleure solution pour le "no logging in release" est la classe suivante:

class NullStream { 
    template<typename T> NullStream& operator<< const(T&) { } 
}; 

Utilisation:

#ifdef DEBUG 
#define CERR std::cerr 
#else 
#define CERR NullStream() 
#endif 
+0

Pas plus gentil: les arguments seront évalués ... même si c'est inutile! –

+0

Vrai, mais vous avez également ce problème lorsque vous écrivez par exemple. un stringstream. Cela économise à la fois les frais généraux de 'operator << (ostream &, T)' et 'ostreambuf' – MSalters

0

Créez votre propre flux NULL.

#include <iostream> 

class NullStream {}; 
template<typename T> 
NullStream& operator <<(NullStream& n,T const& data)      {return n;} 
NullStream& operator <<(NullStream& n,std::ostream& (*)(std::ostream&))  {return n;} 

#ifdef _TEST_ 
#define myerr  std::cerr 
#else 
NullStream myerrstream; 
#define myerr  myerrstream 
#endif 

int main() 
{ 
    myerr << "Hi" << std::endl;; 
    myerr << std::endl;; 
}