Ho una classe C++ che è il frontend per un sistema di registrazione. La sua funzione di registrazione è implementata utilizzando C++ 11 di modelli variadic:Come utilizzare l'attributo di formato printf di GCC con i modelli variadici C++ 11?
template <typename... Args>
void Frontend::log(const char *fmt, Args&&... args) {
backend->true_log(fmt, std::forward<Args>(args)...);
}
Ogni registrazione backend implementa la sua versione di true_log
, che, tra le altre cose, utilizza i parametri inoltrati a chiamare vsnprintf
. Es .:
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..
}
Tutto funziona alla grande e sono felice.
Ora, voglio aggiungere un controllo statico sui parametri log()
: in particolare, vorrei utilizzare l'attributo di formato printf di GCC.
Ho iniziato taggando la funzione log()
con __attribute__ ((format (printf, 2, 3)))
(come this
è il primo parametro "nascosto", ho bisogno di spostare gli indici dei parametri di uno). Questo non funziona, perché se non riesce con un errore di compilazione:
error: args to be formatted is not ‘...’
Poi, ho provato ad aggiungere lo stesso attributo alla funzione true_log()
. Si compila, ma in realtà non viene eseguito alcun controllo degli errori: ho provato a passare a log()
alcune combinazioni di formato/variabile non valide e non è stato emesso alcun avviso. Forse questo tipo di controllo è "troppo tardi", o, in altre parole, l'informazione sulla variabile è stata persa nella catena di chiamate?
Come ultima risorsa, se ho annotato log()
con __attribute__ ((format (printf, 2, 0)))
, riceverei avvisi su stringhe di formato errate, ma non verrebbe emessa alcuna diagnostica per combinazioni formato/variabile non valide.
Riassumendo il problema: Come posso controllare il formato completo da GCC se utilizzo i modelli variadic di C++ 11?
Poiché vsnprintf() non può gestire più di quello che può fare la vecchia scuola, perché preoccuparsi con i modelli variadici in primo luogo? –
Perché stai usando modelli variadici quando stai semplicemente buttando via le informazioni sul tipo? Basta rendere 'true_log()' la tua reale funzione di logging. –
Oppure rendere 'Frontend :: log' prendere un argomento variabile ... –