Note: The C++11 construct
std::to_string( x ) is more efficient than this. See end of article for perfomance comparisons.
Quite frequently, a C++ coder will face the issue of turning some value or object into its string representation (usually for output of some kind). Conveniently, when you want to write to terminal or a file, this can be done quite easily using the commonplace
int i = 42; std::cout << "The value of i is " << i << "\n";
Things get a bit more difficult when you want to get the result as a
std::string (for example, as parameter to an exception constructor):
std::ostringstream s; s << "The value of i is " << i; std::string output = s.str();
There are several footholes to be aware of, and anyway writing up those lines over and over again can become quite tedious. Thus, I present to thee:
By no means an invention of myself, I first came across this construct in 2002. Since then, it has followed me to whatever C++ code I was working upon. Without further ado:
#include <sstream> #define SSTR( x ) static_cast< std::ostringstream & >( std::ostringstream() << std::dec << x ).str()
Creating an anonymous ostringstream object with which we will construct the string.
Setting the integer output format to “decimal” looks like a non-op since decimal is the default anyway. However, it has the effect of returning not the original
ostringstream object, but a reference to
ostream. This is important if the first data element given to the macro is a pointer (e.g. a C-style string): If we would use the
ostringstream object directly, function lookup would use ostream::operator<<( void * ) in this case (giving us a boolean value) instead of the global operator<<( ostream &, char const * ) we want (giving us a string output).
Other versions of this macro that I came across in the 'net use the non-op construct
std::ostringstream().seekp( 0, std::ios_base::cur ) to get at that
ostream & return value. However, that construct is known to break on Microsoft Visual C++ 2005, and possibly some others, whereas the
std::dec trick worked on any platform I have been working on so far, including Solaris and AIX.
…passes the macro parameter(s) verbatim. This could be a single data value, or any number of values daisy-chained with more
static_cast< std::ostringstream & >( … )
We turned our
ostringstream object into a
ostream reference, and “piped” all our output to it. Now we want to extract the accumulated string from the object; but the member function
str() that would do this for us is not defined for
ostream, only for
ostringstream. So we cast our ostream reference back to the correct type…
…and extract the string.
Nikos Athanasiou on StackOverflow benchmarked this construct in comparison to the more traditional
Stringify( T const & value ) template function (also using
lexical_cast<>, and C++11
lexical_cast<string>() ... 125 to_string() .............. 250 SSTR .................... 1003 Stringify() ............. 1229
int i = 42; std::string s1 = SSTR( i ); std::string s2 = SSTR( "Value of i is: " << i ); std::string s3 = SSTR( i << " is the answer to the universe, life, and everything." );