Gnu Lesser General Public License, v2.1 (Included in the Code)
Somewhere on your include path, unzip stdplus_stringfmt.zip. A file should be placed into a folder called stdplus:
I have been quite frustrated by having to create a (named) temporary object of type std::stringstream just to format strings before calling a function:
std::stringstream temp; temp << [a bunch of stuff]; some_function_that_takes_a_string( temp.str() ); |
I find that this idiom makes code quite difficult to read. One approach around it would be to overload some_function_that_takes_a_string to also take a std::stringstream and call it like so:
std::stringstream temp; temp << [a bunch of stuff]; some_function_that_takes_a_string( temp ); |
This is still weak, because you have to declare temp!
So I started toying around with the idea of using an unnamed std::stringstream, like so
some_function_that_takes_a_string ( std::stringstream() << [a bunch of stuff] ); |
The problem here is that operator<< returns a std::ostream. Clearly you don't want to overload some_function_that_takes_a_string to accept a std::ostream, since other stream types wouldn't make any sense with this function. So I wrote an object called string_extractor that dynamic_cast'd the ostream back to a std::stringstream and returned its string, yielding:
some_function_that_takes_a_string
( std::stringstream() << [a bunch of stuff]
<< stdplus::string_extractor );
|
This seemed to work fine until I actually ran it. For some reason, the stream kept getting garbled up. Although I never figured out why, it forced me to rethink my approach. What I really needed was something compatible with std::string that also supported all of the operators << that std::ostream supports. Enter template magic!
If you look at the implementation of stringfmt, you'll notice that it has a templatized operator<< that takes any OTHER type and tries to use operator<< to in turn insert the other value into m_stream. It then returns a reference to itself. Because it returns a reference to stringfmt as opposed to a reference to std::ostream, when it comes time to pass the stringfmt to another function that takes a std::string, the implicit conversion via operator std::string() is considered and (hurrah!) used.
The end result is that now you can do this:
some_function_that_takes_a_string ( stdplus::stringfmt() << [a bunch of stuff] ); |
I've started integrating stringfmt around my codebase, taking out a slew of explicit references to std::stringstream and I can say that, at least in my case, it has really improved the readability of my code. In fact, I have written a similar class, AnsiStringfmt, that I am now using for functions that take Borland C++ Builder's AnsiString class.
Simply include <stdplus/stringfmt.h> in your project and enjoy.
#include <stdplus/stringfmt.h>
std::string test =
stdplus::stringfmt( )
<< "Hello There. This is kind of a pointless example, but hey, it\'s just an example!";
// Or Better:
some_function_that_takes_a_string
( stdplus::stringfmt( )
<< "Hello there. This is a string generated inline with numbers, too:" << 32
);
|
Currently none.