C++11 可变模板与vsnprintf

C++11 可变模板与vsnprintf,c++11,variadic-templates,C++11,Variadic Templates,尝试将以下函数升级到C++11时 int inline formatText(const char* const fmt, ...) { va_list args; va_start(args, fmt); int len = std::min(vsnprintf(m_text, m_textSize, fmt, args), m_textSize); va_end(args); m_text[len] = '\0'; // assume m_textSi

尝试将以下函数升级到C++11时

int inline formatText(const char* const fmt, ...)
{
    va_list args;
    va_start(args, fmt);
    int len = std::min(vsnprintf(m_text, m_textSize, fmt, args), m_textSize);
    va_end(args);
    m_text[len] = '\0'; // assume m_textSize is storage size - sizeof('\0')
    return len;
}
显然,因为printf处理的是pod,所以这个函数按值接受其参数并不是什么问题

但我意识到,我不清楚如何实现类似宏的参数精确转发,我意识到,通过内联一个简单的版本,编译器可以消除传递值,但我不确定以下三种方法中哪一种在技术上是最好的:

template<typename... Args>
  #if defined(APPROACH_1)
int formatText(const char* const fmt, Args...)
  #elif defined(APPROACH_2)
int formatText(const char* const fmt, const Args&...)
  #else
int formatText(const char* const fmt, Args&&...)
  #endif
{
    int len = std::min(snprintf(m_text, m_textSize, fmt, std::forward<Args>(args)...);
    m_text[len] = '\0';
    return len;
}
模板
#如果定义(方法1)
int formatText(常量字符*常量fmt,参数…)
#已定义elif(方法2)
int formatText(常量字符*常量fmt,常量参数&…)
#否则
int formatText(常量字符*常量fmt,参数&&…)
#恩迪夫
{
int len=std::min(snprintf(m_text,m_textSize,fmt,std::forward(args)…);
m_text[len]='\0';
回程透镜;
}
既然我们在这里讨论printf,那么按值复制并不可怕,因为我不应该将其传递给非pod对象;指定const ref肯定会帮助我不想复制的复杂对象,但对于printf的正常用例来说显然是适得其反的。我不确定方法3的副作用是什么


到目前为止,我读到的所有内容都给我留下了这样的印象,即“Args&&…”可能是可变模板的正常情况,但在这种情况下,我的直觉告诉我采用方法1。

只是好奇:为什么这三种方法中的任何一种都比旧的varargs方法好?varargs表单分为两个函数调用,首先调用formatText和rep对参数进行打包,然后调用vsnprintf。可变模板在一次调用中就完成了这项工作,将指令数减少了近一半。并将性能提高了2倍以上。我对这段代码进行了基准测试()使用g++4.8.1和
-Wall-O3-ggdb-std=c++11-o test.exe test.cpp
。然后我用
时间/test.exe>/dev/null
对其进行了基准测试。在我的测试盒上,ALG1的平均值为6.3009墙秒,用户数为5.245,而模板变量为2.006墙秒,用户数为2.004。阅读此-。简言之,使用和似乎是最好的变量。。。作为旁注:gcc可能不会使用省略号内联函数,因此这可能是您的性能增益(但我很惊讶,它比snprintf快3倍,因为snprintf只调用vsnprintf:))至少在gcc中,您将获得传递的参数与格式字符串的编译时验证,这是非常值得的(而不是无法解释的性能增益)