I have a class similar to boost::any, in that it is a templated container class. I'd like to have a method to write the contained value to a string. However, if the contained type doesn't provide a stream insertion operator, I'd like my method to return some default tring rather than failing to compile. Below is as close as I've come, and should make it clear as to what I'm trying to do:
namespace W {
namespace hide {
template <typename T>
std::ostream& operator<<(std::ostream& out, const T& t) {
return std::operator<<(out, typeid(T).name());
}
}
template <typename T> struct C {
T t_;
std::string ToString() const {
using namespace hide;
std::ostringstream oss;
oss << t_;
return oss.str();
}
};
}
This works pretty well, with some caveats. For example, if I want to actually provide an overloaded insertion operator for a class, then that operator has to either be in the same namespace as the class, or it has to be in the W namespace for it to be considered.
It also has problems with any type that already has a non-member std::operator<<, e.g. char and std::string. If T is one of those types, then the oss << t_
line above becomes ambiguous. This can be worked around by adding overloads for these types inside the W namespace, for example:
std::ostream& operator << (std::ostream& out, const std::string& s) {
return std::operator <<(out, s);
}
My question is, has anyone found a better method than this? Why do I have to add my own overloads for things like std::string? Is this all supported according to the standard, or am I taking advantage of non-standard behavior? (I am testing with g++ 4.3.3)