实现复合类型的C++运算符<<

Implementing C++ operator<< for a composite type

提问人:Miral 提问时间:11/30/2017 更新时间:11/30/2017 访问量:85

问:

operator<<(ostream&, T const&)是支持将类型对象输出到流的标准机制,通常也用于将自定义类型转换为字符串表示形式(尽管 C++11 中似乎也提供了基本类型)。Tostringstreamto_string

对于简单的单数据成员类型,这相当简单:

friend std::ostream& operator<<(std::ostream& str, Simple const& s)
{
    return str << s.value;
}

这允许根据流的当前规则输出值 - 即。以所需的数字格式和指定的宽度或填充。

但是,一旦您有一个希望输出多个项目的复合类型,这就会变得更加复杂:

friend std::ostream& operator<<(std::ostream& str, Complex const& c)
{
    return str << s.a << ':' << s.b;
}

乍一看,上述工作按预期进行,这似乎是最常见的实现方式,至少根据文档是这样。但这是错误的。

有人将 Complex 视为要显示的单个值,并用于为其指定一些理由,他们会惊讶地发现它们的宽度完全应用于第一个组件,而不是“整个值”。类作者可能会惊讶地发现,有时它们的值是以十六进制打印的。setw

那么,也许我们应该只向原始流输出一个值?

friend std::ostream& operator<<(std::ostream& str, Complex const& c)
{
    std::ostringstream s;
    s << c.a << ':' << c.b;
    return str << s.str();
}

首先,将一个流变成一个字符串,然后把它戳回一个流(并且需要额外的内存分配)感觉有点不对劲——但另一种替代方法是不起作用的,因为它被视为多个单独的插入,再次在错误的位置应用外部。s.rdbuf()setw

其次,虽然现在外部按预期处理,但它已与流上的其他设置隔离,例如是否以十六进制显示或使用什么区域设置。也许这在某些情况下是一件好事,但一般来说,这似乎不是正确的做法。它仍然需要单独分配临时缓冲区。setw

有没有一种首选的方式来优雅地处理这些事情?

C++ IO 运算符重载 IOSTREAM

评论

2赞 Sam Varshavchik 11/30/2017
IOSTREAMS 并不完全以快速和高效而闻名。构造一个中间体,然后将最终结果转储为单个字符球不会使现有情况比现在更糟。如果复杂对象一直被打印出来,也许可以将复杂对象的文本实现缓存为其成员之一,并根据需要生成它。std::ostringstreamstd::string
0赞 Cris Luengo 11/30/2017
一个值得关注的地方是 .std::complex
0赞 chris 11/30/2017
啊哈哈,我想你的字符串流解决方案对于 libc++: github.com/llvm-mirror/libcxx/blob/master/include/complex#L1433 来说已经足够好了(编辑:和 libstdc++:github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/......)
0赞 Miral 11/30/2017
澄清一下,我的意思是“复杂”是“比简单更复杂”,而不是与 .但这仍然是一个有趣的比较。std::complex

答: 暂无答案