Qual è la differenza tra __PRETTY_FUNCTION__
, __FUNCTION__
, __func__
e dove sono documentati? Come posso decidere quale usare?
__func__
è un identificatore implicitamente dichiarato che si espande in una variabile di matrice di caratteri contenente il nome della funzione quando viene utilizzata all’interno di una funzione. È stato aggiunto a C in C99. Da C99 §6.4.2.2 / 1:
L’identificatore
__func__
è implicitamente dichiarato dal traduttore come se, immediatamente dopo la parentesi di apertura di ogni definizione di funzione, la dichiarazionestatic const char __func__[] = "function-name";
è apparso, dove nome-funzione è il nome della funzione che include lessicamente. Questo nome è il nome disadorno della funzione.
Si noti che non è una macro e non ha alcun significato speciale durante la preelaborazione.
__func__
stato aggiunto a C ++ in C ++ 11, dove è specificato come contenente “una stringa defi nita all’implementazione” (C ++ 11 §8.4.1 [dcl.fct.def.general] / 8), che non è abbastanza utile come la specifica in C. (La proposta originale di aggiungere __func__
a C ++ era N1642 ).
__FUNCTION__
è un’estensione pre-standard supportata da alcuni compilatori C (inclusi gcc e Visual C ++); in generale, dovresti usare __func__
dove è supportato e usare solo __FUNCTION__
se stai usando un compilatore che non lo supporta (per esempio, Visual C ++, che non supporta C99 e non supporta ancora tutto il C ++ 0x, non fornisce __func__
).
__PRETTY_FUNCTION__
è un’estensione gcc che è per lo più uguale a __FUNCTION__
, eccetto che per le funzioni C ++ contiene il nome “carino” della funzione che include la firma della funzione. Visual C ++ ha un’estensione simile (ma non del tutto identica), __FUNCSIG__
.
Per le macro non standard, ti consigliamo di consultare la documentazione del compilatore. Le estensioni di Visual C ++ sono incluse nella documentazione MSDN delle “macro predefinite” del compilatore C ++. Le estensioni della documentazione di gcc sono descritte nella pagina della documentazione di gcc “Nomi di funzione come stringhe”.
Nonostante questo non risponda completamente alla domanda originale, è ciò che la maggior parte delle persone che google potrebbe voler vedere
Per GCC:
[email protected]:~$ cat test.cpp #include int main(int argc, char **argv) { std::cout << __func__ << std::endl << __FUNCTION__ << std::endl << __PRETTY_FUNCTION__ << std::endl; } [email protected]:~$ g++ test.cpp [email protected]:~$ [email protected]:~$ ./a.out main main int main(int, char**)
__PRETTY_FUNCTION__
gestisce le funzionalità di C ++: classi, spazi dei nomi, modelli e sovraccarico
#include namespace N { class C { public: template static void f(int i) { std::cout << __func__ << std::endl << __FUNCTION__ << std::endl << __PRETTY_FUNCTION__ << std::endl; } template static void f(double f) { std::cout << __PRETTY_FUNCTION__ << std::endl; } }; } int main() { N::C::f(1); N::C::f(1.0); }
Output GCC 7.2 g++ -std=gnu++98
:
f f static void N::C::f(int) [with T = char] static void N::C::f(double) [with T = void]
__func__
è documentato nello standard C ++ 0x nella sezione 8.4.1. In questo caso è una variabile locale della funzione predefinita del modulo:
static const char __func__[] = "function-name ";
dove “nome della funzione” è specfic di implementazione. Ciò significa che ogni volta che si dichiara una funzione, il compilatore aggiungerà questa variabile implicitamente alla propria funzione. Lo stesso vale per __FUNCTION__
e __PRETTY_FUNCTION__
. Nonostante il loro uppercasing, non sono macro. Sebbene __func__
sia un’aggiunta a C ++ 0x
g++ -std=c++98 ....
compilerà ancora il codice usando __func__
.
__PRETTY_FUNCTION__
e __FUNCTION__
sono documentati qui http://gcc.gnu.org/onlinedocs/gcc-4.5.1/gcc/Function-Names.html#Function-Names . __FUNCTION__
è solo un altro nome per __func__
. __PRETTY_FUNCTION__
è uguale a __func__
in C ma in C ++ contiene anche la firma del tipo.
Per quelli che si chiedono come va in VS.
Aggiornamento MSVC 2015 1, versione cl.exe 19.00.24215.1:
#include template struct A { template static void f() { std::cout << "from A::f():" << std::endl << __FUNCTION__ << std::endl << __func__ << std::endl << __FUNCSIG__ << std::endl; } }; void main() { std::cout << "from main():" << std::endl << __FUNCTION__ << std::endl << __func__ << std::endl << __FUNCSIG__ << std::endl << std::endl; A::f(); }
produzione:
da main (): principale principale int __cdecl main (void) da A :: f (): A:: f f void __cdecl A :: f (void)
L’utilizzo di __PRETTY_FUNCTION__
innesca l’errore dell’identificatore non dichiarato, come previsto.