Was ist der Unterschied zwischen __PRETTY_FUNCTION__
, __FUNCTION__
, __func__
, und wo sind sie dokumentiert? Wie entscheide ich mich für eine?
__func__
Ist ein implizit deklarierter Bezeichner, der zu einer Zeichenarrayvariablen mit dem Funktionsnamen erweitert wird, wenn er in einer Funktion verwendet wird. Es wurde C in C99 hinzugefügt. Von C99 §6.4.2.2/1:
Der Bezeichner
__func__
Wird vom Übersetzer implizit so deklariert, als ob unmittelbar nach der öffnenden Klammer jeder Funktionsdefinition die Deklarationstatic const char __func__[] = "function-name";
erschienen, wobei Funktionsname der Name der lexikalisch einschließenden Funktion ist. Dieser Name ist der schmucklose Name der Funktion.
Beachten Sie, dass es sich nicht um ein Makro handelt und während der Vorverarbeitung keine besondere Bedeutung hat.
__func__
Wurde C++ in C++ 11 hinzugefügt, wo angegeben wird, dass es "eine implementierungsdefinierte Zeichenfolge" enthält (C++ 11 §8.4.1 [dcl.fct.def.general]/8). , was nicht ganz so nützlich ist wie die Spezifikation in C. (Der ursprüngliche Vorschlag, __func__
zu C++ hinzuzufügen, war N1642 ).
__FUNCTION__
Ist eine Pre-Standard-Erweiterung, die einige C-Compiler unterstützen (einschließlich gcc und Visual C++). Im Allgemeinen sollten Sie __func__
verwenden, wenn dies unterstützt wird, und nur __FUNCTION__
, wenn Sie einen Compiler verwenden, der dies nicht unterstützt (z. B. Visual C++, der C99 nicht unterstützt und dies tut) unterstützt noch nicht alle C++ 0x, liefert keine __func__
).
__PRETTY_FUNCTION__
Ist eine gcc-Erweiterung, die größtenteils mit __FUNCTION__
Identisch ist, außer dass sie für C++ - Funktionen den "hübschen" Namen der Funktion einschließlich der Signatur der Funktion enthält. Visual C++ hat eine ähnliche (aber nicht ganz identische) Erweiterung, __FUNCSIG__
.
Informationen zu nicht standardmäßigen Makros finden Sie in der Dokumentation Ihres Compilers. Die Visual C++ - Erweiterungen sind in der MSDN-Dokumentation des C++ - Compilers enthalten "Predefined Macros" . Die Erweiterungen der gcc-Dokumentation werden auf der Seite der gcc-Dokumentation "Funktionsnamen als Zeichenfolgen" beschrieben
Obwohl die ursprüngliche Frage nicht vollständig beantwortet wurde, ist dies wahrscheinlich das, was die meisten Googler sehen wollten.
Für GCC:
[email protected]:~$ cat test.cpp
#include <iostream>
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__
verarbeitet C++ - Funktionen: Klassen, Namespaces, Vorlagen und Überladung
#include <iostream>
namespace N {
class C {
public:
template <class T>
static void f(int i) {
std::cout << __func__ << std::endl
<< __FUNCTION__ << std::endl
<< __PRETTY_FUNCTION__ << std::endl;
}
template <class T>
static void f(double f) {
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
};
}
int main() {
N::C::f<char>(1);
N::C::f<void>(1.0);
}
Ausgang 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]
Möglicherweise interessieren Sie sich auch für Stack-Traces mit Funktionsnamen: print call stack in C oder C++
C++ 20 source_location::function_name
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1208r5.pdf ist zu C++ 20 übergegangen, wir haben also noch eine andere Möglichkeit es.
In der Dokumentation heißt es:
constexpr const char * Funktionsname () const noexcept;
6 Rückgabe: Wenn dieses Objekt eine Position im Hauptteil einer Funktion darstellt, wird ein implementierungsdefiniertes NTBS zurückgegeben, das dem Funktionsnamen entsprechen sollte. Andernfalls wird eine leere Zeichenfolge zurückgegeben.
dabei bedeutet NTBS "Null Terminated Byte String".
Ich werde es versuchen, wenn GCC unterstützt wird, GCC 9.1.0 mit g++-9 -std=c++2a
unterstützt es immer noch nicht.
__func__
ist im C++ 0x-Standard in Abschnitt 8.4.1 dokumentiert. In diesem Fall handelt es sich um eine vordefinierte lokale Funktionsvariable des Formulars:
static const char __func__[] = "function-name ";
dabei ist "Funktionsname" implementierungsspezifisch. Dies bedeutet, dass der Compiler diese Variable implizit zu Ihrer Funktion hinzufügt, wenn Sie eine Funktion deklarieren. Gleiches gilt für __FUNCTION__
und __PRETTY_FUNCTION__
. Trotz ihrer Großschreibung sind sie keine Makros. Obwohl __func__
ist eine Ergänzung zu C++ 0x
g++ -std=c++98 ....
kompiliert weiterhin Code mit __func__
.
__PRETTY_FUNCTION__
und __FUNCTION__
sind hier dokumentiert http://gcc.gnu.org/onlinedocs/gcc-4.5.1/gcc/Function-Names.html#Function-Names . __FUNCTION__
ist nur ein anderer Name für __func__
. __PRETTY_FUNCTION__
ist das gleiche wie __func__
in C, aber in C++ enthält es auch die Typensignatur.
Für diejenigen, die sich fragen, wie es in VS geht.
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>();
}
ausgabe:
von main (): main main int __cdecl main (void) von A :: f () : A <int, float> :: f F Void __cdecl A <int, float> :: f & ltbool> (void)
Verwendung von __PRETTY_FUNCTION__
löst erwartungsgemäß einen nicht deklarierten Bezeichnerfehler aus.