Qual é a diferença entre __PRETTY_FUNCTION__
, __FUNCTION__
, __func__
, e onde eles estão documentadas? Como decido qual deles usar?
Qual é a diferença entre __PRETTY_FUNCTION__
, __FUNCTION__
, __func__
, e onde eles estão documentadas? Como decido qual deles usar?
Respostas:
__func__
é um identificador declarado implicitamente que se expande para uma variável de matriz de caracteres que contém o nome da função quando é usada dentro de uma função. Foi adicionado a C em C99. Do ponto C99 §6.4.2.2 / 1:
O identificador
__func__
é declarado implicitamente pelo tradutor como se, imediatamente após a chave de abertura de cada definição de função, a declaraçãostatic const char __func__[] = "function-name";
apareceu, onde nome da função é o nome da função que encerra lexicamente. Este nome é o nome sem adornos da função.
Observe que não é uma macro e não tem significado especial durante o pré-processamento.
__func__
foi adicionado ao C ++ no C ++ 11, onde é especificado como contendo "uma string definida pela implementação" (C ++ 11 §8.4.1 [dcl.fct.def.general] / 8), que não é tão útil como a especificação em C. (A proposta original para adicionar __func__
ao C ++ era N1642 ).
__FUNCTION__
é uma extensão pré-padrão que alguns compiladores C suportam (incluindo gcc e Visual C ++); em geral, você deve usar __func__
onde é suportado e usar somente __FUNCTION__
se estiver usando um compilador que não o suporte (por exemplo, Visual C ++, que não oferece suporte ao C99 e ainda não suporta todo o C ++ 0x, não fornecer __func__
).
__PRETTY_FUNCTION__
é uma extensão do gcc que é basicamente a mesma __FUNCTION__
, exceto que para as funções do C ++, ela contém o nome "bonito" da função, incluindo a assinatura da função. Visual C ++ tem uma extensão semelhante (mas não completamente idêntica) __FUNCSIG__
,.
Para macros fora do padrão, convém consultar a documentação do seu compilador. As extensões do Visual C ++ estão incluídas na documentação do MSDN das "Macros predefinidas" do compilador C ++ . As extensões da documentação do gcc são descritas na página de documentação do gcc "Nomes de funções como seqüências de caracteres".
__FUNCTION__
, eles fazem coisas ligeiramente diferentes. gcc fornece o equivalente a __func__
. O VC fornece a versão não decorada, mas ainda adornada, do nome. Para um método chamado "foo", o gcc fornecerá a você "foo"
, o VC fornecerá "my_namespace::my_class::foo"
.
__PRETTY_FUNCTION__
ele aparece na lista como disponível e quando movo o mouse sobre ele, ele exibe informações sobre o nome da função, mas falha na compilação.
Apesar de não responder totalmente à pergunta original, é provavelmente o que a maioria das pessoas pesquisando no Google queria ver.
Para o 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 quando incorporado em outra função? Digamos que eu tenho function1, não é necessário argumentos. function1 chama function2 que inclui __func__
, qual nome da função será impresso, 1 ou 2?
__func__
macro é traduzida para qualquer função em que você esteja atualmente. Se você colocar em f1 e chamar f1 em f2, você sempre obterá f1.
__PRETTY_FUNCTION__
lida com recursos do C ++: classes, namespaces, modelos e 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);
}
Compile e execute:
g++ -ggdb3 -O0 -std=c++11 -Wall -Wextra -pedantic -o main.out main.cpp
./main.out
Resultado:
f
f
static void N::C::f(int) [with T = char]
static void N::C::f(double) [with T = void]
Você também pode estar interessado em rastreamentos de pilha com nomes de função: imprimir pilha de chamada em C ou C ++
Testado no 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 entrou no C ++ 20, portanto, temos mais uma maneira de fazê-lo.
A documentação diz:
constexpr const char * nome_da_função () const noexcept;
6 Retorna: se este objeto representa uma posição no corpo de uma função, retorna um NTBS definido pela implementação que deve corresponder ao nome da função. Caso contrário, retorna uma string vazia.
onde NTBS significa "Cadeia de bytes nulos terminados".
Vou tentar quando o suporte chegar ao GCC, o GCC 9.1.0 com g++-9 -std=c++2a
ainda não o suporta.
https://en.cppreference.com/w/cpp/utility/source_location afirma que o uso 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!");
}
Saída possível:
info:main.cpp:16:main Hello world!
observe como isso retorna as informações do chamador e, portanto, é perfeito para uso em log, consulte também: Existe uma maneira de obter o nome da função dentro de uma função C ++?
__func__
está documentado no padrão C ++ 0x na seção 8.4.1. Nesse caso, é uma variável local de função predefinida do formulário:
static const char __func__[] = "function-name ";
onde "nome da função" é uma implementação específica. Isso significa que sempre que você declarar uma função, o compilador adicionará essa variável implicitamente à sua função. O mesmo vale para __FUNCTION__
e __PRETTY_FUNCTION__
. Apesar de serem maiúsculas, não são macros. Embora __func__
seja uma adição ao C ++ 0x
g++ -std=c++98 ....
ainda irá compilar o código usando __func__
.
__PRETTY_FUNCTION__
e __FUNCTION__
estão documentados aqui http://gcc.gnu.org/onlinedocs/gcc-4.5.1/gcc/Function-Names.html#Function-Names . __FUNCTION__
é apenas outro nome para __func__
. __PRETTY_FUNCTION__
é o mesmo que __func__
em C, mas em C ++ também contém a assinatura de tipo.
__func__
não faz parte do C ++ 03. Ele foi adicionado no C ++ 0x, mas o C ++ 0x ainda não é "o padrão C ++", ainda está em forma de rascunho.
Para aqueles que se perguntam como isso acontece no VS.
MSVC 2015, atualização 1, cl.exe versão 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>();
}
resultado:
from main (): a Principal a Principal int __cdecl principal (vazio) de A :: f (): A <int, float> :: f f void __cdecl A <int, float> :: f <bool> (void)
O uso de __PRETTY_FUNCTION__
disparadores de erro de identificador não declarado, conforme o esperado.