顯而易見的解決方案是在中使用。但是給定的 代碼仍然不起作用。 (你的例子將編譯,但它不會做你認爲應該做的 )。表達式std::ostringstream()
是一個臨時的 ,你不能初始化一個臨時的非const引用, 和std::operator<<(std::ostream&, char const*)
的第一個參數 是一個非const引用。 (您可以撥打 暫時撥打會員功能,如std::ostream::operator<<(void const*)
。所以代碼 將編譯,但它不會做你的期望。
可以解決此問題,使用類似:
foo(std::ostringstream().flush() << "number = " << 500);
std::ostream::flush()
返回非const引用,所以沒有 進一步的問題。而在新創建的流上,這是一個無操作。 不過,我認爲你會同意它不是最優雅或直觀的 解決方案。
我通常在這種情況下,要做的就是創建一個包裝類,其中 包含它自己的std::ostringstream
,並提供了一個模板 成員operator<<
其轉發到包含 std::ostringstream
。您的功能foo
將採取const
對此—的引用,或者我所做的是直接將析構函數調用 foo
,以便客戶端代碼甚至不必擔心它 它;它是這樣的:
log() << "number = " << 500;
log()
返回包裝類的實例函數(見下文 ),這個類的(最終)析構函數調用你的函數 foo
。
這有一個小問題。返回值可能會被複制, 並在複製後立即被破壞。這將破壞我剛剛解釋的 ;實際上,由於std::ostringstream
不是 可複製的,它甚至不會編譯。這裏的解決方案是將所有的 實際邏輯,包括std::ostringstream
和 析構函數邏輯的實例調用foo
在一個單獨的實現類中,具有 公共包裝器有一個boost::shared_ptr
它,並轉發。或者 只是重新實現了一下共享指針邏輯的類:
class LogWrapper
{
std::ostringstream* collector;
int* useCount;
public:
LogWrapper()
: collector(new std::ostringstream)
, useCount(new int(1))
{
}
~LogWrapper()
{
-- *useCount;
if (*useCount == 0) {
foo(collector->str());
delete collector;
delete useCount;
}
}
template<typename T>
LogWrapper& operator<<(T const& value)
{
(*collector) << value;
return *this;
}
};
注意,很容易擴展,以支持可選的記錄;只需要 爲LogWrapper提供了一個構造函數,它將collector
設置爲 NULL
,並在operator<<
中對此進行測試。
編輯:其他
一件事發生在我:你可能會想檢查 析構函數是否被稱爲異常的結果,在這種情況下,不叫 foo
。從邏輯上講,我倒是希望你 可能得到的唯一的例外是std::bad_alloc
,但總是會有誰 寫類似用戶:
log() << a + b;
其中+
是拋出一個用戶定義的過載。
'foo'確實需要'ostream'嗎?或者,如果它需要'stringstream&'或者可能是一個'std :: string const&quot;它會被接受嗎? –
讓它在一行中工作我相信它的確如此 – Leo
難道你不能爲此創建一個宏,因爲它是C++嗎?那麼你會有'foo(MACRO_NAME(「number =」<< 500))''。 – hochl