我有一個C++類,它是日誌系統的前端。它的日誌功能使用C++ 11的可變參數模板來實現:如何在C++ 11可變參數模板中使用GCC的printf格式屬性?
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格式屬性。
我開始用__attribute__ ((format (printf, 2, 3)))
標記log()
函數(因爲this
是第一個「隱藏」參數,我需要將參數索引移動一個)。這是不行的,如果失敗,編譯錯誤,因爲:
error: args to be formatted is not ‘...’
然後,我想同樣的屬性添加到true_log()
功能。它編譯,但沒有實際執行錯誤檢查:我試圖傳遞給log()
一些無效的格式/變量組合,並且沒有發出警告。也許這種檢查「太遲了」,換句話說,有關變量的信息在調用鏈中已經丟失了?
作爲最後的手段,如果我註釋log()
與__attribute__ ((format (printf, 2, 0)))
,我會收到有關錯誤格式字符串的警告,但不會針對無效的格式/變量組合發出診斷。
總結問題:如果我使用C++ 11的可變參數模板,如何從GCC進行全格式檢查?
由於vsnprintf()不能處理比什麼老學校...可以做什麼更多,爲什麼要首先打擾可變參數模板呢? –
爲什麼當你丟棄類型信息時使用可變參數模板?只要讓'true_log()'成爲你真正的日誌記錄功能。 –
或者讓'Frontend :: log'帶一個變量參數... –