Qual è la differenza tra __PRETTY_FUNCTION__
, __FUNCTION__
, __func__
, e dove sono documentate? Come faccio a decidere quale utilizzare?
Qual è la differenza tra __PRETTY_FUNCTION__
, __FUNCTION__
, __func__
, e dove sono documentate? Come faccio a decidere quale utilizzare?
Risposte:
__func__
è un identificatore implicitamente dichiarato che si espande in una variabile di array di caratteri contenente il nome della funzione quando viene utilizzato all'interno di una funzione. Fu aggiunto a C nel C99. Da C99 §6.4.2.2 / 1:
L'identificatore
__func__
viene implicitamente dichiarato dal traduttore come se, immediatamente dopo il controvento iniziale di ciascuna definizione di funzione, la dichiarazionestatic const char __func__[] = "function-name";
è apparso, dove nome-funzione è il nome della funzione che racchiude il lessico. 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 che contiene "una stringa definita dall'implementazione" (C ++ 11 §8.4.1 [dcl.fct.def.general] / 8), che non è del tutto utile come specifica in C. (La proposta originale da aggiungere __func__
al C ++ era N1642 ).
__FUNCTION__
è un'estensione pre-standard supportata da alcuni compilatori C (inclusi gcc e Visual C ++); in generale, è necessario utilizzare __func__
dove è supportato e utilizzare solo __FUNCTION__
se si utilizza un compilatore che non lo supporta (ad esempio Visual C ++, che non supporta C99 e non supporta ancora tutto C ++ 0x, non fornire __func__
).
__PRETTY_FUNCTION__
è un'estensione gcc che è per lo più la stessa __FUNCTION__
, ad eccezione del fatto che per le funzioni C ++ contiene il nome "grazioso" della funzione inclusa la firma della funzione. Visual C ++ ha un'estensione simile (ma non del tutto identiche) __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 funzioni come stringhe".
__FUNCTION__
, fanno cose leggermente diverse. gcc fornisce l'equivalente di __func__
. VC fornisce la versione non decorata, ma ancora ornata, del nome. Per un metodo chiamato "pippo", gcc ti darà "foo"
, VC ti darà "my_namespace::my_class::foo"
.
__PRETTY_FUNCTION__
lo scrivo appare nell'elenco come disponibile e quando ci muovo sopra con il mouse, visualizza informazioni sul nome della funzione, ma non riesce a compilare.
Nonostante non abbia risposto completamente alla domanda originale, questo è probabilmente ciò che la maggior parte delle persone che cercavano su Google voleva vedere.
Per GCC:
petanb@debian:~$ cat test.cpp
#include <iostream>
int main(int argc, char **argv)
{
std::cout << __func__ << std::endl
<< __FUNCTION__ << std::endl
<< __PRETTY_FUNCTION__ << std::endl;
}
petanb@debian:~$ g++ test.cpp
petanb@debian:~$
petanb@debian:~$ ./a.out
main
main
int main(int, char**)
__func__
funziona quando è incorporato in un'altra funzione? Diciamo che ho function1, non ci vuole argomento. function1 chiama function2 che include __func__
, quale nome di funzione verrà stampato, 1 o 2?
__func__
è una macro, si tradurrà in qualunque funzione tu sia attualmente. Se lo metti in f1 e chiami f1 in f2, otterrai sempre f1.
__PRETTY_FUNCTION__
gestisce le funzionalità C ++: classi, spazi dei nomi, modelli e sovraccarico
main.cpp
#include <iostream>
namespace N {
class C {
public:
template <class T>
static void f(int i) {
(void)i;
std::cout << __func__ << std::endl
<< __FUNCTION__ << std::endl
<< __PRETTY_FUNCTION__ << std::endl;
}
template <class T>
static void f(double f) {
(void)f;
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
};
}
int main() {
N::C::f<char>(1);
N::C::f<void>(1.0);
}
Compila ed esegui:
g++ -ggdb3 -O0 -std=c++11 -Wall -Wextra -pedantic -o main.out main.cpp
./main.out
Produzione:
f
f
static void N::C::f(int) [with T = char]
static void N::C::f(double) [with T = void]
Potresti anche essere interessato a tracce di stack con nomi di funzioni: stampa stack di chiamate in C o C ++
Testato in Ubuntu 19.04, GCC 8.3.0.
C ++ 20 std::source_location::function_name
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1208r5.pdf è entrato in C ++ 20, quindi abbiamo ancora un altro modo per farlo.
La documentazione dice:
constexpr const char * nome_funzione () const noexcept;
6 Restituisce: se questo oggetto rappresenta una posizione nel corpo di una funzione, restituisce un NTBS definito dall'implementazione che dovrebbe corrispondere al nome della funzione. Altrimenti, restituisce una stringa vuota.
dove NTBS significa "Null Terminated Byte String".
Lo proverò quando il supporto arriva a GCC, GCC 9.1.0 con g++-9 -std=c++2a
ancora non lo supporta.
https://en.cppreference.com/w/cpp/utility/source_location l' utilizzo delle attestazioni sarà simile a:
#include <iostream>
#include <string_view>
#include <source_location>
void log(std::string_view message,
const std::source_location& location std::source_location::current()
) {
std::cout << "info:"
<< location.file_name() << ":"
<< location.line() << ":"
<< location.function_name() << " "
<< message << '\n';
}
int main() {
log("Hello world!");
}
Uscita possibile:
info:main.cpp:16:main Hello world!
quindi nota come questo restituisce le informazioni sul chiamante, ed è quindi perfetto per l'uso nella registrazione, vedi anche: C'è un modo per ottenere il nome della funzione all'interno di una funzione C ++?
__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 funzione" è specifico dell'implementazione. Ciò significa che ogni volta che dichiari una funzione, il compilatore aggiungerà implicitamente questa variabile alla tua funzione. Lo stesso vale per __FUNCTION__
e __PRETTY_FUNCTION__
. Nonostante il loro carattere maiuscolo, non sono macro. Anche se __func__
è un'aggiunta a C ++ 0x
g++ -std=c++98 ....
compilerà comunque 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__
è lo stesso __func__
di C ma in C ++ contiene anche la firma del tipo.
__func__
non fa parte di C ++ 03. È stato aggiunto in C ++ 0x, ma C ++ 0x non è ancora "lo standard C ++", è ancora in forma bozza.
Per quelli che si chiedono come va in VS.
Aggiornamento 1 di MSVC 2015, versione cl.exe 19.00.24215.1:
#include <iostream>
template<typename X, typename Y>
struct A
{
template<typename Z>
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<int, float>::f<bool>();
}
produzione:
da main (): principale principale int __cdecl main (vuoto) da A :: f (): A <int, float> :: f f void __cdecl A <int, float> :: f <bool> (void)
L'uso di __PRETTY_FUNCTION__
attiva un errore di identificazione non dichiarato, come previsto.