I have a value-semantic class that I'd like to be "showable" in the same sense as Haskells Show
class, or Python provides a universal __str__()
function.
In c++:
operator<<(ostream&, ...)
so I can output my class to e.g. cout
operator std::string()
so my class converts to std::string
operator const char*()
so my class converts to const char *.str()
member, or a to_string(...)
free functionEach of these functions could be defined in terms of the other. Is one option better over the others? Are these all the options? What would the most elegant way be to do this given c++11/14/17?
The question is going to be put in hold in a very few minutes, but I will still share my thoughts here.
First, of all, we can remove const char* / std::string() operator overloads from the list. If the class is not a string, it should not be convertible to string, and serialization enablement does not make your class a string.
As for str()
, to_string
and operator <<
they a pretty equivalent. However, since for any complex class to_string() and str() are very likely to use ostreams internally, I believe, operator <<
is the best option.
I don't know whether it's best practice or not but...
for debugging I always define operator<<
which gives a summarised output in text form (this means it's easy to stream objects to log files)
for formatted output I would probably choose to implement this in terms of free functions: detail::x_detail_writer write_details(const X&)
and then give detail::x_detail_writer
(which is a functor) an operator<< overload
for anything but the most trivial object I implement to_string
in terms of operator<<
if at all.
for aiding with debugging output we have a helper class which goes something like this:
template<class T>
struct make_writeable {
friend std::ostream& operator<<(std::ostream& os, const T& t) {
// example prefix...
os << demangle(typeid(T).name()) << "{";
t.write(os);
// example postfix:
os << " }";
return os;
}
};
then derive some class from this and give it a member function called write:
struct X : make_writeable<X>
{
void write(std::ostream& os) const {
// write out members here. they will appear within the prefix and postfix
}
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With