Table of Contents

SSTR()

Note: The C++11 construct std::to_string( x ) is more efficient than this. See end of article for perfomance comparisons.

Preface

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 << "\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:

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 ) 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 operator«().

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.

Performance

​Nikos Athanasiou on StackOverflow benchmarked this construct in comparison to the more traditional Stringify( T const & value ) template function (also using std::stringstream), Boost lexical_cast<>, and C++11 to_string():

lexical_cast<string>() ... 125
to_string() .............. 250
SSTR .................... 1003
Stringify() ............. 1229

Usage

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." );