¿Cuál es la diferencia entre __PRETTY_FUNCTION__
, __FUNCTION__
, __func__
, y dónde están documentados? ¿Cómo decido cuál usar?
¿Cuál es la diferencia entre __PRETTY_FUNCTION__
, __FUNCTION__
, __func__
, y dónde están documentados? ¿Cómo decido cuál usar?
Respuestas:
__func__
es un identificador declarado implícitamente que se expande a una variable de matriz de caracteres que contiene el nombre de la función cuando se usa dentro de una función. Fue agregado a C en C99. De C99 §6.4.2.2 / 1:
El
__func__
traductor declara implícitamente el identificador como si, inmediatamente después de la llave de apertura de cada definición de función, la declaraciónstatic const char __func__[] = "function-name";
aparecido, donde nombre-función es el nombre de la función de cierre léxico. Este nombre es el nombre sin adornos de la función.
Tenga en cuenta que no es una macro y no tiene un significado especial durante el preprocesamiento.
__func__
se agregó a C ++ en C ++ 11, donde se especifica que contiene "una cadena definida por la implementación" (C ++ 11 §8.4.1 [dcl.fct.def.general] / 8), que no es tan útil como la especificación en C. (La propuesta original para agregar __func__
a C ++ fue N1642 ).
__FUNCTION__
es una extensión preestándar que admiten algunos compiladores de C (incluidos gcc y Visual C ++); en general, deberías usar__func__
donde sea compatible y solo usar __FUNCTION__
si está utilizando un compilador que no lo admite (por ejemplo, Visual C ++, que no admite C99 y aún no admite todo C ++ 0x, no proporcionar __func__
).
__PRETTY_FUNCTION__
es una extensión de gcc que es casi igual a __FUNCTION__
, excepto que para las funciones de C ++ contiene el nombre "bonito" de la función, incluida la firma de la función. Visual C ++ tiene una extensión similar (pero no del todo idénticos), __FUNCSIG__
.
Para las macros no estándar, deberá consultar la documentación de su compilador. Las extensiones de Visual C ++ se incluyen en la documentación de MSDN de las "Macros predefinidas" del compilador de C ++ . Las extensiones de documentación de gcc se describen en la página de documentación de gcc "Nombres de funciones como cadenas".
__FUNCTION__
, hacen cosas ligeramente diferentes. gcc da el equivalente de __func__
. VC da la versión sin decorar, pero aún adornada, del nombre. Para un método llamado "foo", gcc te dará "foo"
, VC te dará "my_namespace::my_class::foo"
.
__PRETTY_FUNCTION__
aparece en la lista como disponible y cuando muevo el mouse sobre él, muestra información sobre el nombre de la función, sin embargo, no se compila.
A pesar de no responder completamente la pregunta original, esto es probablemente lo que la mayoría de las personas que buscaban en Google quería ver.
Para 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__
funciona cuando está incrustado en otra función? Digamos que tengo function1, no requiere argumentos. function1 llama a function2 que incluye __func__
, ¿qué nombre de función se imprimirá, 1 o 2?
__func__
Es una macro, se traducirá a cualquier función en la que se encuentre actualmente. Si lo coloca en f1 y llama a f1 en f2, siempre obtendrá f1.
__PRETTY_FUNCTION__
maneja características de C ++: clases, espacios de nombres, plantillas y sobrecarga
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);
}
Compilar y ejecutar:
g++ -ggdb3 -O0 -std=c++11 -Wall -Wextra -pedantic -o main.out main.cpp
./main.out
Salida:
f
f
static void N::C::f(int) [with T = char]
static void N::C::f(double) [with T = void]
También puede estar interesado en los seguimientos de pila con nombres de funciones: imprimir la pila de llamadas en C o C ++
Probado en 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 entró en C ++ 20, por lo que tenemos otra forma de hacerlo.
La documentación dice:
constexpr const char * nombre_función () const noexcept;
6 Devuelve: Si este objeto representa una posición en el cuerpo de una función, devuelve un NTBS definido por la implementación que debería corresponder al nombre de la función. De lo contrario, devuelve una cadena vacía.
donde NTBS significa "Cadena de bytes terminada nula".
Lo intentaré cuando llegue el soporte a GCC, GCC 9.1.0 con g++-9 -std=c++2a
todavía no lo admite.
https://en.cppreference.com/w/cpp/utility/source_location el uso de reclamos será como:
#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!");
}
Salida posible:
info:main.cpp:16:main Hello world!
así que tenga en cuenta cómo esto devuelve la información de la persona que llama y, por lo tanto, es perfecto para su uso en el registro, vea también: ¿Hay alguna manera de obtener el nombre de la función dentro de una función de C ++?
__func__
está documentado en el estándar C ++ 0x en la sección 8.4.1. En este caso es una variable local de función predefinida de la forma:
static const char __func__[] = "function-name ";
donde "nombre de función" es específico de implementación. Esto significa que siempre que declare una función, el compilador agregará esta variable implícitamente a su función. Lo mismo es cierto de __FUNCTION__
y __PRETTY_FUNCTION__
. A pesar de sus mayúsculas, no son macros. Aunque __func__
es una adición a C ++ 0x
g++ -std=c++98 ....
seguirá compilando código usando __func__
.
__PRETTY_FUNCTION__
y __FUNCTION__
están documentados aquí http://gcc.gnu.org/onlinedocs/gcc-4.5.1/gcc/Function-Names.html#Function-Names . __FUNCTION__
es solo otro nombre para __func__
. __PRETTY_FUNCTION__
es lo mismo que __func__
en C pero en C ++ también contiene la firma de tipo.
__func__
no es parte de C ++ 03. Se ha agregado en C ++ 0x, pero C ++ 0x aún no es "el estándar de C ++", todavía está en forma de borrador.
Para aquellos que se preguntan cómo va en VS.
MSVC 2015 Update 1, cl.exe versión 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>();
}
salida:
de main (): principal principal int __cdecl main (nulo) de A :: f (): A <int, float> :: f F void __cdecl A <int, float> :: f <bool> (void)
El uso de __PRETTY_FUNCTION__
disparadores de error de identificador no declarado, como se esperaba.