2009-12-15 17 views
11

Actuellement, je suis en utilisant le modèle de fonction suivante pour supprimer les avertissements variables inutilisées:Supprimer l'avertissement de variable inutilisée dans C++ => bug du compilateur ou bogue de code?

template<typename T> 
void 
unused(T const &) { 
    /* Do nothing. */ 
} 

Cependant, lors du portage à cygwin de Linux, je reçois maintenant des erreurs du compilateur sur g ++ 3.4.4 (Sur linux je suis 3.4 0,6, alors peut-être cela est un bug fix):

Write.cpp: In member function `void* Write::initReadWrite()': 
Write.cpp:516: error: invalid initialization of reference of type 'const volatile bool&' from expression of type 'volatile bool' 
../../src/common/Assert.h:27: error: in passing argument 1 of `void unused(const T&) [with T = volatile bool]' 
make[1]: *** [ARCH.cygwin/release/Write.o] Error 1 

L'argument utilisé est une variable membre déclaré:

volatile bool readWriteActivated; 

est-e est un bug de compilateur ou un bug dans mon code?

Voici le cas de test minimal:

template<typename T> 
void unused(T const &) { } 

int main() { 
    volatile bool x = false; 
    unused(!x); // type of "!x" is bool 
} 
+0

Je ne peux pas reproduire le problème. Pouvez-vous poster du code qui reproduit le problème. –

+1

WilliamKF - Pourquoi avez-vous accepté une réponse que vous indiquez clairement ne résout pas votre problème? – Tom

Répondre

2

Dans GCC, vous pouvez définir une macro comme suit:

#ifdef UNUSED 
#elif defined(__GNUC__) 
# define UNUSED(x) UNUSED_ ## x __attribute__((unused)) 
#elif defined(__LCLINT__) 
# define UNUSED(x) /*@[email protected]*/ x 
#else 
# define UNUSED(x) x 
#endif 

Tous les paramètres marqués avec cette macro supprimera les émette de GCC d'avertissement inutilisés (et renomme le paramètre avec le préfixe UNUSED_). Pour Visual Studio, vous pouvez supprimer les avertissements avec une directive #pragma.

+0

Oui, mais cela dépend du compilateur. La question donne la manière courante de le faire d'une manière qui ne dépend pas du compilateur, cependant, comme montré, il est en train d'exercer un bug dans le compilateur. – WilliamKF

+0

+1 c'est la réponse la plus portable. De plus, gcc supporte '#pragma unused' - voir aussi la documentation de la directive' _Pragma'. – justin

9

Je ne suis pas sûr à 100% que ce soit portable, mais c'est l'idiome que j'ai habituellement utilisé pour supprimer les avertissements sur les variables inutilisées. Le contexte ici est un gestionnaire de signal qui est seulement utilisé pour attraper SIGINT et SIGTERM, donc si la fonction est appelée, je sais qu'il est temps que le programme sorte.

volatile bool app_killed = false; 
int signal_handler(int signum) 
{ 
    (void)signum; // this suppresses the warnings 
    app_killed = true; 
} 

J'ont tendance à ne pas aimer qui encombrent la liste des paramètres avec __attribute__((unused)), puisque l'affaire coulé à vide fonctionne sans avoir recours à des macros pour Visual C++.

+0

Oui, c'est à la fois légal et portable. – greyfade

+1

Si vous souhaitez rendre cette approche compatible avec le code existant qui utilise unused(), définissez une macro: '#define unused (x) ((void) x)' –

+0

Cela ne fonctionnera pas si la variable est une référence à un type incomplet. Par exemple, 'struct a; void f (a & a_) {(vide) a_; } 'donnera une erreur de compilation. – Timothy003

28

La façon réelle de vous indiquant de ne pas utiliser réellement un paramètre ne donne pas un nom:

int f(int a, float) { 
    return a*2; 
} 

compilera partout avec tous les avertissements sous tension, sans avertissement au sujet du flotteur utilisé. Même si l'argument a un nom dans le prototype (par exemple, int f(int a, float f);), il ne se plaindra pas.

+1

, c'est la bonne façon de le faire. – Mizipzor

+7

Oui, et j'utilise normalement quelque chose comme int f (int count, float/* epsilon * /) afin de nommer le paramètre inutilisé et sa signification. –

+0

En effet, ce sont de bonnes manières, j'ai oublié ça, mais vous avez absolument raison. – haavee

1

La réponse proposée par haavee (modifié par ur) est celui que j'utiliserions normalement:

int f(int a, float /*epsilon*/) { 
    return a*2; 
} 

Le vrai problème se produit lorsque l'argument est parfois mais pas toujours utilisé dans la méthode, par exemple:

int f(int a, float epsilon) { 
#ifdef LOGGING_ENABLED 
    LOG("f: a = %d, epsilon = %f\n", a, epsilon); 
#endif 
    return a*2; 
} 

maintenant, je ne peux pas commenter le nom du paramètre epsilon parce que cela va me casser la construction de l'exploitation forestière (je ne veux pas insérer une autre #ifdef dans la liste des arguments parce que rend le code beaucoup plus difficile à lire).

Je pense donc la meilleure solution serait d'utiliser la suggestion de Tom:

int f(int a, float epsilon) { 
(void) epsilon; // suppress compiler warning for possibly unused arg 
#ifdef LOGGING_ENABLED 
    LOG("f: a = %d, epsilon = %f\n", a, epsilon); 
#endif 
    return a*2; 
} 

Mon seul souci serait que certains compilateurs pourraient mettre en garde contre la « (vide) epsilon; » déclaration, par ex. "déclaration n'a aucun effet" avertissement ou une telle - je suppose que je vais devoir tester sur tous les compilateurs que je suis susceptible d'utiliser ...