You’ve all pretty much nailed this already. But it’s a little challenging to follow. So let me take a stab at summarizing what you’ve said…
That difficulties here are that:
-
We are playing with a temporary
ostringstream
object, so taking addresses is contra-indicated. -
Because it’s a temporary, we cannot trivially convert to an
ostream
object through casting. -
Both the constructor [obviously] and
str()
are classostringstream
methods.
(Yes, we need to use.str()
. Using theostringstream
object directly would wind up invokingios::operator void*()
, returning a pointer-like good/bad value and not a string object.) -
operator<<(...)
exists as both inheritedostream
methods and global functions. In all cases it returns anostream&
reference. -
The choices here for
ostringstream()<<"foo"
are the inherited methodostream::operator<<(void* )
and the global functionoperator<<(ostream&,const char* )
. The inheritedostream::operator<<(void* )
wins out because we can’t convert to anostream
object reference to invoke the global function. [Kudos to coppro!]
So, to pull this off, we need to:
- Allocate a temporary
ostringstream
. - Convert it to an
ostream
. - Append data.
- Convert it back to an
ostringstream
. - And invoke
str()
.
Allocating: ostringstream()
.
Converting: There are several choices. Others have suggested:
ostringstream() << std::string() // Kudos to *David Norman*
ostringstream() << std::dec // Kudos to *cadabra*
Or we could use:
ostringstream() . seekp( 0, ios_base::cur )
ostringstream() . write( "", 0 )
ostringstream() . flush()
ostringstream() << flush
ostringstream() << nounitbuf
ostringstream() << unitbuf
ostringstream() << noshowpos
- Or any other standard manipulator. [
#include <iomanip>
] Reference: See “Insert data with format” 1/3 of the way down on this webpage.
We cannot use:
operator<<( ostringstream(), "" )
(ostream &) ostringstream()
Appending: Straightforward now.
Converting back: We could just use (ostringstream&)
. But a dynamic_cast
would be safer. In the unlikely event dynamic_cast
returned NULL
(it shouldn’t), the following .str()
will trigger a coredump.
Invoking str()
: Guess.
Putting it all together.
#define FORMAT(ITEMS) \
( ( dynamic_cast<ostringstream &> ( \
ostringstream() . seekp( 0, ios_base::cur ) << ITEMS ) \
) . str() )
References:
.