Tengo una clase C++ que es la interfaz para un sistema de registro. Su función de registro se implementa el uso de plantillas de C++ variadic 11:¿Cómo usar el atributo de formato printf de GCC con las plantillas variadas de C++ 11?
template <typename... Args>
void Frontend::log(const char *fmt, Args&&... args) {
backend->true_log(fmt, std::forward<Args>(args)...);
}
Cada registro backend implementa su propia versión de true_log
, que, entre otras cosas, utiliza los parámetros enviados a llamar vsnprintf
. Por ejemplo:
void Backend::true_log(const char *fmt, ...) {
// other stuff..
va_list ap;
va_start(ap, fmt);
vsnprintf(buffer, buffer_length, fmt, ap);
va_end(ap);
// other stuff..
}
Todo funciona muy bien, y estoy contento.
Ahora, quiero agregar una verificación estática en los parámetros log()
: específicamente, me gustaría usar el atributo de formato printf de GCC.
Comencé etiquetando la función log()
con __attribute__ ((format (printf, 2, 3)))
(como this
es el primer parámetro "oculto", necesito cambiar los índices de parámetros por uno). Esto no funciona, porque si falla con un error de compilación:
error: args to be formatted is not ‘...’
Entonces, traté de añadir el mismo atributo de la función true_log()
. Se compila, pero no se realiza ninguna comprobación de errores: Intenté pasar a log()
algunas combinaciones inválidas de formato/variable, y no se emitió ninguna advertencia. Tal vez este tipo de control es "demasiado tarde", o, en otras palabras, la información sobre la variable se ha perdido en la cadena de llamadas.
Como último recurso, si anotada log()
con __attribute__ ((format (printf, 2, 0)))
, iba a recibir advertencias sobre las cadenas de formato equivocadas, pero sin diagnóstico serían emitidas por formato combinaciones no válidas/variables.
Resumiendo el problema: cómo puedo tener formato completo la comprobación de GCC si uso las plantillas variadic de C++ 11?
Dado que vsnprintf() no puede hacer frente a más de lo que la vieja escuela ... puede hacer, ¿por qué molestarse con las plantillas variadic en primer lugar? –
¿Por qué está usando plantillas variadic cuando está tirando la información del tipo? Simplemente haga de 'true_log()' su verdadera función de registro. –
O haga que 'Frontend :: log' tome un argumento variable ... –