Я реализую обработчик журналов в C ++, и он работает хорошо и все, однако есть одна вещь, которую я бы нашел пригодной для использования, и именно здесь регистратор получил вывод.
Я думаю, это не очень большая проблема, но я наткнулся на __func__
идентификатор, который в основном будет хранить имя функции текущей функции.
Так что у меня есть статическая функция в моем классе журнала называется Write
, он занимает уровень журнала и список изменений. Я бы назвал это так:
Log::Write(LOG_DEBUG, "this is an integer: %d", 10);
и он напечатает:
2013-01-02 => 10:12:01.366 [DEBUG]: this is an integer: 10
Однако я подумал, что было бы полезно также включить вызывающего в сообщение, чтобы получить что-то вроде этого:
2013... => 10:12:... (functionName) [DEBUG]: blah
Так что я могу сделать (конечно), чтобы добавить __func__
в качестве параметра для Log::Write
Однако это будет означать, что в любое время я звоню Log::Write
Мне нужно также отправить __func__
что всегда будет одним и тем же, и я чувствую, что это можно сделать без явного указания.
Итак, что я хочу, это функциональность, которая будет обеспечена:
Log::Write(LOG_DEBUG, __func__, "message");
без необходимости явно набирать FUNC каждый раз.
Я не знаю, возможно ли это на самом деле, лучше всего я понимаю, что есть какой-то способ разыменования вызывающей стороны внутри функции Write
Маловероятно, что я могу просто «вывести» такой параметр. Но стоит хотя бы спросить, и, возможно, я смогу посмотреть, какие есть варианты.
Благодарю.
Обычно это делается с помощью макросов вместе с именем файла __FILE__
и номер строки __LINE__
,
void Log::Write(Level l,
char const* function,
char const* file,
int line,
char const* format,
...);
оборачивается в макрос:
#define LOG(Level_, Format_, ...) \
Log::Write(Level_, __func__, __FILE__, __LINE__, Format_, __VA_ARGS__);
Обратите внимание, что вы можете «сохранить» некоторые вычисления, проверив, регистрироваться ли на этом уровне или нет:
// suppose availability of "bool Log::Enabled(Level l)"#define LOG(Level_, Format_, ...) \
while (Log::Enabled(Level_)) { \
Log::Write(Level_, __func__, __FILE__, __LINE__, Format_, __VA_ARGS__); \
break; \
}
Использование while
вместо if
это, чтобы избежать висящей проблемы.
Примечание: вы можете исследовать использование потоков для регистрации. Вопрос с printf
Стиль в том, что он не является составным. С помощью потоков вы можете перегружать std::ostream& operator<<(std::ostream&, X const&)
для любого X
а потом только пиши один раз метод, чтобы сбросить его содержимое в журналах.
#define WRITE_LOG(X,...) Log::Write(LOG_DEBUG, __func__, (X),__VA_ARGS__);
Используйте этот макрос для записи логов вместо функции, и он автоматически добавит FUNC параметр. Как упоминает Мат, это типичный способ, я не могу придумать, как избежать макросов в этом случае.