2010-02-24 29 views
6

Attualmente utilizzo il seguente modello semplicemente come un modo per verificare il puntatore NULL e se NULL stampa un messaggio di errore in un file di registro e quindi restituisce false.Passare il "nome" della variabile in C++

template< typename T > 
static bool isnull(T * t, std::string name = "") 
{ 
    _ASSERTE(t != 0); 
    if(!t) 
    { 
     if(!(name.length())) name = "pointer"; 
     PANTHEIOS_TRACE_ERROR(name + " is NULL"); 
     return false; 
    } 
    return true; 
} 

Attualmente chiamo questo come segue:

if(!(isnull(dim, BOOST_STRINGIZE(dim)))) return false; 

Se notate ho bisogno di passare nel campo "Nome" del puntatore variabile che voglio stampare il file di log, come il 2 ° parametro. Attualmente sto usando BOOST_STRINGIZE che converte semplicemente qualsiasi testo all'interno delle parentesi in una stringa.

Di seguito sono riportati gli svantaggi della mia implementazione template (per il mio utilizzo almeno)

  • Chiunque potrebbe passare nel nulla come parametro per BOOST_STRINGIZE stampare nel file di log - in quanto i 2 parametri non siano legati da comunque - quindi non vedrei necessariamente il "nome variabile" che è in realtà NULL
  • Dobbiamo ricordare di passare nel 2 ° parametro, altrimenti inutile.

Esiste comunque la possibilità di determinare automaticamente il "nome" di quella 1a variabile, in modo che possa ometterlo, come secondo parametro, ad ogni chiamata?

+1

A meno che non si esegua la magia del preprocessore non è possibile. ma è sempre possibile scrivere: '#define IS_NULL (a) isnull ((a), #a)' – lollinus

+1

Il secondo problema può essere risolto eliminando l'impostazione predefinita sul parametro name. Solo tangenzialmente correlati, usando "nome.empty()" potrebbe essere più veloce e/o più chiaro di "! Name.length()" –

+0

@ Mark-B. Grazie per il commento "vuoto" :). Penso che ho appena assunto che dal momento che vector.empty() chiama effettivamente size() (nell'implementazione VC++ 2005) che probabilmente era lo stesso per le stringhe. Cattivo ossacadico – ossandcad

risposta

9

Si potrebbe mettere tutto in un unico macro:

#define IS_NULL(name_) isnull(name_, #name_) 

noti che BOOST_STRINGIZE espande il suo argomento se una macro, che può o non può essere quello che vuole:

#define X(x_) std::cout << BOOST_STRINGIZE(x_) << " = " << x_ << std::endl; 
X(NULL); // prints: "0 = 0" 
+0

Vuoi una macro di stringify come "BOOST_STRINGIZE', o passerà sempre" name_ ". – GManNickG

+1

In questo modo, '#' stringa 'nome_'? La differenza di 'BOOST_STRINGIZE' è solo che espande' name_' se è una macro che non considero necessariamente un vantaggio. :) –

+0

Stavo pensando ad altro: 3 Entrambi i miei commenti scompariranno misteriosamente in una quantità di tempo non specificata. – GManNickG

1

Certo, perché no:

#define new_isnull(x) isnull(x, BOOST_STRINGIZE(x)) 
+0

Grazie. usare # invece di BOOST_STRINGIZE era un vantaggio della risposta accettata. – ossandcad

1

L'unico modo per fare qualcosa in questo modo lessicale è con i macro. Se si vuole sempre la stampa corretta, la soluzione migliore è quella di avvolgere l'intera dichiarazione in una macro:

//if(!(isnull(dim, BOOST_STRINGIZE(dim)))) return false; 
#define ISNULL(a) isnull((a), #a) 
if (!ISNULL(dim)) return false; 

Si noti che, come sempre, le macro hanno un certo numero di svantaggi ad essi associati.

Problemi correlati