這不是C++ 11,這是C++ 03提高自己的執行追加前綴和後綴的流
問題
我有一個叫decorator
類應該是能夠將文本添加到用戶通過operator<<
傳遞給它的消息的兩端。
例如:
decorator dec(
"-> ", // prefix
"\n" // suffix
);
dec << "the value is: " << 33;
這應該輸出:-> the value is 33\n
我的實現
dec << "the value is"
當該代碼被處理,proxy operator<<(decorater & dec , const T & msg)
被調用,decorater添加前綴,trea t消息並返回一個臨時代理對象。這個臨時對象將負責處理鏈條的其餘部分。
temporary_proxy_object << 33
現在處理此代碼,臨時對象通過代理operator<<(const proxy &, const T &)
處理整數。它還記錄了它已被operator<<
唆使的事實。最後它返回一個臨時對象,它是它自己的副本。
由於沒有其他消息要處理,所以最後一個臨時對象單獨死亡。由於它沒有被operator<<
索引,所以它調用一個成員函數decorater
來讓它知道它是最後一個對象,裝飾者愉快地追加後綴。
我痛心
我最討厭這個實現是它依賴於編譯器的優化:
proxy operator(const proxy & p, const T & msg)
{
// some work here
return proxy(p);
}
沒有什麼能阻止從創建兩個臨時代理對象的編譯器,第一個在函數中,第二個作爲返回的臨時。如果是這樣的話,那麼我的實現將被搞砸,因爲第一個臨時對象不會被請求。
源代碼
#include <string>
#include <sstream>
#include <iostream>
class decorater;
class proxy
{
public:
proxy(const decorater & creator),
proxy(const proxy & other);
void solicitate() const
{
m_solicitated = true;
}
~proxy();
const decorater & getDecorater() const;
private:
mutable bool m_solicitated;
const decorater & m_creator;
};
class decorater
{
public:
decorater(const std::string & prefix, const std::string & suffix)
:m_ostr()
,m_prefix(prefix)
,m_suffix(suffix)
{
}
template<typename T>
proxy treat (const T & msg) const
{
m_ostr << msg;
return proxy(*this);
}
void appendPrefix() const
{
m_ostr << m_prefix;
}
void appendSuffix() const
{
m_ostr << m_suffix;
}
void print()
{
std::cout << m_ostr.str();
}
private:
mutable std::ostringstream m_ostr;
std::string m_prefix, m_suffix;
};
template <typename T>
proxy operator<<(decorater & dec , const T & msg)
{
dec.appendPrefix();
return dec.treat(msg);
}
proxy::proxy(const decorater & creator)
:m_solicitated(false)
,m_creator(creator)
{
}
proxy::proxy(const proxy & other)
:m_solicitated(false)
,m_creator(other.m_creator)
{
}
proxy::~proxy()
{
if (!m_solicitated)
getDecorater().appendSuffix();
}
const decorater & proxy::getDecorater() const
{
return m_creator;
}
template <typename T>
proxy operator<<(const proxy & p, const T & msg)
{
p.getDecorater().treat(msg);
p.solicitate();
return p;
}
int main()
{
decorater dec("-> ", "\n");
dec << "the value is: " << 33;
dec.print();
}
如果這很關注你,是否有理由使用代理對象而不是修改裝飾器狀態並通過引用返回它(iostream插入器的工作方式?)無論如何...如果你只是想創建一個代理對象,然後傳遞它,你可以使用'shared_ptr'(TR1或boost) - 複製將會很便宜,並且會在最後清理。 –
HostileFork
@HostileFork我不介意修改裝飾器狀態,實際上這是我在決定使用代理對象之前所做的。該解決方案的問題是,我無法知道鏈的最後一個元素何時被處理。換句話說,我還沒有找到一種方法來知道何時追加「後綴」部分。 – qdii