我们正在使用第三方 C 库,它提供了 printf()
风格的日志函数,
void log(const char *format, ...);
出于不值得深入探讨的原因,我们需要限制消息的记录速率,类似于
void rate_limited_log(const char* format, ...)
{
if (<not too fast>) {
log(format, ...);
}
}
幸运的是,C 库的作者知道他们在做什么,并提供了
void logv(const char* format, va_list ap);
所以写上面的函数是一件比较简单的事情。然而不幸的是variadic functions don't play well with inlining ,所以我想到了第二个解决方案:
template <typename... T>
void rate_limited_log(const char* format, T&&... args)
{
if (<not too fast>) {
log(format, std::forward<T>(args)...);
}
}
这完美地工作并且内嵌了我们想要的速率限制条件。但我对此有几个问题:
在 C++11 中将参数包扩展到 C 风格的可变参数函数调用中是合法的、定义明确的事情,还是我们只是很幸运它能工作?
鉴于我们调用的是 C 函数,
&&
和std::forward
在这里真的是必需的吗?如果我使用const T&
,或者甚至只是按值使用T
,无论是否使用std::forward
,它似乎都一样有效。
最佳答案
将参数包扩展为可变参数是有效的。
而且想转发就转发也没有坏处。但是通过 const&
获取也传达了一些有用的信息。
传递给 ...
的值将经历“默认参数提升”。参见 http://en.cppreference.com/w/cpp/language/variadic_arguments
这些都不关心引用。
您可以改进您的代码。您可以检查 Ts...
是否是传递给打印例程的有效类型,既可以通过“类型类型”,也可以通过实际解析格式字符串和确认参数的数量(有时是类型) .如果失败,您可以记录错误消息而不是崩溃。
关于c++ - 将可变模板参数传递给可变函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25512630/