Я создаю регистратор со следующими разделами:
// #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;
}
}
приводит к «формату», содержащему нежелательные данные вместо обычной правильной строки.
Я думаю, это потому, что временный ostream, возвращаемый оператором <<, переживает поток строк, из которого он исходит. </p>
Или я не прав?
(Почему string () работает таким образом? Это потому, что он возвращает ссылку на себя? Я предполагаю, что да.)
Мне бы очень хотелось сделать это так, как я бы исключил дополнительное выделение при входе в режим релиза.
Приветствуются любые указатели или уловки, чтобы сделать это таким образом. В моем реальном решении у меня много разных функций журнала, и все они более сложные, чем эта. Поэтому я бы предпочел, чтобы это было реализовано как-то в вызывающем коде. (И не изменяя мой #define, если это возможно)
Просто чтобы дать идею, пример одного из моих фактических #defines:
#define LOG_DEBUG_MSG(format, ...) \
LogMessage(DEBUG_TYPE, const char* filepos, sizeof( __QUOTE__( @__VA_ARGS__ )), \
format, __VA_ARGS__)
, который соответствует функциям журнала varargs printf-подобного, принимающим char *, string () и ostream (), а также функциям не vararg, принимающим string (), exception () и HRESULT.