繁体   English   中英

将可变参数从 function 传递给另一个?

[英]Passing variadic parameters from a function to another?

由于我不想在这里重复代码,我试图找出一种方法将这些记录器功能(例如调试、警告、信息等)中的每一个的公共部分移动到另一个 function 中。 我自己尝试过一种天真的方法,但似乎不能正常工作。 我想我需要直接传递一个va_list但这样做我不知道首先创建一个单独的 function 是否值得。 关于如何实现这一目标的任何想法/建议?

原来的

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, LOG_MAX_LENGTH, fmt, 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++中也更推荐。

使用参数包完善的转发

template <class ...args_t>
const std::string get_log_text(const char *fmt, args_t &&...args)
{
    char log_text[LOG_MAX_LENGTH];
    sprintf(log_text, fmt, std::forward<args_t>(args)...);
    return std::string(log_text);
}

template <class ...args_t>
void debug(const char *fmt, args_t &&...args)
{
    if (static_cast<uint8_t>(LogLevel::DEBUG) <= static_cast<uint8_t>(configuration.priority))
    {
        std::string log_text = get_log_text(fmt, std::forward<args_t>(args)...);
        std::cout << get_time_as_string() + " [DEBUG] " + log_text + "\n";
        std::cout.flush();
    }
}

因此,由于使用可变参数模板看起来是解决这个问题的最佳现代解决方案,我最终得到了以下解决方案,其中每个日志 function(调试、警告等)不再需要专门化。 自从我使用c++17进行编译以来,我从这个建议中获得了使用折叠表达式的灵感。

  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();
  }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM