我正在实现一个使用流运算符的日志记录类。基本思想是自定义类型可以实现一个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
is-a ostringstream
is-a basic_ostringstream
is-a basic_ostream
。有任何想法吗?
另外:有没有办法直接提供operator<<
重载log_stream&
而不是提供重载std::ostream
(如果需要两个不同的日志重载 - 与 - 一起使用log_stream
- 例如序列化到磁盘 - 与 - 一起使用fstream
)?
编辑#1
如果添加“r 值能力” 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
好吧,它当然应该调用 member 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";
不漂亮,但有点。有更好(更漂亮)的想法吗?