В чем разница между симпатичной функцией, функцией, 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&ltbool>(void)

использование __PRETTY_FUNCTION__ запускает необъявленную ошибку идентификатора, как и ожидалось.