How to use an ostringstream in just an expression - c++

I use std::ostringstream for formatting strings, which inherits its << operators from ostream, and consequently they return an ostream and not an ostringstream, which means that I can't call ostringstream::str on the result. This usually isn't a problem, since I can typically do this:
ostringstream stream;
stream << whatever;
string str = stream.str();
But occasionally I need* to use it in just a single expression, which is more difficult. I could do
string str = ((ostringstream&) (ostringstream() << whatever)).str();
but bad things will happen if that << overload returns some ostream that isn't an ostringstream. The only other thing I can think to do is something like
string str = ([&] () -> string {ostringstream stream; stream << whatever; return stream.str();})();
but this can't possibly be efficient, and is certainly very bad c++ code.
*Okay, I don't need to, but it would be a lot more convenient to.

Using
string str = ([&] () -> string
{
ostringstream stream;
stream << whatever;
return stream.str();
})();
is ok. However, I think it will be better to name that operation, create a function with that name, and call the function.
namespace MyApp
{
template <typename T>
std::string to_string(T const& t)
{
ostringstream stream;
stream << t;
return stream.str();
}
}
and then use
string str = MyApp::to_string(whatever);

The only other thing I can think to do is something like
string str = ([&] () -> string {ostringstream stream; stream << whatever; return stream.str();})();
but this can't possibly be efficient, and is certainly very bad c++
code.
Actually, no. Once the optimizer has a look at this, it's exactly as fast as the original code. And it's not "very bad c++ code". It's known as an Immediately Invoked Lambda Expression, or IILE. It's an idiom, and actually quite decent practice.
It would be better formatted more like this, though:
// One of the benefits of IILEs is that `const` can be used more frequently
string const str = [&] {
ostringstream stream;
stream << whatever;
return stream.str();
}();
Some people prefer using std::invoke to invoke the lambda instead:
string const str = std::invoke([&] {
ostringstream stream;
stream << whatever;
return stream.str();
});

Assuming you got
std::string get_str(std::ostream& out) {
retrun static_cast<std::stringbuf*>(out.rdbuf())->str();
}
You could use
std:: string s = get_str(std::ostringstream{} << ...);

Related

How to overload an in-place and a copying string manipulation functions?

I would like to be able to do the following:
std::cout << str_manip("string to manipulate");
as well as
std::string str;
str_manip(str);
std::cout << str;
For this, I have two functions
#include <string>
// copying
std::string str_manip(std::string str)
{
// manipulate str
return str;
}
// in-place
void str_manip(std::string& str)
{
// manipulate str
}
but they produce the following error:
error: call of overloaded 'str_manip(std::__cxx11::string&)' is ambiguous
How can I overcome this?
The problem is with this call:
std::string str;
str_manip(str);
std::cout << str;
The compiler doesn't know which version of str_manip to call.
You can change your functions to look like this:
#include <string>
// copying
std::string str_manip(const std::string& str)
{
std::string dup = str;
// manipulate dup
return dup;
}
// in-place
void str_manip(std::string& str)
{
// manipulate str
}
Now, the compiler knows that the ambiguous call has to be the function that takes the non-const parameter. You can also be sure that your call that returns a std::string to the << operator isn't modifying your string.
This might be not the thing you are looking for, but for your code
std::cout << str_manip("string to manipulate");
the parameter to str_manip is not a string but const char* (actually an array, but convertible to a char pointer). You can overload based on that.
std::string str_manip(const char* s)
{
std::string str(s); // create str
// manipulate str
return str;
}
However, let's look at the big picture. When you see str_manip in your code, does this mean "change the string" or "make a new string based on the given string"? Do you want to be intentionally ambivalent on the real meaning?
Consider yourself reading your code in 1 year in future. What will you think when you see a call to str_manip - does this mutate its parameter? Does the answer to the previous question depend on context?
The goal in writing code is to make it clear, especially in a multi-paradigm language like C++. So, in my opinion, just don't do overloading that you are thinking about. Instead, make 2 distinct names, like
void frobnicate_str(std::string&) {...}
std::string get_frobnicated_str(std::string) {...}

calling enum << operator for string composition

Suppose we have enum with implemented operator<< converting enum value to string. Is it possible to call this operator during string construction or something similar? My current approach uses std::stringstream calling << on enum and extracting string from std::stringstream. Is there any other way? Using std::cout << is not an option.
Example code:
enum class Status {
OK,
ERROR
}
::std::ostream& operator<<(::std::ostream& os, Status status)
{
switch (status) {
case Status::OK:
return os << "OK";
case Status::ERROR:
return os << "ERROR";
}
Usage:
Status s = Status::OK;
std::stringstream stream;
stream << s;
std::string statusString = s.str().c_str();
Unfortunately, here is no any elegant solution as you want.
If we only could, we might use a user defined conversion but it needs to be a non-static member function which is impossible with enums.
But you may always use argument-dependent lookup like you do with your operator<<.
Or if you want string, make a map and put desired string-equivalent there.

Can a temporary stringstream object be used?

This works:
stringstream temp;
temp << i;
result_stream << transform(temp.str());
(transform is a function that takes a string and returns a string; i is an int). However, my attempt to let C++11 create a temporary object without a name didn't work:
result_stream << transform((stringstream() << i).str());
I thought it would work, since the second << should just return the first argument and I'd be able to use str() on that. But I get this error:
error: 'class std::basic_ostream<char>' has no member named 'str'
I'm using g++ 4.8.1 (MinGW-W64).
Is there a way to accomplish this (i.e. write code like this using an unnamed temporary)? (The above code is a bit simplified, and the actual code involves using << on arguments other than int.)
This doesn't work because the second << is std::ostream &operator<<(std::ostream &, int); and so the return type is ostream& which has no member str().
You would have to write:
result_stream << transform( static_cast<stringstream &>(stringstream() << i).str() );
Update (2019): According to LWG 1203 the standard may be changed in future (and one major implementation already has) so that this code no longer works, and a simpler code works instead. See this question for detail.
In the interim period, apparently the following works on both old and new:
result_stream << transform( static_cast<stringstream &>(stringstream().flush() << i).str() );
// ^^^^^^^^
This should not be a performance penalty since flushing an empty stream has no effect...
operator<<() returns a reference to the base class std::ostream contained within the std::stringstream. The base class doesn't contain the str() method. You can cast it back down to a std::stringstream&:
result_stream << transform(static_cast<std::stringstream&>(std::stringstream() << i).str());
The result of the << operator on the temporary stringstream is an ostream. There is no str() method on an ostream.
Use to_string instead:
using std::to_string;
result_stream << transform(to_string(i));
You can define a helper to_string to handle objects not covered by std::to_string.
template <typename T>
std::string to_string (const T &t) {
std::ostringstream oss;
oss << t;
return oss.str();
}
For example, if you had a class Foo that understood redirection to an ostream, and f was an instance of Foo, then you could do:
result_stream << transform(to_string(f));
Try it online!
If you actually want to use a lot of redirection to build up a string before transforming, you could create a helper object for that as well.
struct to_string_stream {
std::ostringstream oss;
template <typename T>
auto & operator << (const T &t) { oss << t; return *this; }
operator std::string () const { return oss.str(); }
void clear () { oss.string(std::string()); }
};
Then, you could do something like:
to_string_stream tss;
result_stream << transform(tss << i << ':' << f);
Try it online!
Tried and failed to do this for C++11 (in 2009):
http://cplusplus.github.io/LWG/lwg-active.html#1203
libc++ went outlaw and implemented it anyway.
It is up for reconsideration, but can not possibly be standardized prior to 2017 (standardization is a glacial process).

Using streams to convert objects to strings

I have an object that overrides the stream operator << to act as a stringstream to make console printing easy.
cout << obj << endl;
I want to test this functionality in a unit test by comparing the string output with an expected string. I currently accomplish this by:
stringStream ss;
ss << obj;
string objStr = ss.str();
EXPECT_EQ(objStr, "expected string output");
This is not particular readable and it is certainly not succinct. Is there any easier, shorter and simpler way to get the string representation of an obj?
You could write a small, generic utility function that does that thing for you:
#include <utility>
#include <string>
#include <sstream>
template<typename T>
std::string make_string(T const& o)
{
std::stringstream ss;
ss << o;
return ss.str();
}
And use it this way:
EXPECTED_EQ(make_string(obj), "expected string output");

c++ stringstream to ostream to string

I would like to be able to do:
foo(stringstream()<<"number = " << 500);
EDIT: single line solution is crucial since this is for logging purposes. These will be all around the code.
inside foo will print the string to screen or something of the sort.
now since stringstream's operator<< returns ostream&, foo's signature must be:
foo(ostream& o);
but how can I convert ostream& to string? (or char*).
Different approaches to achieving this use case are welcome as well.
The obvious solution is to use dynamic_cast in foo. But the given
code still won't work. (Your example will compile, but it won't do what
you think it should.) The expression std::ostringstream() is a
temporary, you can't initialize a non-const reference with a temporary,
and the first argument of std::operator<<( std::ostream&, char const*)
is a non-const reference. (You can call a member function on a
temporary. Like std::ostream::operator<<( void const* ). So the code
will compile, but it won't do what you expect.
You can work around this problem, using something like:
foo( std::ostringstream().flush() << "number = " << 500 );
std::ostream::flush() returns a non-const reference, so there are no
further problems. And on a freshly created stream, it is a no-op.
Still, I think you'll agree that it isn't the most elegant or intuitive
solution.
What I usually do in such cases is create a wrapper class, which
contains it's own std::ostringstream, and provides a templated
member operator<< which forwards to the contained
std::ostringstream. Your function foo would take a const
reference to this—or what I offen do is have the destructor call
foo directly, so that the client code doesn't even have to worry about
it; it does something like:
log() << "number = " << 500;
The function log() returns an instance of the wrapper class (but see
below), and the (final) destructor of this class calls your function
foo.
There is one slight problem with this. The return value may be copied,
and destructed immediately after the copy. Which will wreck havoc with
what I just explained; in fact, since std::ostringstream isn't
copyable, it won't even compile. The solution here is to put all of the
actual logic, including the instance of std::ostringstream and the
destructor logic calling foo in a separate implementation class, have
the public wrapper have a boost::shared_ptr to it, and forward. Or
just reimplement a bit of the shared pointer logic in your class:
class LogWrapper
{
std::ostringstream* collector;
int* useCount;
public:
LogWrapper()
: collector(new std::ostringstream)
, useCount(new int(1))
{
}
~LogWrapper()
{
-- *useCount;
if ( *useCount == 0 ) {
foo( collector->str() );
delete collector;
delete useCount;
}
}
template<typename T>
LogWrapper& operator<<( T const& value )
{
(*collector) << value;
return *this;
}
};
Note that it's easy to extend this to support optional logging; just
provide a constructor for the LogWrapper which sets collector to
NULL, and test for this in the operator<<.
EDITED:
One other thing occurs to me: you'll probably want to check whether the
destructor is being called as a result of an exception, and not call
foo in that case. Logically, I'd hope that the only exception you
might get is std::bad_alloc, but there will always be a user who
writes something like:
log() << a + b;
where the + is a user defined overload which throws.
I would suggest you to use this utility struct:
struct stringbuilder
{
std::stringstream ss;
template<typename T>
stringbuilder & operator << (const T &data)
{
ss << data;
return *this;
}
operator std::string() { return ss.str(); }
};
And use it as:
void f(const std::string & s );
int main()
{
char const *const pc = "hello";
f(stringbuilder() << '{' << pc << '}' );
//this is my most favorite line
std::string s = stringbuilder() << 25 << " is greater than " << 5 ;
}
Demo (with few more example) : http://ideone.com/J995r
More on my blog : Create string on the fly just in one line
You could use a proxy object for this; this is a bit of framework, but if you want to use this notation in a lot of places then it may be worth it:
#include <iostream>
#include <sstream>
static void foo( std::string const &s )
{
std::cout << s << std::endl;
}
struct StreamProxy
{
std::stringstream stream;
operator std::string() { return stream.str(); }
};
template <typename T>
StreamProxy &operator<<( StreamProxy &s, T v )
{
s.stream << v;
return s;
}
static StreamProxy make_stream()
{
return StreamProxy();
}
int main()
{
foo( make_stream() << "number = " << 500 );
}
This program prints
number = 500
The idea is to have a little wrapper class which can be implicitely converted into a std::string. The << operator is simply forwarded to the contained std::stringstream. The make_stream() function is strictly speaking not necessary (you could also say StreamProxy(), but I thought it looks a bit nicer.
A couple of options other than the nice proxy solution just presented by Frerich Raabe:
Define a static string stream variable in the header that defines the logging function and use the comma operator in your invocation of the logging function so that this variable is passed rather than the ostream& returned by the stream insertion operator. You can use a logging macro to hide this ugliness. The problem with this solution is that it is a bit on the ugly side, but this is a commonly used approach to logging.
Don't use C++ I/O. Use a varargs C-style solution instead. Pass a format string as the first argument, with the remaining arguments being targets for that format string. A problem with this solution is that even if your compiler is smart enough to ensure that printf and its cousins are safe, the compiler probably won't know that this new function is a part of the printf family. Nonetheless, this is also a commonly used approach.
If you don't mind using macros functions, you can make the logging function accept const string&, and use the following macro
#define build_string(expr) \
(static_cast<ostringstream*>(&(ostringstream().flush() << expr))->str())
And suppose you foo has signature void foo(const string&), you only need the one-liner
foo(build_string("number = " << 500))
This was inspired by James Kanze's answer about static_cast and stringstream.flush. Without the .flush() the above method fails with unexpected output.
Please note that this method should not leak memory, as temporary values, whether in the pointer form or not, are still allocated on the stack and hence destroyed upon return.
Since you're converting to string anyways, why not
void foo(const std::string& s)
{
std::cout << "foo: " << s << std::endl;
}
...
std::stringstream ss;
ss << "number = " << 500;
foo(ss.str());
This is not possible. As the name ostream implies, it is used for output, for writing to it. You could change the parameter to stringstream&. This class has the method str() which returns a std::string for your use.
EDIT I did not read the issue with operator << returning ostream&. So I guess you cannot simply write your statements within the functions argument list but have to write it before.
You can create a small wrapper around std::ostringstream that will convert back to std::string on use, and have the function take a std::string const &. The first approach to this solution can be found in this answer to a different question.
On top of that, you can add support for manipulators (std::hex) if needed.