我正在实现一个使用流操作符的日志类。基本思想是,自定义类型可以实现一个operator<<
,为日志记录提供可读的表示形式。日志类将"收集"各种消息,并在销毁时将它们作为单个日志条目转发(到syslog或其他)。
class log_stream : public std::ostringstream
{
inline ~log_stream()
{
forward_to_log(str().c_str());
}
};
class custom_type
{
};
std::ostream &operator<<(std::ostream &stream, const custom_type &)
{
stream << "<custom_type data>";
return stream;
}
log_stream() << "error in custom type: " << custom_type_variable;
除了语句不是从std::ostream的重载开始而是直接使用自定义类型之外,这实际上工作得很好:
log_stream() << custom_type_variable; // no known conversion from 'log_stream'
// to 'basic_ostream<char, ...>&
// for 1st argument
现在我想知道为什么,因为log_stream
是- ostringstream
是- basic_ostringstream
是- basic_ostream
。什么好主意吗?
另外:有没有办法直接为log_stream&
而不是std::ostream
提供operator<<
过载(如果有人想要两个不同的日志过载-与log_stream
一起使用-例如序列化到磁盘-与fstream
一起使用)?
编辑# 1
如果添加一个'r-value capable'的operator<<
,第一个问题就解决了。
template <typename Type> inline log_stream &operator<<(log_stream &&stream, Type&& type)
{
return operator<<(stream, std::forward<Type>(type));
}
然而,它现在/仍然在类型转换到基类(ostringstream
或ostream
)。
log_stream() << custom_type(); // OK
log_stream() << custom_type() << "text"; // OK
log_stream() << "next"; // non-const lvalue reference to type 'log_stream' cannot bind
// to a value of unrelated type 'basic_ostream<char, ...>'
为什么basic_ostream<char, ...>
类型无关?它是一个log_stream
的基类,它应该可以在这里得到对这个基类的引用,不是吗?
编辑# 2
当然,它应该调用成员operator<<
,这样它就可以工作了。
template <typename Type> inline log_stream &operator<<(log_stream &&stream, Type&& type)
{
stream << std::forward<Type>(type);
return stream;
}
所以这个问题在c++ 11中已经解决了,但是在c++ 03 (argh)中仍然不起作用。
我想到的一个解决方案是提供一个'r值到l值转换运算符',以其最短的形式operator()
。
class log_stream
{
inline log_stream &()()
{
return *this;
}
}
log_stream()() << custom_type() << "text";
不漂亮,但也不错。有更好(更漂亮)的主意吗?
您的日志流是一个临时,而插入操作符需要一个非const引用。不能将前者转换为后者。
必须引入log_stream
类型的实际命名变量,并将其用作<<
的左操作数。