Как получить имя вызывающей функции c ++ на этапе предварительной обработки - PullRequest
0 голосов
/ 21 ноября 2018

Я должен использовать макрос PERF_INSTRUMENT из библиотеки.PERF_INSTRUMENT ожидает, что пользователь предоставит строку в стиле c в качестве имени функции для печати местоположения этой точки инструмента.

Но я не хочу писать имя функции каждый раз, когда использую PERF_INSTRUMENT, вместо этого я хочу вызывать его с помощью __func__, чтобы имя функции автоматически включалось в журнал выполнения.

Но когда я использую __func__, он на самом деле возвращает operator(), потому что __func__ встроен в лямбда-функцию.

Это любой способ, которым я могу передать main()имя функции для макроса PERF_INSTRUMENT.

#include <cstdio>
#include <cassert> 
#include <type_traits> 

using namespace std;

namespace /* anonymous */
{
    template< typename T >
    struct Is_Const_Char_Array
      : std::is_same< std::remove_reference_t< T >,
                      char const[ std::extent< std::remove_reference_t< T > >::value ] >
    {};

    template< typename T >
    struct Is_C_String_Literal
      : Is_Const_Char_Array< T >
    {};
}

#define PERF_INSTRUMENT(name)  auto instObj = [] { static_assert( Is_C_String_Literal< decltype( name ) >::value, "input argument must be a c-string literal" ); /* Some other Logic*/ printf(name);return 1; }()


// <------------------ MY CODE -------------------> //

int main(){
    PERF_INSTRUMENT("main"); // <-- this works fine
    PERF_INSTRUMENT(__func__); // <-- this prints operator()
    // PERF_INSTRUMENT(__builtin_FUNCTION());
}

Обратите внимание, что я могу изменить только код ниже строки МОЙ КОД

Ответы [ 2 ]

0 голосов
/ 21 ноября 2018

Поскольку assert в корне ошибочен - он принимает любой массив const char - обертывание макроса в другой макрос должно работать.
Примерно так:

#define PERF_FUNCTION do { \
    const char name[] = __func__; \
    PERF_INSTRUMENT(name); \
} while(0)
0 голосов
/ 21 ноября 2018

Это любой способ, с помощью которого я могу передать имя основной функции в макрос PERF_INSTRUMENT.

Вы можете передать "name" в качестве аргумента самой лямбде.

Что-то вроде

#define PERF_INSTRUMENT(name) \
    auto instObj = [](char const * str) \ // <-- receive an argument
       { static_assert( Is_C_String_Literal< decltype( name ) >::value, \
                       "input argument must be a c-string literal" );\
         /* Some other Logic*/ \
         printf(str); \  // <-- print the argument received, not directly name
         return 1;\
       }(name)
//.......^^^^   pass name as argument

Бонус от темы Предложение: обнаружить объект - это литерал C-строки, я предлагаю альтернативный способ

template <typename T>
constexpr std::false_type islHelper (T, long);

template <typename T, std::size_t N>
constexpr std::true_type islHelper (T const(&)[N], int);

template <typename T>
using isStringLiteral = decltype(islHelper(std::declval<T>(), 0));

В static_assert()стать

static_assert( isStringLiteral<decltype(name)>::value,
               "input argument must be a c-string literal" );
...