2009-12-15 9 views
11

Attualmente, sto usando il seguente modello di funzione di sopprimere avvertimenti variabili non utilizzati:Sopprime l'avviso di variabili inutilizzate in C++ => bug del compilatore o bug del codice?

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

Tuttavia, quando il porting di cygwin da Linux, ora sto ottenendo gli errori del compilatore g ++ su 3.4.4 (su Linux Sono 3.4 0,6, così forse questo è correggere un bug):?

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'argomento non utilizzato è una variabile membro dichiarata come:

volatile bool readWriteActivated; 

Is ° è un bug del compilatore o un bug nel mio codice?

Qui è il banco di prova minimo:

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

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

Non riesco a riprodurre il problema. Puoi pubblicare il codice che riproduce il problema. –

+1

WilliamKF - Perché hai accettato una risposta che dichiari chiaramente di non risolvere il tuo problema? – Tom

risposta

2

In GCC, è possibile definire una macro come segue:

#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 

I parametri contrassegnati con questa macro sopprimerà le emette avvertimento GCC non utilizzati (e rinomina il parametro con un prefisso di UNUSED_). Per Visual Studio, è possibile sopprimere gli avvisi con una direttiva #pragma.

+0

Sì, ma dipende dal compilatore. La domanda fornisce il modo comune per farlo in modo non dipendente dal compilatore, tuttavia, come mostrato, sta esercitando un bug nel compilatore. – WilliamKF

+0

+1 questa è la risposta più portabile. inoltre, gcc supporta '#pragma inutilizzato' - vedi anche la documentazione per la direttiva' _Pragma'. – justin

9

Non sono sicuro al 100% che questo sia portatile, ma questo è l'idioma che ho solitamente utilizzato per sopprimere gli avvisi relativi alle variabili non utilizzate. Il contesto qui è un gestore di segnale che viene utilizzato solo per catturare SIGINT e SIGTERM, quindi se la funzione viene mai chiamata so che è ora che il programma esca.

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

tendo a non gradire ingombrano l'elenco dei parametri con __attribute__((unused)), dal momento che il trucco getto a vuoto funziona senza ricorrere alle macro per Visual C++.

+0

Sì, è sia legale che C++ portatile. – greyfade

+1

Se vuoi rendere questo approccio compatibile con il codice esistente che usa inutilizzato(), definisci una macro: '#define inutilizzato (x) ((void) x)' –

+0

Questo non funzionerà se la variabile è un riferimento a un tipo incompleto. Ad esempio, 'struct a; void f (a & a_) {(void) a_; } 'darà un errore di compilazione. – Timothy003

28

il modo attuale di indicare in realtà non utilizza un parametro non sta dando un nome:

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

compilerà ovunque con tutte le avvertenze acceso, senza avvertimento circa il galleggiante inutilizzato. Anche se l'argomento ha un nome nel prototipo (ad esempio int f(int a, float f);), non si lamenterà ancora.

+1

+1 , questo è il modo giusto per farlo. – Mizipzor

+7

Sì, e di solito uso qualcosa come int f (int count, float/* epsilon * /) per denominare il parametro non utilizzato e il suo significato. –

+0

In verità, sono buone maniere, l'ho dimenticato, ma hai assolutamente ragione. – haavee

1

La soluzione proposta da haavee (modificata dalla ur) è quella che normalmente utilizzare:

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

Il vero problema si verifica quando l'argomento è volte ma non sempre utilizzato nel procedimento, ad esempio:

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

Ora, non posso commentare il nome del parametro epsilon perché che rompere il mio registrazione build (io non voglio inserire un altro #ifdef nella lista degli argomenti perché questo rende il codice molto difficile da leggere).

Quindi penso che la soluzione migliore sarebbe quella di utilizzare il suggerimento di 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; 
} 

La mia unica preoccupazione è che alcuni compilatori potrebbero mettere in guardia circa la "epsilon (void);" affermazione, ad es. "la dichiarazione non ha effetto" avviso o alcuni di questi - credo che dovrò solo testare tutti i compilatori che probabilmente userò ...

Problemi correlati