我应该使用另一个streambuf创建一个临时的ostream吗?

时间:2014-11-06 11:48:10

标签: c++ iostream streambuf

假设我有一个函数,它接受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)我还没有考虑过另一种更好的方法吗?

3 个答案:

答案 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);

将精度恢复为原始值