ロギングシステムのフロントエンドであるC++クラスがあります。そのロギング機能は、C++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
最初の「非表示」パラメーターと同様に、パラメーターのインデックスを1つシフトする必要があります)。コンパイルエラーで失敗した場合、これは機能しません。
error: args to be formatted is not ‘...’
次に、同じ属性をtrue_log()
関数に追加しようとしました。コンパイルされますが、実際にはエラーチェックは実行されません。いくつかの無効な形式/変数の組み合わせを渡そうとしましたがlog()
、警告は発行されませんでした。たぶん、この種のチェックは「遅すぎる」、つまり、変数に関する情報が一連の呼び出しで失われたのでしょうか。
最後の手段として、で注釈を付けるlog()
と__attribute__ ((format (printf, 2, 0)))
、間違った形式の文字列に関する警告が表示されますが、無効な形式と変数の組み合わせに対する診断は発行されません。
問題の要約:C ++ 11の可変個引数テンプレートを使用する場合、GCCから完全な形式をチェックするにはどうすればよいですか?