Note: This construct is mostly obsolete since C++11 made its appearance. Use std::to_string( x ) instead.
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 operator<<() syntax:
int i = 42; std::cout << "The value of i is " << i << std::endl;
Things get a bit more difficult when you want to get the result as a string (for example, as parameter to an exception constructor):
ostringstream s; s << "The value of i is " << i; 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:
The SSTR() macro
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 ) dynamic_cast< std::ostringstream & >( \ std::ostringstream() << std::dec << x ).str()
Creating an anonymous ostringstream object with which we will construct the string.
- << std::dec
Setting the integer output format to "decimal" looks like a non-op since decimal is the default anyway. However, it has the effect of turning the type of our object from ostringstream 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.
- << x
...passes the macro parameter(s) verbatim. This could be a single data value, or any number of values daisy-chained with more << operators.
- dynamic_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.
I have not profiled the construct, but a smart compiler with a sufficiently smart library implementation should be able to optimize most of the implied code away. Should someone have hard facts on this, feel free to drop me a mail (at solar@...), and I will publish them here.
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." );