У меня есть класс С++, который является интерфейсом для системы ведения журнала. Его функция ведения журнала реализована с использованием вариативных шаблонов С++ 11:
template <typename... Args>
void Frontend::log(const char *fmt, Args&&... args) {
backend->true_log(fmt, std::forward<Args>(args)...);
}
Каждый бэкэнд ведения журнала реализует свою собственную версию true_log
, которая, помимо прочего, использует перенаправленные параметры для вызова vsnprintf
. Например:.
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..
}
Все отлично работает, и я счастлив.
Теперь я хочу добавить статическую проверку параметров log()
: в частности, я хотел бы использовать атрибут формата GCC printf.
Я начал с тегирования функции log()
с помощью __attribute__ ((format (printf, 2, 3)))
(поскольку this
является первым "скрытым" параметром, мне нужно сдвинуть индексы параметров на единицу). Это не работает, потому что если с ошибкой компиляции сбой:
error: args to be formatted is not ‘...’
Затем я попытался добавить тот же атрибут к функции true_log()
. Он компилируется, но проверка ошибок фактически не выполняется: я попытался перейти к log()
некоторым недопустимым комбинациям форматирования/переменной, и никаких предупреждений не было. Может быть, такая проверка "слишком поздно" или, другими словами, информация о переменной была потеряна в цепочке вызовов?
В крайнем случае, если я аннотировал log()
с помощью __attribute__ ((format (printf, 2, 0)))
, я получал бы предупреждения о неправильных строках формата, но не была бы выдана диагностика для недопустимых комбинаций форматирования/переменных.
Подведение итогов проблемы: как я могу получить полную проверку формата из GCC, если я использую вариативные шаблоны С++ 11?