When confronted with this in the past, I've used a stringstream
along with a manipulator that displays the current contents of the stringstream
using MessageBox
:
#include <windows.h>
#include <sstream>
#include <ostream>
std::ostream &MessageBox(std::ostream &s) {
std::ostringstream *st = dynamic_cast<std::ostringstream *>(&s);
if (NULL != st)
::MessageBox(NULL, st->str().c_str(), "", MB_OK);
return s;
}
To use this, the syntax looks a fair amount like using cout
, but with MessageBox
replacing std::endl
. For example:
std::ostringstream stm;
stm << " blah blah blah. Value: " << 1213.1231 << MessageBox;
Edit: mostly for fnieto. In this case, the downcast really is necessary. The reason is fairly simple: a typical inserter receives and returns a reference to an ostream:
std::ostream &operator<<(std::ostream &os, T const &t) {
// code here to insert t into os, then return os;
}
This takes the original stringstream object and silently (and safely) casts it up to a simple ostream. That's fine in itself, and works fine for most inserters and manipulators, because they only interact with the ostream
interface themselves.
This manipulator, however, is a bit different -- it uses the str()
member, which ostream
doesn't define at all. For our call to str()
to resolve and compile, we have to convert the ostream &
to an ostringstream &
, so the compiler is aware that the object we're working with really will have a str()
member.
To eliminate the downcast, we'd really only have one choice: make its parameter an ostringstream &
. That would work as long as we never chained operators:
my_stream << x;
my_stream << MessageBox;
but trying to chain those would fail:
// should be equivalent:
my_stream << x << MessageBox;
Worse, the compiler's error message will probably try to tell the user something about std::basic_ostream<char>::str()
, which isn't mentioned in the user's code at all. Worse still, most people are sufficiently accustomed to chaining or not giving identical results that it would probably take them a while to even figure out why the code sometimes worked fine, and other times failed to compile, with a completely indecipherable error message.