Generally, using the C++11 variadic template feature with functions requires the variadic-based function arguments to be the last in the function argument list. There is one exception; they are the next-to-last arguments if there are C-level variadic arguments, which must be dead last.
template < typename ...Args >
int super_printf( Something x, Args &&...a, ... );
I sometimes randomly think about C++, and I wondered how such a function can be implemented. I first thought about the usual recursive peeling of arguments from a, then I remembered that the C-level varargs don't cascade. I have to turn them to a definitive va_list right away.
template < typename ...Args >
int super_vaprintf( Something x, std::va_list &aa, Args &&...a );
// Note that "aa" is passed by reference.
template < typename ...Args >
int super_printf( Something x, Args &&...a, ... )
{
std::va_list args2;
int result;
va_start( args2, XXX ); // (A)
try {
result = super_vaprintf( x, args2, std::forward<Args>(a)... );
} catch ( ... ) {
va_end( args2 ); // (1)
throw;
}
va_end( args2 ); // (2)
return result;
// Can (1) and (2) be compacted with RAII using a custom deleter lambda
// in std::unique_ptr or something? Remember that "va_end" is a macro!
}
The usual C++ variadic recursive peeling happens in the super_vaprintf
call. At line (A), what goes in the place of XXX
, "a" or "a..."? What happens if a is empty, does x go there instead? If that last question's true, are we screwed if there's no x; that there's no arguments besides the variadic ones? (And if it's true, how do we conditionalize the code to use x when a is empty, and a otherwise?)
...
I just looked at my copy of the C++11 standard for any assistance here. There doesn't seem to be any. This would prompt a request for the C++ committee to come back to fix this, but I'm not sure that there's any way such a function could be called without the C++ varargs taking everything. Am I wrong; can a function call be made to use both C++ and C varargs? Or is mixing only useful for declarations, in terms of Stupid (Template) Instantiation Tricks?
super_printf<int, int>( Something{}, 1, 2, 3, 4 )
" could force some arguments as C-level (the "3" and "4" in this case). – Biologistprintf
example, my query is going in the other direction. If you meant his outlook on variadics, I'm querying on legality/"could", not morality/"should". – Biologist