Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing variadic template arguments to a variadic function

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 && and std::forward actually necessary here, given we're calling a C function? It seems to work just as well if I use const T&, or even just T by value, with or without std::forward.

like image 884
Tristan Brindle Avatar asked Aug 26 '14 18:08

Tristan Brindle


1 Answers

Expanding parameter packs into varargs is valid.

And there is no harm in forwarding when you want to forward. But taking by const& also communicates something useful.

The values passed to ... will experience "default argument promotions". See http://en.cppreference.com/w/cpp/language/variadic_arguments

None of these care about references.

You can improve your code. You can check that the Ts... are valid types to pass to the printing routine, both by "kind of type" and by actually parsing the formatting string and confirming number (and sometimes type) of arguments. If this fails, you can log an error message instead of crashing.

like image 63
Yakk - Adam Nevraumont Avatar answered Sep 25 '22 14:09

Yakk - Adam Nevraumont