20
my_macro << 1 << "hello world" << blah->getValue() << std::endl;

次のように展開する必要があります。

std::ostringstream oss;
oss << 1 << "hello world" << blah->getValue() << std::endl;
ThreadSafeLogging(oss.str());
4

7 に答える 7

76
#define my_macro my_stream()
class my_stream: public std::ostringstream  {
public:
    my_stream() {}
    ~my_stream() {
        ThreadSafeLogging(this->str());
    }
};
int main() {
    my_macro << 1 << "hello world" << std::endl;
}

my_streamのサブクラスであるタイプのテンポラリが作成されostringstreamます。その一時的な作業に対するすべての操作は、ostringstream.

ステートメントが終了すると (つまり、main() の印刷操作全体のセミコロンの直後)、一時オブジェクトは範囲外になり、破棄されます。my_streamデストラクタはThreadSafeLogging、以前に「収集された」データを使用して呼び出します。

テスト済み (g++)。

全体を単純化する方法を指摘してくれたdingoに感謝/クレジットするので、オーバーロードは必要ありませんoperator<<。残念ながら、賛成票は共有できません。

于 2010-02-03T23:02:22.017 に答える
3

ostream から派生させて、独自のスレッドセーフな実装を提供することはできませんか? それからあなたはただすることができます

myCOutObject << 1 << "hello world" << blah->getValue() << std::endl;

マクロを使用せずに C++ を適切に使用して、まったく同じ機能を取得しますか?

于 2010-02-03T23:03:04.733 に答える
2

いいえ。問題は、関数構文を使用しないと、マクロがその場所でのみ置換されることに制限されることです。

ただし、関数構文を使用する場合は、引数の前後の両方を置き換えることができます。

my_macro(1 << "hello world" << blah->getValue() << std::endl);

MyMacro を次のように定義することで可能です。

#define my_macro(args) std::ostreamstring oss; \
                       oss << args; \
                       ThreadSafeLogging(oss.str());
于 2010-02-03T23:01:26.373 に答える
2

google- glog を見てください。これは、インスタンス化された一時オブジェクトを使用して行われます。

LOG(INFO) << "log whatever" << 1;

また、LOG_IF などの他の興味深いマクロもあります。

于 2010-02-03T23:09:26.140 に答える
1

これは、私がどこかで見た別の厄介なトリックです。私の他の答えと比較して重大な欠点があります.変数を宣言するため、同じスコープで2回使用することはできません. ただし、の後にsomemacro foo何かを実行したい場合には、それでも興味深い場合があります。 foo

#define my_macro \
    std::ostringstream oss; \
    for (int x=0; x<2; ++x) \
        if (x==1) ThreadSafeLogging(oss.str()); \
        else oss

int main() {
    my_macro << 1 << "hello world" << std::endl;
}
于 2010-02-05T23:05:17.953 に答える