2

简短版本: 如何将...变量参数函数中表示的内容传递给另一个函数,而无需先将其解析为va_list?

长版:

以下是我的一类中的两个功能。我想提请您注意,每个函数的前四行是相同的。我在这个类中有六个其他函数,前四行相同。

void cyclOps::Logger::warn(char* szFile, char* szFunction, int iLine, char* szFormat, ...) {
    va_list vaArguments;
    va_start(vaArguments, szFormat);
    char szOutput[10000];
    _vsnprintf_s(szOutput, CYCLOPSSIZEOF(szOutput), _TRUNCATE, szFormat, vaArguments);
    this->log("WARNING: %s [%s - %s(%d)]", szOutput, szFile, szFunction, iLine);
}

void cyclOps::Logger::info(char* szFormat, ...) {
    va_list vaArguments;
    va_start(vaArguments, szFormat);
    char szOutput[10000];
    _vsnprintf_s(szOutput, CYCLOPSSIZEOF(szOutput), _TRUNCATE, szFormat, vaArguments);
    this->log("INFO: %s", szOutput);
}

我想将这四行相同的行放在一个名为的函数中summarizeVariableArguments(),并称它为这样的......

void cyclOps::Logger::info(char* szFormat, ...) {
      std::string strOutput = this->summarizeVariableArguments(/* TBD */);
    this->log("INFO: %s", strOutput.c_str());
}

...其中的内容strOutput将与szOutput前两个函数中的内容相同。但是如何将...参数传递给另一个函数?

4

3 回答 3

4

这就是完美转发的全部内容+ 可变参数模板。

template<typename ...Args>
void cyclOps::Logger::info(char* szFormat, Args &&...args) {
    std::string strOutput = this->summarizeVariableArguments(std::forward<Args>(args)...);
    this->log("INFO: %s", strOutput.c_str());
}
于 2012-12-06T17:34:46.100 回答
4

您不能以可移植的方式做到这一点(或者可能在编译时,使用可怕的 C++2011 可变参数模板技巧)。

如果您想在运行时调用可变参数函数,您可能需要使用libffi

详细信息是操作系统、编译器、处理器和 ABI 特定的。(但libffi正在尝试抽象它们)。

于 2012-12-06T17:13:07.680 回答
3

你制作了另一个接受va_list这样工作的函数:

void cyclOps::Logger::vLog(const char* format, va_list args)
{
    std::string logMessage = vFormat<10000>(format, args);
    // Do what you want with logMessage
}

template <size_t BufferSize>
std::string cyclOps::Logger::vFormat(const char* format, va_list args)
{
    char buffer[BufferSize];
    vsprintf(buffer, format, args);
    return std::string(buffer);
}

我已经为我的项目在 MSVC 和 GCC 上对此进行了测试。我只能说它对我有用。

这是一个工作示例。该解决方案适用于 C++03,我相信应该适用于 C++11。

于 2012-12-06T17:33:05.807 回答