【问题标题】:Implementing a no-op std::ostringstream that can be accepted as a std::ostringstream reference实现可以作为 std::ostringstream 引用接受的无操作 std::ostringstream
【发布时间】:2016-10-17 09:15:17
【问题描述】:

任何人都可以建议一种方法来获得一个 null std::ostringstream,避免对使用<< 传递给它的参数做任何工作吗?

这里有两个相关的帖子 Implementing a no-op std::ostreamPrinting to nowhere with ostream ,到目前为止最有希望的解决方案是 https://stackoverflow.com/a/760353/826203 ,但是在测试它时

int main() {
    onullstream os;
    os << 666;

//  std::ostringstream & oss = os; // error C2440: 'initializing' : cannot convert from 'onullstream' to 'std::ostringstream &'
    oss << "hello, world";
}

但是,它只能像os&lt;&lt;666 一样使用,但不能std::ostringstream &amp; 那样使用。有什么办法吗?

【问题讨论】:

  • 您会收到错误消息,因为std::ostringstreamonullstream 是继承树的不同部分。虽然两者都继承自std::ostream,但它们在其他方面无关。相反,我认为在这里使用std::ostringstream 的要求是错误的要求,您并不真正需要。例如,如果您有一个使用流调用的函数,您将需要一个std::ostream 引用。然后你可以传递一个std::ostringstream 对象一个onullstream 对象。

标签: c++ reference stream


【解决方案1】:

创建非操作流的最简单方法实际上是不创建自定义流类,而是禁用现有流。例如,您可以通过将其流缓冲区设置为 null 来禁用对 std::ostream 的格式化:

std::ostringstream out;
out.std::ostream::rdbuf(0);
// any attempt to write anything to out will fail.

如果您需要一个成功格式化数据失败的流,您可以创建一个不存储任何字节且始终成功的流缓冲区。但是,当使用此流缓冲区时,将执行实际格式化:

struct nullbuf: std::streambuf {
    std::streambuf::int_type overflow(std::streambuf::int_type c) {
        return std::char_traits<char>::not_eof(c);
    }
};
// ...
nullbuf            buf;
std::ostringstream out;
out.std::ostream::rdbuf(&buf);

请注意,我还建议 not 让函数将 std::ostringstream 作为参数。相反,任何不构造流的函数都应该以std::ostream&amp; 的形式传播。如果您现有的接口已经采用std::ostringstream,您可以通过从std::ostringstream 派生并适当地设置流缓冲区来创建一个空流:

class onullstream
    : private virtual nullbuf
    , public std::ostringstream {
public:
    nullstring()
        : std::ios(this)
        , std::ostringstgream() {
        this->std::ostream::rdbuf(this);
    }
};

【讨论】:

  • 谢谢!请问1)“将执行实际格式化”是什么意思,2)为什么建议不要将std::ostringstream作为参数,而是使用std::ostream&amp;
  • @athos:抱歉,我一直忘记派生流对rdbuf() 有重载(这是相当误导的)。只需直接调用函数的std::ios-version,例如:out.std::ostream::rdbuf(&amp;buf)(其他版本也一样)。
  • @athos:关于您的其他问题: 1. nullbuf 简单地吃掉发送给它的所有字符。然而,由于它是成功的,所以所有的角色都被制作出来了。也就是说,例如,当您插入int 时,int 将被转换为代表int 值的chars 序列,并且不会使用chars。也就是说,可能有大量工作只是为了忽略字符!相当强制地使流无效,即将流缓冲区设置为0,导致流操作不转换值但所有操作都失败。
  • @athos:流失败是否重要,我不知道 - 很可能不重要:输出流很少测试成功操作。请注意,在所有情况下,都会评估实际参数。例如,当使用out &lt;&lt; f() 时,函数f() 被调用但没有使用结果,或者至少没有使用字符。对于 2.:格式化通常不关心它得到什么流 - 它可能是 std::ostringstreamstd::ofstream 或其他一些自定义流。相应地,功能最好在std::ostream&amp;方面旅行。
  • @athos:我还更新了答案中的代码(仍未编译 - 我目前正在使用移动设备。指示编译器调用基类版本应该足够了rdbuf().
猜你喜欢
  • 1970-01-01
  • 2015-11-11
  • 2013-11-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-06
  • 2014-12-03
相关资源
最近更新 更多