my_macro << 1 << "hello world" << blah->getValue() << std::endl;
次のように展開する必要があります。
std::ostringstream oss;
oss << 1 << "hello world" << blah->getValue() << std::endl;
ThreadSafeLogging(oss.str());
my_macro << 1 << "hello world" << blah->getValue() << std::endl;
次のように展開する必要があります。
std::ostringstream oss;
oss << 1 << "hello world" << blah->getValue() << std::endl;
ThreadSafeLogging(oss.str());
#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<<
。残念ながら、賛成票は共有できません。
ostream から派生させて、独自のスレッドセーフな実装を提供することはできませんか? それからあなたはただすることができます
myCOutObject << 1 << "hello world" << blah->getValue() << std::endl;
マクロを使用せずに C++ を適切に使用して、まったく同じ機能を取得しますか?
いいえ。問題は、関数構文を使用しないと、マクロがその場所でのみ置換されることに制限されることです。
ただし、関数構文を使用する場合は、引数の前後の両方を置き換えることができます。
my_macro(1 << "hello world" << blah->getValue() << std::endl);
MyMacro を次のように定義することで可能です。
#define my_macro(args) std::ostreamstring oss; \
oss << args; \
ThreadSafeLogging(oss.str());
google- glog を見てください。これは、インスタンス化された一時オブジェクトを使用して行われます。
LOG(INFO) << "log whatever" << 1;
また、LOG_IF などの他の興味深いマクロもあります。
これは、私がどこかで見た別の厄介なトリックです。私の他の答えと比較して重大な欠点があります.変数を宣言するため、同じスコープで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;
}