C++ equivalent of StringBuffer/StringBuilder?

前端 未结 10 909
说谎
说谎 2020-11-29 15:51

Is there a C++ Standard Template Library class that provides efficient string concatenation functionality, similar to C#\'s StringBuilder or Java\'s StringBuffer?

10条回答
  •  轻奢々
    轻奢々 (楼主)
    2020-11-29 16:30

    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)

提交回复
热议问题