2013-04-21 103 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