次のセクションでロガーを作成しています。
// #define LOG(x) // for release mode
#define LOG(x) log(x)
log(const string& str);
log(const ostream& str);
するという考えで:
LOG("Test");
LOG(string("Testing") + " 123");
stringstream s;
LOG(s << "Testing" << 1 << "two" << 3);
これはすべて意図したとおりに機能しますが、そうすると:
LOG(stringstream() << "Testing" << 1 << "two" << 3);
それは動作しません:
void log(const ostream& os)
{
std::streambuf* buf = os.rdbuf();
if( buf && typeid(*buf) == typeid(std::stringbuf) )
{
const std::string& format = dynamic_cast<std::stringbuf&>(*buf).str();
cout << format << endl;
}
}
通常の正しい文字列ではなく、ジャンク データを含む 'format' になります。
これは、 << 演算子によって返された一時的な ostream が、元の文字列ストリームよりも長生きするためだと思います。
それとも私が間違っていますか?
(string() がこのように機能するのはなぜですか?それは、それ自体への参照を返すためですか?私はそう仮定しています。)
リリースモードでログインするときに追加の割り当てを排除するので、私は本当にこの方法でやりたいと思っています。
この方法でそれを行うための指針やコツは大歓迎です。私の実際のソリューションでは、さまざまなログ関数があり、それらはすべてこれよりも複雑です。したがって、これを何らかの方法で呼び出し元のコードに実装することをお勧めします。(可能であれば #define を変更しないでください)
アイデアを与えるために、私の実際の #defines の 1 つの例を示します。
#define LOG_DEBUG_MSG(format, ...) \
LogMessage(DEBUG_TYPE, const char* filepos, sizeof( __QUOTE__( @__VA_ARGS__ )), \
format, __VA_ARGS__)
これは、char*、string()、および ostream() を取る可変引数の printf のようなログ関数と、string()、exception()、および HRESULT を取る非可変引数関数に一致します。