We are using a third-party C library which provides a printf()
-style log function,
void log(const char *format, ...);
For reasons that aren't worth going in to, we need to limit the rate at which messages get logged, something along the lines of
void rate_limited_log(const char* format, ...)
{
if (<not too fast>) {
log(format, ...);
}
}
Fortunately the authors of the C library knew what they were doing, and provided
void logv(const char* format, va_list ap);
so writing the above function is a relatively simple matter. Unfortunately however variadic functions don't play well with inlining, and so I came up with a second solution:
template <typename... T>
void rate_limited_log(const char* format, T&&... args)
{
if (<not too fast>) {
log(format, std::forward<T>(args)...);
}
}
This works perfectly and inlines the rate limiting condition as we'd like. But I have a couple of questions about it:
Is expanding a parameter pack into a C-style variadic function call like this a legal, well-defined thing to do in C++11, or have we just got lucky that it works?
Are the
&&
andstd::forward
actually necessary here, given we're calling a C function? It seems to work just as well if I useconst T&
, or even justT
by value, with or withoutstd::forward
.