﻿# V1056\. The predefined identifier '\_\_func\_\_' always contains the string 'operator\(\)' inside function body of the overloaded 'operator\(\)'\.

Анализатор обнаружил использование идентификатора '\_\_func\_\_' в теле перегруженного оператора '\(\)'\.

Рассмотрим пример:

```cpp
class C
{
  void operator()(void)
  {
    std::cout << __func__ << std::endl;
  }
};

void foo()
{
  C c;
  c();
}
```

При запуске будет выведено 'operator\(\)'\. На первый взгляд, это вполне ожидаемое поведение для подобного кода, поэтому перейдем к более неочевидному примеру:

```cpp
void foo()
{
  auto lambda = [] () { return __func__; };
  std::cout << lambda() << std::endl;
}
```

Важно учитывать тот факт, что '\_\_func\_\_' не является переменной в привычном смысле этого слова, поэтому следующие варианты не сработают, и по\-прежнему будет выведено 'operator\(\)':

```cpp
void fooRef()
{
  auto lambda = [&] () { return __func__; };
  std::cout << lambda() << std::endl;
}
void fooCopy()
{
  auto lambda = [=] () { return __func__; };
  std::cout << lambda() << std::endl;
}
```

Чтобы исправить это в случае с лямбдой, необходимо передать '\_\_func\_\_' явно через список захвата:

```cpp
void foo()
{
  auto lambda = [func = __func__] () { return func; };
  std::cout << lambda() << std::endl;
}
```

Для более полноценного вывода имени функции даже внутри перегруженного 'operator\(\)' или тела лямбды можно воспользоваться специфичными для платформы/компилятора макросами\. Так, компилятор MSVC предоставляет следующие три макроса:

* '\_\_FUNCTION\_\_' – выводит имя функции, не опуская при этом его область объявления\. Например, для лямбды внутри функции main мы получим такой вывод: 'main::<lambda\_\.\.\.\.\>::operator \(\)';
* '\_\_FUNCSIG\_\_' – выводит полную сигнатуру функции\. Так же может быть полезным в связке с лямбдой: 'auto \_\_cdecl main::<lambda\_\.\.\.\.\>::operator \(\)\(void\) const';
* '\_\_FUNCDNAME\_\_' – выводит декорированное имя функции\. Это достаточно специфичная информация, поэтому она не подходит для полноценной замены '\_\_func\_\_'\.

Для компиляторов Clang и GCC доступны следующие макросы:

* '\_\_FUNCTION\_\_' – выводит то же имя, что и стандартный '\_\_func\_\_';
* '\_\_PRETTY\_FUNCTION\_\_' – выводит полную сигнатуру функции, например для лямбды может быть следующий вывод: 'auto main\(\)::\(anonymous class\)::operator\(\)\(\) const'\.