2013-04-21 102 views
2

我正在实现一个使用流操作符的日志记录类。基本思想是自定义类型可以实现一个operator<<为记录提供可读的表示。日志记录类将收集各种消息并将它们(作为单个日志记录条目)转发(销毁到系统日志或其他)。运算符<<超载(只)为std :: stringstream dervied类

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是-a ostringstream is-a basic_ostringstream is-a basic_ostream。有任何想法吗?

此外:是否有任何方式为log_stream&而不是直接提供operator<<重载std::ostream(如果一个人想用于记录两种不同的过载 - 与log_stream使用 - 和例如序列化的盘 - 与fstream使用) ?

EDIT#1

如果 '能够r值' operator<<被添加的第一个问题就解决了。

template <typename Type> inline log_stream &operator<<(log_stream &&stream, Type&& type) 
{ 
    return operator<<(stream, std::forward<Type>(type)); 
} 

然而现在/静止的类型转换为基类分解(无论是ostringstreamostream)。

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(哎呀)工作。

想到的一个解决方案是提供一个“r值给l值换算操作符”,其最短形式为operator()

class log_stream 
{ 
    inline log_stream &()() 
    { 
     return *this; 
    } 
} 

log_stream()() << custom_type() << "text"; 

不漂亮,但有些东西。任何更好(更漂亮)的想法?

+0

您应该从'streambuf'派生,而不是流类型。阅读http://gabisoft.free.fr/articles/fltrsbf1.html – aschepler 2013-04-21 13:44:59

+1

这对实际问题没有影响。 – 2013-04-21 14:59:35

+0

广告附加(编辑)问题:stream << type'的返回类型是'basic_ostream',所以你需要执行一个'static_cast'回到你的派生类型。例如:'return static_cast (stream << std :: forward (type));' – dyp 2013-04-21 17:58:37

回答

2

您的日志流是临时,而插入操作符需要非常量引用。你不能将前者转换为后者。

您必须引入log_stream类型的实际命名变量,并将其用作<<的左操作数。

+0

为什么它应该是一个常量引用?临时文件有效且可修改,直到分号为止。然而,问题的确是它是一个r值(而运算符<<过载需要一个l值)。但是我不*想要给它一个名字,因为它不会被破坏,直到它超出范围。 – 2013-04-21 14:55:35

+0

@ T.Carter:临时(右值)确实可以修改,您可以调用非const成员函数。尽管如此,你不能将它转换为非const引用,因为标准是这样说的。这就是人生。 – 2013-04-21 15:00:44

+0

好的。请在初始文章中查看**编辑#1 **。 – 2013-04-21 17:46:06