我有一个类似于boost :: any的类,因为它是一个模板化的容器类。我想有一个方法将包含的值写入字符串。但是,如果包含的类型不提供流插入操作符,我希望我的方法返回一些默认的tring而不是无法编译。下面就像我来的那样接近,并且应该明确我要做的事情:
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();
}
};
}
这很有效,但有一些警告。例如,如果我想为一个类实际提供一个重载的插入运算符,那么该运算符必须与该类位于同一名称空间中,或者它必须位于W名称空间中才能被考虑。
任何已经拥有非成员std :: operator&lt;&lt;的类型也存在问题,例如char和std :: string。如果T是这些类型之一,则上面的oss << t_
行变得模糊不清。这可以通过在W名称空间内为这些类型添加重载来解决,例如:
std::ostream& operator << (std::ostream& out, const std::string& s) {
return std::operator <<(out, s);
}
我的问题是,有没有人找到比这更好的方法?为什么我必须为std :: string之类的东西添加自己的重载?这是根据标准支持的,还是我利用非标准行为? (我正在使用g ++ 4.3.3进行测试)
答案 0 :(得分:3)
下面是我记得在编译器构造类中看到的一些代码。我认为它特别聪明(如果不是'干净')所以我坚持下去。
来自http://www.cs.colorado.edu/~main/a++/tree.h
// If data of type T can be printed with the usual << operator, then
// print<T>(out, p) will interpret *p as a T object and print its
// value to out. Otherwise, a message is printed to out, indicating
// that objects of type T are not printable.
template<typename T> void print(std::ostream& out, const void* p)
{
// The first part of this code sets an enum value, is_printable, to
// be 1 if the data type T can be printed with the usual <<
// operator. Otherwise, is_printable is set to zero. The programming
// technique is based on a note from Herb Sutter at
// http://www.gotw.ca/gotw/071.htm
class object
{
public:
object(T convert) { };
};
char operator << (std::ostream&, const object&);
enum { is_printable = sizeof(std::cout << (*static_cast<T*>(0))) == sizeof(char) ? 0 : 1 };
// Notice that the boolean expression in the if-statement is known at
// compile time, so that only one of the two output statements will be
// compiled into object code.
if (is_printable)
out << *static_cast<const T*>(p);
else
out << "(value of type " << typeid(T).name() << " cannot be printed)";
}
构造容器对象时,按住指向变量的打印函数的指针:
void (*printer)(std::ostream&, const void*);
printer = print<T>;
然后使用printer()函数显示包含的值(如果可能)。
希望这有帮助。