I would like to implement a stringstream object which represents a stringstream of a certain type .
For instance,
class ohtmlstringstream : public std::ostringstream {
};
ohtmlstringstream& operator <<(ohtmlstringstream& ohss, double d) {
ohss << "<div title='double'>" << d << "</div>";
return ohss;
}
Sadly this does not work, and any ohtmlstringstream
object I create which I <<
a double into just runs std::ostream& operator <<(std::ostream&, double)
.
What's the way to do this? Looks like I should not be inheriting ostringstream.
I really just want a clean and simple way to "fork" the ways that a particular type can be serialized. For a long time I had only ever wanted to serialize a type in a single way, but now I want to build string representations of my types for at least 3 cases: In a HTML (or XML) representation, in JSON, and in the way that I already do which is something basic for dumping into the terminal while debugging.
Setting aside the general wisdom of deriving from std::ostringstream
, perhaps a global
template<typename T>
ohtmlstringstream & operator <<(ohtmlstringstream& ohss, T const & t)
in the following vein would do for you:
#include <sstream>
#include <iostream>
#include <typeinfo>
using namespace std;
class ohtmlstringstream : public ostringstream {};
template<typename T>
ohtmlstringstream & operator <<(ohtmlstringstream& ohss, T const & t)
{
static_cast<ostringstream &>(ohss)
<< "<div title='"
<< typeid(T).name() // For the sake of illustration
<< "'>"
<< t <<
"</div>\n";
return ohss;
}
// Testing ...
int main()
{
ohtmlstringstream ohtml;
ohtml << string("Testing")
<< '1' << 2 << 3.0f << "4" << endl << "Bye" << endl;
cout << ohtml.str() << endl;
return 0;
}
Output:
<div title='Ss'>Testing</div>
<div title='c'>1</div>
<div title='i'>2</div>
<div title='f'>3</div>
<div title='A2_c'>4</div>
Bye
typeid(T).name()
is doubtless not a satisfactory descriptor of T
. You might replace it with custom of specializations of, say:
template<typename T>
std::string type_desc(T const &)
{
return typeid(T).name();
}
for all T
you require (resigning yourself to this much drudgery).
Note that inserting a manipulator (eg std::endl
) terminates the "html-ization", because the insertion returns a reference to the base std::ostream
.
If you don't want this to happen, you would probably want the manipulator merely to be noted, but not acted upon, in the html output. So you might add the specialization:
inline ohtmlstringstream &
operator <<(ohtmlstringstream& ohss, ostream & (*pf)(ostream &))
{
static_cast<ostringstream &>(ohss)
<< "<div title='"
<< typeid(pf).name()
<< "'>"
"</div>\n";
return ohss;
}
With this addition the output becomes:
<div title='Ss'>Testing</div>
<div title='c'>1</div>
<div title='i'>2</div>
<div title='f'>3</div>
<div title='A2_c'>4</div>
<div title='PFRSoS_E'></div>
<div title='A4_c'>Bye</div>
<div title='PFRSoS_E'></div>
(Built with gcc 4.8.2 and clang 3.3)
If you are only interested in the numeric types, you could use a custom std::num_put<...>
facet to format the values. However, other types generally do not let you intercept the processing.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.