问题描述
因为我不想在这里重复代码,所以我试图找出一种方法将每个记录器函数(例如调试、警告、信息等)的公共部分移到另一个函数中.
我自己尝试了一种幼稚的方法,但似乎无法正常工作。我想我需要直接传递一个 va_list
,但这样做我不知道是否值得首先创建一个单独的函数。关于如何实现这一目标的任何想法/建议?
原创
void ConsoleLogger::debug(const char *fmt...)
{
if (static_cast<uint8_t>(LogLevel::DEBUG) <= static_cast<uint8_t>(configuration.priority))
{
va_list args;
char log_text[LOG_MAX_LENGTH];
va_start(args,fmt);
vsnprintf(log_text,LOG_MAX_LENGTH,fmt,args);
va_end(args);
std::cout << get_time_as_string() + " [DEBUG] " + log_text + "\n";
std::cout.flush();
}
}
我的镜头没有按预期工作,因为 log_text 填充了错误/随机字符,而在原始文件中它打印了正确的字符串。
const std::string Logger::get_log_text(const char *fmt...) const
{
va_list args;
char log_text[LOG_MAX_LENGTH];
va_start(args,fmt);
vsnprintf(log_text,args);
va_end(args);
return std::string(log_text);
}
void ConsoleLogger::debug(const char *fmt...)
{
if (static_cast<uint8_t>(LogLevel::DEBUG) <= static_cast<uint8_t>(configuration.priority))
{
std::string log_text = get_log_text(fmt);
std::cout << get_time_as_string() + " [DEBUG] " + log_text + "\n";
std::cout.flush();
}
}
解决方法
嗯,首先这个答案并没有从字面上回答问题,因为我对 C 可变参数函数不是特别熟悉,但它可以解决你的实际问题,在 C++ 中也更推荐。
使用 parameter pack 和 perfect forwarding。
c=0
,
因此,由于使用可变参数模板看起来是解决此问题的最佳现代解决方案,因此我最终采用了以下解决方案,其中不再需要对每个日志功能(调试、警告等)进行专门化处理。自从我使用 c++17
编译后,我从 this 建议中获得了使用折叠表达式的灵感。
template <typename... T> void debug(const T &...args)
{
if (static_cast<uint8_t>(LogLevel::DEBUG) <= static_cast<uint8_t>(configuration.priority))
{
std::string final_text = "[DEBUG] " + get_log_text(args...);
log(final_text); // this is specialized in every Logger derived class depending on the type
}
}
template <typename... T> const std::string get_log_text(T &...args) const
{
std::ostringstream log_text;
((log_text << std::forward<T>(args)),...);
return log_text.str();
}