C ++マクロとして次の書き込みにとにかくありますか?
-
25-09-2019 - |
質問
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
の場合と同じようます。
ときの文が終了すると、一時的なオブジェクトがスコープ外に出ると、破壊される(すなわち。右のメイン()で全体の印刷動作にセミコロンの後)。 my_stream
デストラクタは、以前に「収集」データでThreadSafeLogging
を呼び出します。
テストした(G ++)。
おかげで/クレジットディンゴの全体を簡素化する方法を指摘して、私は、オーバーロードoperator<<
を必要としません。あまりにも悪いupvotesを共有することはできません。
他のヒント
あなただけの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らなどの他の興味深いマクロを持っています。
を考えると、あなたは、はい、それは可能です。
、これらの行は、あなたのコードのどこかに含まれてい#include <iostream>
#include <sstream>
__LINE__
マクロが全てスタンダートコンパイラによって定義されます。
我々は異なるウィッヒ変数名を生成するためにそれを使用できるようにするたびに、あなたは、マクロを使用します)。
ここで一つだけ文命令として見られている新しいバージョンは次のとおりです。 (編)
#define Var_(Name, Index) Name##Index
#define Var(Name, Index) Var_(Name, Index)
#define my_macro \
for (struct { int x; std::ostringstream oss; } Var(s, __LINE__) = { 0 }; \
Var(s, __LINE__).x<2; ++Var(s, __LINE__).x) \
if (Var(s, __LINE__).x==1) ThreadSafeLogging(Var(s, __LINE__).oss.str()); \
else Var(s, __LINE__).oss
// So you can use it like this
int main()
{
if (4 != 2)
my_macro << 4 << " hello " << std::endl;
my_macro << 2 << " world !" << std::endl;
}
開発者に対し、おそらくオペレータ<<
の簡略化のbecasue同じ行に二回、このマクロを使用する必要はありません。しかし、あなたがこれを必要とする場合には、あなたは__LINE__
によって__COUNTER__
の使用に切り替えることができます(非標準であります!)。このヒントのためのQuuxplusoneに感謝します。
ここで私はどこか見た別の厄介なトリックです。それは私の他の回答と比較して有意な欠点を持っている:それは変数を宣言しているため、あなたは同じスコープに二回、それを使用することはできません。しかし、それはまだのために面白いかもしれの他のあなたは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;
}
私が持っているログのセットアップは非常に似ています:
bool ShouldLog(const char* file, size_t line, Priority prio);
class LoggerOutput : public std::stringstream {
public:
LoggerOutput(const char* file, size_t line, Priority prio)
: prio(prio)
{
Prefix(file, line, prio);
}
void Prefix(const char* file, size_t line, Priority prio);
~LoggerOutput() {
Flush();
}
void Flush();
private:
Priority prio;
};
#define LOG(Prio) if (!Logging::ShouldLog(__FILE__, __LINE__, Prio)) {} else Logging::LoggerOutput(__FILE__, __LINE__, Prio)
あなたのロギングが無効になっている場合は、、ostreamには作成されず、わずかなオーバーヘッドが存在しているん。あなたは、ファイル名&行番号(S)または優先レベルにロギングを設定することができます。あなたは出力を絞るか、制限できるようShouldLog機能は、呼び出し間で変更することができます。両方が単一のコマンドとしてログ出力にそれをフラッシュし、それに改行を追加行に接頭辞、及びフラッシュ()「:ライン(PRIO)ファイルを」追加ログ出力用途自体を変更するための2つの機能を、プレフィックス。私の実装では、それは常に行いますが、1がすでに存在していない場合、あなたはそれを条件付きにすることができます。