「顯而易見的」解決方案是使用操縱器來安裝自定義std::num_put<char>
方面,只是根據需要格式化int
s。
上述說法雖然完全描述瞭解決方案,但可能有點神祕。以下是實際執行邏輯的代碼。第一個成分是一個特殊的std::num_put<char>
方面這只是從std::num_put<char>
派生的類,並且覆蓋了它的一個virtual
函數。使用的方面是一個過濾方面,用於查看存儲在流中的標記(使用iword()
)以確定是否應更改行爲。下面是代碼:
class num_put
: public std::num_put<char>
{
std::locale loc_;
static int index() {
static int rc(std::ios_base::xalloc());
return rc;
}
friend std::ostream& twodigits(std::ostream&);
friend std::ostream& notwodigits(std::ostream&);
public:
num_put(std::locale loc): loc_(loc) {}
iter_type do_put(iter_type to, std::ios_base& fmt,
char fill, long value) const {
if (fmt.iword(index())) {
fmt.width(2);
return std::use_facet<std::num_put<char> >(this->loc_)
.put(to, fmt, '0', value);
}
else {
return std::use_facet<std::num_put<char> >(this->loc_)
.put(to, fmt, fill, value);
}
}
};
的主要部分是do_put()
成員函數,其決定的值需要如何被格式化:如果在fmt.iword(index())
標誌是非零,它設置寬度2
並調用格式函數的填充字符爲0
。無論如何寬度將被重置,並且填充字符不會與流存儲在一起,即,不需要任何清理。
通常情況下,代碼可能會生活在一個單獨的翻譯單元中,並且它不會在頁眉中聲明。在這種情況下,頭部中真正聲明的唯一功能是twodigits()
和notwodigits()
,它們被製作爲friend
,以提供對index()
成員函數的訪問。 index()
成員函數只是在調用時間時分配一個可與std::ios_base::iword()
一起使用的索引,然後它僅返回此索引。操縱器twodigits()
和notwodigits()
主要設置此索引。如果num_put
方面沒有安裝流twodigits()
還安裝方面:
std::ostream& twodigits(std::ostream& out)
{
if (!dynamic_cast<num_put const*>(
&std::use_facet<std::num_put<char> >(out.getloc()))) {
out.imbue(std::locale(out.getloc(), new num_put(out.getloc())));
}
out.iword(num_put::index()) = true;
return out;
}
std::ostream& notwodigits(std::ostream& out)
{
out.iword(num_put::index()) = false;
return out;
}
的twodigits()
操縱分配使用new num_put(out.getloc())
的num_put
方面。它不需要任何清理,因爲在std::locale
對象中安裝構面會進行必要的清理。流的原始std::locale
使用out.getloc()
訪問。它由方面改變。理論上,notwodigits
可以恢復原始的std::locale
而不是使用標誌。然而,imbue()
可能是一個相對昂貴的操作,使用標誌應該便宜很多。當然,如果有很多類似的格式標誌,事情可能會變得不同...
爲了演示操縱器的使用,下面有一個簡單的測試程序。它設置了格式標誌twodigits
兩次驗證方面只創建一次(這將是一個有點傻創造std::locale
個鏈通過格式化:
int main()
{
std::cout << "some-int='" << 1 << "' "
<< twodigits << '\n'
<< "two-digits1='" << 1 << "' "
<< "two-digits2='" << 2 << "' "
<< "two-digits3='" << 3 << "' "
<< notwodigits << '\n'
<< "some-int='" << 1 << "' "
<< twodigits << '\n'
<< "two-digits4='" << 4 << "' "
<< '\n';
}
創建一個新的'int'的ostream&operator <<'是一個非常糟糕的主意。 :) –
@LightnessRacesinOrbit是的,我也明白這一點。任何建議,而不是做什麼? – Ali
如果你想格式化日期/時間,你可能想檢查一下:http://en.cppreference.com/w/cpp/io/manip/put_time – zahir