2016-08-24 3 views
2

(C++ 11なし)ログは現在、我々のコードベースは、次のようなコードをたくさん持っている:C++繰延

void log(int level, const char *msg) { 
    // logLevel is some global int defining which messages to log 
    if (level <= logLevel) { 
     cout << msg << endl; 
    } 
} 

... 

int someNum = 3; 
if (1 <= logLevel) { 
    char msg[200]; 
    sprintf(msg, "Some format %d", someNum); 
    log(1, msg); 
} 

我々は、Visual Studio 2008を使用しているので、任意の機能を使用することはできませんC++ 11。閉鎖をログメソッドに渡すきれいな方法があるので、重複した "if"条件を削除できますか?例えば、私は事前にC++ 11構文で、次のコードと同等を探しています:

void log(int level, std::function<std::string()> getMessage) { 
    if (level <= logLevel) { 
     cout << getMessage() << endl; 
    } 
} 

... 

int someNum = 3; 
log(1, [someNum]() -> std::string { 
    std::ostringstream sstream; 
    sstream << "Some format " << someNum; 
    return sstream.str(); 
}); 

私が思い付くことが最高です:マクロは、一般的に推奨されていない場合でも

struct LogMessage { 
    virtual std::string operator()() const = 0; 
}; 

void log(int level, const LogMessage &getMessage) { 
    if (level <= logLevel) { 
     cout << getMessage() << endl; 
    } 
} 

... 

struct X : public LogMessage { 
    X(int num) : myNum(num) { } 
    std::string operator()() const { 
     std::ostringstream out; 
     out << "Some format " << myNum; 
     return out.str(); 
    } 
    private: const int myNum; 
} a(someNum); 
log(1, a); 
+0

あなたは条件が2回試験された場合(呼び出し側によっておよび機能をログ)を避けるためにしたいですか? – jpo38

+0

ローカル構造体はテンプレート(C++ 03)で使用できないので、あなたが持つことができる最高のものだと思います。 – Jarod42

+0

@ jpo38はい、あなたの解釈は正しいです。 –

答えて

1

特に、すべてのテキストをストリームで処理できる場合は、この特定の場合に役立ちます。あなたがしなければ、その後

#define LOG(level, msg) { if (level <= logLevel) { cout << msg << endl; } } 

は、あなたのログ機能は、マクロも作成し

LOG(1, "Some format " << someNum) 

ifテストが行​​われ、一つだけと任意の複雑な書式は、マクロの2番目のパラメータで行われますのみログレベル条件がtrueの場合に実行してください。

注:sprintfのを使用して、既存のラインについて、あなたはまだ関数を宣言する必要があります...:

inline std::string printNum(int someNum) 
{ 
    char msg[200]; 
    sprintf(msg, "Some format %d", someNum); 
    return msg; 
} 

LOG(1, printNum(3)) 
+0

マクロパラメータにコンマが含まれている場合(sprintfの例のように)、括弧でマクロパラメータを囲むことができるので、そのまま渡すことができます。あなたは、もしあなたが二度は行われませんが、あなたの例はないと言います。あなたはあなたの例を質問に使われたものにすることができますか? –

+0

@JerryJeremiah:「スプリント」ステートメントはストリーム操作で置き換えることができます。ところで、マクロには 'if'(' if(level <= logLevel) ')があります。 – jpo38

+0

興味深いアイデア。違反行の多くはすでにsprintfスタイルですが、他のものはsprintfとcoutの両方を組み合わせています。私はCoutスタイルを使用するためにすべてを変換することができますが、変換中にエラーが発生する可能性はありません(現在のコードベースには数千のログステートメントがあります)。私はマクロルートに行くために必要なすべての作業を行うのではなく、コードをそのままにしておくことをお勧めします。 –