10

printf()-スタイルのログ機能を提供するサードパーティの C ライブラリを使用しています。

void log(const char *format, ...);

踏み込む価値のない理由から、メッセージがログに記録される速度を制限する必要があります。

void rate_limited_log(const char* format, ...)
{
    if (<not too fast>) {
         log(format, ...);
    }
}

幸いなことに、C ライブラリの作成者は自分たちが何をしているのかを知っていたので、

void logv(const char* format, va_list ap);

したがって、上記の関数を書くことは比較的簡単なことです。残念ながら、可変個引数関数は inliningではうまく機能しないため、2 番目の解決策を思いつきました。

template <typename... T>
void rate_limited_log(const char* format, T&&... args)
{
    if (<not too fast>) {
        log(format, std::forward<T>(args)...);
    }
}

これは完全に機能し、必要に応じてレート制限条件をインライン化します。しかし、それについていくつか質問があります。

  • このようにパラメーター パックを C スタイルの可変引数関数呼び出しに展開することは、C++11 で行うべき正当で明確に定義されたものですか? それとも、それが機能するという幸運に恵まれたのでしょうか?

  • C関数を呼び出しているとすれば、実際にここで&&andが必要ですか? を使用しても、値だけでもstd::forward、 を使用しても使用しなくても、同様に機能するようです。const T&Tstd::forward

4

2 に答える 2

8

パラメータ パックを varargs に展開することは有効です。

また、転送したいときに転送しても害はありません。しかし、取ることconst&は何か有益なことも伝えます。

に渡された値は、...「デフォルト引数の昇格」を経験します。http://en.cppreference.com/w/cpp/language/variadic_argumentsを参照してください。

これらのどれも参照を気にしません。

コードを改善できます。Ts...「型の種類」と、実際に書式設定文字列を解析し、引数の数 (および場合によっては型) を確認することの両方によって、印刷ルーチンに渡す有効な型であることを確認できます。これが失敗した場合は、クラッシュする代わりにエラー メッセージをログに記録できます。

于 2014-08-26T20:48:07.373 に答える
3

ロギング機能にとってインライン化が重要かどうかはわかりません。実際、多くの C コンパイラは可変個引数関数をインライン化しません。ただし、マクロにすることはできます

#define RATE_LIMITED_LOG(Fmt,...) do { \
   if (not_too_fast())      \
     log(Fmt,__VA_ARGS__);  \
} while(0)

__LINE__特にロギング関数の場合、マクロにするのは良いことです__FILE__

#define RATE_LIMITED_LOG_AT2(Fil,Lin,Fmt,...) do {
   if (not_too_fast())
     log("%s:%d " Fmt, Fil, (Lin), __VA_ARGS__);
} while(0)
#define RATE_LIMITED_LOG_AT(Fil,Lin,Fmt,...) \
   RATE_LIMITED_LOG_AT2(Fil,Lin,Fmt,__VA_ARGS__)
#define RATE_LIMITED_LOG(Fmt,...) \
   RATE_LIMITED_LOG_AT(__FILE__,__LINE__,Fmt,__VA_ARGS__)

常にリテラルの正式な文字列であると想定されて"%s:%d "いる実数との文字列リテラルの連結に注意してください。Fmt典型的な用途はRATE_LIMITED_LOG("x=%d y=%d", x, y);...

私はそれがローテクで非常に C に似ている (C++11 ガジェットを使用していない) ことを認めますが、実際には非常にうまく機能します。実際には、マクロにソフトウェア固有の接頭辞を使用しています ( C++ ではなく C にあるmy MOM_FATAPRINTFin monimelt.hのように)。

于 2014-08-26T18:24:45.433 に答える