Quelle est la différence entre __PRETTY_FUNCTION__
, __FUNCTION__
, __func__
et où sont - ils documentés? Comment puis-je décider lequel utiliser?
Quelle est la différence entre __PRETTY_FUNCTION__
, __FUNCTION__
, __func__
et où sont - ils documentés? Comment puis-je décider lequel utiliser?
Réponses:
__func__
est un identifiant déclaré implicitement qui se développe en une variable de tableau de caractères contenant le nom de la fonction lorsqu'il est utilisé à l'intérieur d'une fonction. Il a été ajouté à C en C99. À partir de C99 §6.4.2.2 / 1:
L'identifiant
__func__
est implicitement déclaré par le traducteur comme si, immédiatement après l'accolade ouvrante de chaque définition de fonction, la déclarationstatic const char __func__[] = "function-name";
est apparu, où nom-fonction est le nom de la fonction entourant lexicalement. Ce nom est le nom sans fioritures de la fonction.
Notez qu'il ne s'agit pas d'une macro et qu'elle n'a aucune signification particulière lors du prétraitement.
__func__
a été ajouté à C ++ dans C ++ 11, où il est spécifié comme contenant "une chaîne définie par l'implémentation" (C ++ 11 §8.4.1 [dcl.fct.def.general] / 8), ce qui n'est pas tout à fait utile comme spécification en C. (La proposition originale à ajouter __func__
au C ++ était N1642 ).
__FUNCTION__
est une extension pré-standard prise en charge par certains compilateurs C (y compris gcc et Visual C ++); en général, vous devez utiliser __func__
là où il est pris en charge et uniquement __FUNCTION__
si vous utilisez un compilateur qui ne le prend pas en charge (par exemple, Visual C ++, qui ne prend pas en charge C99 et ne prend pas encore en charge la totalité de C ++ 0x, ne fournir __func__
).
__PRETTY_FUNCTION__
est une extension gcc qui est essentiellement la même que __FUNCTION__
, sauf que pour les fonctions C ++, elle contient le "joli" nom de la fonction, y compris la signature de la fonction. Visual C ++ a une extension similaire (mais pas tout à fait identique), __FUNCSIG__
.
Pour les macros non standard, vous voudrez consulter la documentation de votre compilateur. Les extensions Visual C ++ sont incluses dans la documentation MSDN des «macros prédéfinies» du compilateur C ++ . Les extensions de la documentation de gcc sont décrites dans la page de documentation de gcc "Noms de fonction en tant que chaînes".
__FUNCTION__
, ils font des choses légèrement différentes. gcc donne l'équivalent de __func__
. VC donne la version non décorée, mais toujours ornée, du nom. Pour une méthode nommée "foo", gcc vous donnera "foo"
, VC vous donnera "my_namespace::my_class::foo"
.
__PRETTY_FUNCTION__
il apparaît dans la liste comme étant disponible et lorsque je déplace ma souris dessus, il affiche des informations sur le nom de la fonction, mais il ne parvient pas à compiler.
Bien qu'il n'ait pas pleinement répondu à la question initiale, c'est probablement ce que la plupart des gens recherchent sur Google.
Pour 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__
marche quand il est intégré dans une autre fonction? Disons que j'ai function1, cela ne prend aucun argument. function1 appelle function2 qui inclut __func__
, quel nom de fonction sera imprimé, 1 ou 2?
__func__
c'est une macro, elle se traduira dans la fonction dans laquelle vous vous trouvez actuellement. Si vous la mettez dans f1 et appelez f1 dans f2, vous obtiendrez toujours f1.
__PRETTY_FUNCTION__
gère les fonctionnalités C ++: classes, espaces de noms, modèles et surcharge
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);
}
Compiler et exécuter:
g++ -ggdb3 -O0 -std=c++11 -Wall -Wextra -pedantic -o main.out main.cpp
./main.out
Production:
f
f
static void N::C::f(int) [with T = char]
static void N::C::f(double) [with T = void]
Vous pouvez également être intéressé par les traces de pile avec des noms de fonction: imprimer la pile d'appels en C ou C ++
Testé dans 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 est entré en C ++ 20, nous avons donc encore une autre façon de le faire.
La documentation dit:
constexpr const char * nom_fonction () const noexcept;
6 Renvoie: si cet objet représente une position dans le corps d'une fonction, renvoie un NTBS défini par l'implémentation qui doit correspondre au nom de la fonction. Sinon, renvoie une chaîne vide.
où NTBS signifie "Chaîne d'octets terminée Null".
Je vais essayer quand le support arrivera à GCC, GCC 9.1.0 g++-9 -std=c++2a
ne le supporte toujours pas.
https://en.cppreference.com/w/cpp/utility/source_location les réclamations seront comme:
#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!");
}
Sortie possible:
info:main.cpp:16:main Hello world!
notez donc comment cela renvoie les informations sur l'appelant et est donc parfait pour une utilisation dans la journalisation, voir aussi: Existe - t-il un moyen d'obtenir le nom de la fonction dans une fonction C ++?
__func__
est documenté dans la norme C ++ 0x à la section 8.4.1. Dans ce cas, il s'agit d'une variable locale de fonction prédéfinie de la forme:
static const char __func__[] = "function-name ";
où "nom de fonction" est spécifique à l'implémentation. Cela signifie que chaque fois que vous déclarez une fonction, le compilateur ajoute implicitement cette variable à votre fonction. Il en va de même pour __FUNCTION__
et __PRETTY_FUNCTION__
. Malgré leur majuscule, ce ne sont pas des macros. Bien que __func__
soit un ajout à C ++ 0x
g++ -std=c++98 ....
compilera toujours le code en utilisant __func__
.
__PRETTY_FUNCTION__
et __FUNCTION__
sont documentés ici http://gcc.gnu.org/onlinedocs/gcc-4.5.1/gcc/Function-Names.html#Function-Names . __FUNCTION__
est juste un autre nom pour __func__
. __PRETTY_FUNCTION__
est le même qu'en __func__
C mais en C ++ il contient également la signature de type.
__func__
ne fait pas partie de C ++ 03. Il a été ajouté en C ++ 0x, mais C ++ 0x n'est pas encore "la norme C ++", il est toujours sous forme de brouillon.
Pour ceux qui se demandent comment ça se passe en VS.
MSVC 2015 Update 1, cl.exe version 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>();
}
production:
de main (): principale principale int __cdecl main (vide) de A :: f (): A <int, float> :: f F void __cdecl A <int, float> :: f <bool> (void)
Utilisation de __PRETTY_FUNCTION__
déclencheurs d'erreur d'identification non déclarée, comme prévu.