В чем разница между симпатичной функцией, функцией, func?
в чем разница между __PRETTY_FUNCTION__
, __FUNCTION__
, __func__
, и где они документируются? Как мне решить, какой из них использовать?
5 ответов
__func__
- неявно объявленный идентификатор, который расширяется до переменной массива символов, содержащей имя функции, когда она используется внутри функции. Он был добавлен в C в C99. От C99 §6.4.2.2/1:
идентификатор
__func__
неявно объявляется переводчиком, как если бы сразу после открытия скобки каждого определения функции объявлениеstatic const char __func__[] = "function-name";
появилось, где function-name-имя лексически-замкнутой функции. Это имя является незаполненным именем функции.
обратите внимание, что это не макро и не имеет особого значения во время предварительной обработки.
__func__
был добавлен в C++ в C++11, где он указан как содержащий "строку, определенную реализацией" (c++11 §8.4.1[dcl.fct.защита.general] / 8), что не столь полезно, как спецификация в C. (первоначальное предложение добавить __func__
в C++ был N1642).
__FUNCTION__
- это стандартное расширение, которое поддерживают некоторые компиляторы C (включая gcc и Visual C++); в общем, вы должны использовать __func__
где он поддерживается и используется только __FUNCTION__
если вы используете компилятор, который не поддерживает его (например, Visual C++, который не поддерживает C99 и еще не поддерживает все c++0x, не предоставляет __func__
).
__PRETTY_FUNCTION__
это расширение gcc, которое в основном совпадает с __FUNCTION__
, за исключением того, что для Функции C++ он содержит "красивое" имя функции, включая подпись функции. Visual C++ имеет аналогичное (но не совсем идентичное) расширение,__FUNCSIG__
.
для нестандартных макросов вы захотите ознакомиться с документацией вашего компилятора. Расширения Visual C++ включены в документацию MSDN компилятора C++"Стандартные Макросы". Расширения документации gcc описаны на странице документация gcc " имена функций в виде строк."
несмотря на то, что это не полностью отвечает на исходный вопрос, это то, что большинство людей, которые google, возможно, хотели бы видеть
для 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**)
__PRETTY_FUNCTION__
обрабатывает функции C++: классы, пространства имен, шаблоны и перегрузку
#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);
}
выход 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]
__func__
документируется в стандарте C++0x в разделе 8.4.1. В этом случае это предопределенная функция локальной переменной вида:
static const char __func__[] = "function-name ";
где "имя функции" - это реализация specfic. Это означает, что всякий раз, когда вы объявляете функцию, компилятор неявно добавляет эту переменную к вашей функции. То же самое верно и для __FUNCTION__
и __PRETTY_FUNCTION__
. Несмотря на их uppercasing, они не макросы. Хотя __func__
является дополнением к C++0x
g++ -std=c++98 ....
по-прежнему будет компилировать код с помощью __func__
.
__PRETTY_FUNCTION__
и __FUNCTION__
документированы здесь http://gcc.gnu.org/onlinedocs/gcc-4.5.1/gcc/Function-Names.html#Function-Names. __FUNCTION__
- это просто другое название для __func__
. __PRETTY_FUNCTION__
это то же самое, что __func__
в C, но в C++ он также содержит сигнатуру типа.
для тех, кто задается вопросом, как это происходит в VS.
MSVC 2015 Update 1, 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>();
}
выход:
from main(): main main int __cdecl main(void) from A::f(): A<int,float>::f f void __cdecl A<int,float>::f<bool>(void)
использование __PRETTY_FUNCTION__
запускает необъявленную ошибку идентификатора, как и ожидалось.