Is there a C++ Standard Template Library class that provides efficient string concatenation functionality, similar to C#\'s StringBuilder or Java\'s StringBuffer?
A convenient string builder for c++
Like many people answered before, std::stringstream is the method of choice. It works good and has a lot of conversion and formatting options. IMO it has one pretty inconvenient flaw though: You can not use it as a one liner or as an expression. You always have to write:
std::stringstream ss;
ss << "my data " << 42;
std::string myString( ss.str() );
which is pretty annoying, especially when you want to initialize strings in the constructor.
The reason is, that a) std::stringstream has no conversion operator to std::string and b) the operator << ()'s of the stringstream don't return a stringstream reference, but a std::ostream reference instead - which can not be further computed as a string stream.
The solution is to override std::stringstream and to give it better matching operators:
namespace NsStringBuilder {
template class basic_stringstream : public std::basic_stringstream
{
public:
basic_stringstream() {}
operator const std::basic_string () const { return std::basic_stringstream::str(); }
basic_stringstream& operator<< (bool _val) { std::basic_stringstream::operator << (_val); return *this; }
basic_stringstream& operator<< (char _val) { std::basic_stringstream::operator << (_val); return *this; }
basic_stringstream& operator<< (signed char _val) { std::basic_stringstream::operator << (_val); return *this; }
basic_stringstream& operator<< (unsigned char _val) { std::basic_stringstream::operator << (_val); return *this; }
basic_stringstream& operator<< (short _val) { std::basic_stringstream::operator << (_val); return *this; }
basic_stringstream& operator<< (unsigned short _val) { std::basic_stringstream::operator << (_val); return *this; }
basic_stringstream& operator<< (int _val) { std::basic_stringstream::operator << (_val); return *this; }
basic_stringstream& operator<< (unsigned int _val) { std::basic_stringstream::operator << (_val); return *this; }
basic_stringstream& operator<< (long _val) { std::basic_stringstream::operator << (_val); return *this; }
basic_stringstream& operator<< (unsigned long _val) { std::basic_stringstream::operator << (_val); return *this; }
basic_stringstream& operator<< (long long _val) { std::basic_stringstream::operator << (_val); return *this; }
basic_stringstream& operator<< (unsigned long long _val) { std::basic_stringstream::operator << (_val); return *this; }
basic_stringstream& operator<< (float _val) { std::basic_stringstream::operator << (_val); return *this; }
basic_stringstream& operator<< (double _val) { std::basic_stringstream::operator << (_val); return *this; }
basic_stringstream& operator<< (long double _val) { std::basic_stringstream::operator << (_val); return *this; }
basic_stringstream& operator<< (void* _val) { std::basic_stringstream::operator << (_val); return *this; }
basic_stringstream& operator<< (std::streambuf* _val) { std::basic_stringstream::operator << (_val); return *this; }
basic_stringstream& operator<< (std::ostream& (*_val)(std::ostream&)) { std::basic_stringstream::operator << (_val); return *this; }
basic_stringstream& operator<< (std::ios& (*_val)(std::ios&)) { std::basic_stringstream::operator << (_val); return *this; }
basic_stringstream& operator<< (std::ios_base& (*_val)(std::ios_base&)){ std::basic_stringstream::operator << (_val); return *this; }
basic_stringstream& operator<< (const T* _val) { return static_cast&>(std::operator << (*this,_val)); }
basic_stringstream& operator<< (const std::basic_string& _val) { return static_cast&>(std::operator << (*this,_val.c_str())); }
};
typedef basic_stringstream stringstream;
typedef basic_stringstream wstringstream;
}
With this, you can write things like
std::string myString( NsStringBuilder::stringstream() << "my data " << 42 )
even in the constructor.
I have to confess I didn't measure the performance, since I have not used it in an environment which makes heavy use of string building yet, but I assume it won't be much worse than std::stringstream, since everything is done via references (except the conversion to string, but thats a copy operation in std::stringstream as well)