私はロギングシステムのフロントエンドであるC++クラスを持っています。そのロギング機能は、C++ 11の可変引数テンプレートを使用して実装されていますGCCのprintf format属性をC++ 11のバリデーションテンプレートで使用する方法は?
template <typename... Args>
void Frontend::log(const char *fmt, Args&&... args) {
backend->true_log(fmt, std::forward<Args>(args)...);
}
各ログのバックエンドは、とりわけ、vsnprintf
を呼び出すために、転送パラメータを使用して、こと、true_log
の独自のバージョンを実装しています。例:
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)))
というタグを付けることから始めました(this
は最初の "隠し"パラメータなので、パラメータインデックスを1つシフトする必要があります)。場合は、コンパイルエラーで失敗したので、これは、動作しません。そして、
error: args to be formatted is not ‘...’
、私はtrue_log()
関数に同じ属性を追加しようとしました。これはコンパイルされますが、実際にはエラーチェックは行われません。無効な書式/変数の組み合わせをlog()
に渡そうとしましたが、警告は発行されませんでした。たぶん、この種のチェックは「遅すぎますか」、言い換えれば、変数に関する情報がコールのチェーンで失われているのでしょうか?
最後に、log()
に__attribute__ ((format (printf, 2, 0)))
と注釈を付けると、間違った書式文字列に関する警告が表示されますが、無効な書式/変数の組み合わせについては診断が発行されません。
問題の概要:C++ 11の可変テンプレートを使用すると、どのようにGCCからフルフォーマットチェックができますか?
vsnprintf()は古い学校よりも多くのことを処理できないため、最初にバリデーショナルテンプレートを気にするのはなぜですか? –
型情報を投げ捨てるときにバリデーションテンプレートを使用しているのはなぜですか?単に 'true_log()'をあなたの本当のロギング関数にしてください。 –
また、 'Frontend :: log'を可変引数にする... –