Move the string out of a std::ostringstream
std::ostringstream
offers no public interface to access its in-memory buffer unless it non-portably supports pubsetbuf
(but even then your buffer is fixed-size, see cppreference example)
If you want to torture some string streams, you could access the buffer using the protected interface:
#include <iostream>
#include <sstream>
#include <vector>
struct my_stringbuf : std::stringbuf {
const char* my_str() const { return pbase(); } // pptr might be useful too
};
int main()
{
std::vector<float> v = {1.1, -3.4, 1/7.0};
my_stringbuf buf;
std::ostream ss(&buf);
for(unsigned int i=0; i < v.size(); ++i)
ss << v[i] << ' ';
ss << std::ends;
std::cout << buf.my_str() << '\n';
}
The standard C++ way of directly accessing an auto-resizing output stream buffer is offered by std::ostrstream
, deprecated in C++98, but still standard C++14 and counting.
#include <iostream>
#include <strstream>
#include <vector>
int main()
{
std::vector<float> v = {1.1, -3.4, 1/7.0};
std::ostrstream ss;
for(unsigned int i=0; i < v.size(); ++i)
ss << v[i] << ' ';
ss << std::ends;
const char* buffer = ss.str(); // direct access!
std::cout << buffer << '\n';
ss.freeze(false); // abomination
}
However, I think the cleanest (and the fastest) solution is boost.karma
#include <iostream>
#include <string>
#include <vector>
#include <boost/spirit/include/karma.hpp>
namespace karma = boost::spirit::karma;
int main()
{
std::vector<float> v = {1.1, -3.4, 1/7.0};
std::string s;
karma::generate(back_inserter(s), karma::double_ % ' ', v);
std::cout << s << '\n'; // here's your string
}
How to move std::ostringstream's underlying string object?
The standard says that std::ostringstream::str()
returns a copy.
One way to avoid this copy is to implement another std::streambuf
derived-class that exposes the string buffer directly. Boost.IOStreams makes this pretty trivial:
#include <boost/iostreams/stream_buffer.hpp>
#include <iostream>
#include <string>
namespace io = boost::iostreams;
struct StringSink
{
std::string string;
using char_type = char;
using category = io::sink_tag;
std::streamsize write(char const* s, std::streamsize n) {
string.append(s, n);
return n;
}
};
template<typename T>
std::string ToString(T const& obj) {
io::stream_buffer<StringSink> buffer{{}};
std::ostream stream(&buffer);
stream << obj;
stream.flush();
return std::move(buffer->string); // <--- Access the string buffer directly here and move it.
}
int main() {
std::cout << ToString(3.14) << '\n';
}
Is there a way to std::move std::string into std::stringstream
Since C++20 you can move a string
into a stringstream
: cppreference
Old answer for pre-C++20:
I do not see a
std::stringstream
constructor accepting rvalue reference ofstd::string
That's right. Even the str
setter doesn't utilize move semantics, so moving a string into stringstream
is not supported (not in the current standard, but hopefully in the next one).
Is it legal to move the .str() member of a stringstream?
std::ostream::str
indeed returns a copy of the internal string. So the move is legal, but it makes no sense as result.str()
is an rvalue anyway and thus the std::move
does nothing useful. If anything, it hinders RVO, so don't do it. (As @TartanLlama correctly pointed out in their comment, "Don't move the return value" holds true in general, not just when returning rvalues.)
In particular, the std::move
does not affect the internal string object of the stream.
Move or swap a stringstream
This is a missing feature on GCC : see bug 54316 , it has been fixed (you can thank Jonathan Wakely) for the next versions (gcc 5)
Clang with libc++ compiles this code :
int main () {
std::stringstream stream("1234");
std::stringstream stream2 = std::move(std::stringstream("5678"));
return 0;
}
Live demo
And it also compiles the example with std::stringstream::swap
Redirect from a std::ostringstream to another std::ostringstream
You can reassign the associated buffers:
os2.rdbuf(os1.rdbuf());
That effectively aliases the ostream.
In fact, you can even construct ostream
directly from a streambuffer pointer IIRC
Similarly, you can append the whole buffer to another stream without reassigning:
std::cout << mystringstream.rdbuf(); // prints the stringstream to console
remove char from stringstream and append some data
You can extract the string (with the str()
member), remove the last char with std::string::erase
and then reset the new string as buffer to the std::ostringstream
.
However, a better solution would be to not insert the superfluous ','
in the first place, by doing something like that :
std::ostringstream douCoh;
const char* separator = "";
douCoh << '{';
for (size_t i = 0; i < dataSize; ++ i)
{
if (v[i].test)
{
douCoh << separator << i + 1;
separator = ",";
}
}
douCoh << '}';
How do I convert from stringstream to string in C++?
yourStringStream.str()
Related Topics
Modifying Reference Member from Const Member Function in C++
When to Mark a Function in C++ as a Virtual
How to Get Content of Web-Page
Qt Undefined Reference to Vtable
How to Call a Constructor on an Already Allocated Memory
Undefined Symbols in Crypto++/iOS 64-Bit Project
What Is the Overhead Cost of an Empty Vector
How to Wait for Vsync in Xlib App
Can Virtual Functions Be Constexpr
What Is The Linux Equivalent Of: Multibytetowidechar & Widechartomultibyte
Do You Prefer Explicit Namespaces or 'Using' in C++
Is Gcc Considering Builtins of Non-Constant Expression Functions to Be Constant Expressions
Why Does My Program Run Way Faster When I Enable Profiling