假设我有一个函数,它接受ostream &
参数o
并写入该ostream。 operator <<
实施将是一个很好的例子。
ostream& operator << (ostream& o, const MyThing& t)
{
// ... interesting code here ...
return o;
}
在函数中,我可能想在流上指定格式化选项。例如,我可能希望将数字打印为十六进制,无论o
在传递给函数时如何配置。
其次,我可能希望能够对当前的格式化标志做出假设。例如,除非我另有要求,否则能够假设数字被格式化为十进制是很好的。
最后,当函数退出时,我希望o
上的格式化选项与调用函数之前的格式选项相同,以便对调用者不变。这只是打电话的礼貌问题。
到目前为止,我已通过在函数中创建本地ostringstream
,完成所有工作(包括设置格式选项)并将.str()
发送到o
来实现此目的在功能的最后。 StackOverflow问题here表明,比我聪明的人采用相同的方法。然而,令我困扰的是,我在ostringstreams中保留了如此多的数据,这些数据可能会更早地发送到输出(字符串可以变得非常大)。
我有两个问题:
1)是否合法,惯用,良好的形式,等。在o.rdbuf()
周围创建一个临时的(基于堆栈的)ostream并在那个ostream上做我的工作?我自己的测试和cppreference.com处的页面似乎表明我可以。
ostream& operator << (ostream& o_, const MyThing& t)
{
ostream o (o_.rdbuf());
// write stuff to "o",
// setting formatting options as I go.
return o_; // Formatting on the parameter ostream o_ unchanged.
}
2)我还没有考虑过另一种更好的方法吗?
答案 0 :(得分:2)
Boost IO State Savers正是为此目的而构建的。
答案 1 :(得分:1)
这不是一个糟糕的解决方案;这当然是合法的。我不认为 这太常见了,所以评论可能是个好主意 你为什么要这样做。
我在这里看到的最常见的解决方案是创建一个州
saver类,它将保存您需要的所有状态
(通常是flags()
,precision()
和fill()
)
构造函数,并在析构函数中还原它,然后再到
强制设置您想要的所有选项。 (这可能是有可能的
为此使用copyfmt
,虽然这也复制了类似的东西
异常掩码,你可能不想玩。)
答案 2 :(得分:0)
这些设置可以存储在一种名为fmtflags对象的对象中,该对象在名为ios的类中定义,该类包含在iostream中。你可以声明其中一个 这些对象,但您必须使用范围解析运算符声明它。
以下语句将在变量old_settings中保存格式状态的某些方面:
ios::fmtflags old_settings = cout.flags();
然后,在使用新设置进行输出后,您可以通过使用旧设置作为参数调用相同的函数来恢复旧设置:
cout.flags(old_settings);
可以使用成员函数获取和恢复其他设置。例如,
int old_precision = cout.precision();
将保存当前的精度规格。然后
cout.precision(old_precision);
将精度恢复为原始值