c++ - 如何处理自定义输出运算符中的iomanips?
问题描述
我刚刚遇到了将自定义输出运算符与 io-manipulators 相结合的问题。也许我的期望完全偏离了,但如果
std::cout << foo() << "\n";
印刷
00
那么我会期待
std::cout << std::left << std::setw(20) << foo() << "!\n"
打印
00 !
但鉴于这个实现
#include <iostream>
#include <iomanip>
struct foo { int a,b; };
std::ostream& operator<<(std::ostream& out, const foo& f) {
out << f.a << f.b;
return out;
}
int main() {
std::cout << foo() << "\n";
std::cout << std::left << std::setw(20) << foo() << "!";
}
屏幕上打印的是
00
0 0!
我基本上看到了两种选择:A)我的期望是错误的。B)我改用这个实现:
std::ostream& operator<<(std::ostream& out, const foo& f) {
std::stringstream ss;
ss << f.a << f.b;
out << ss.str();
return out;
}
然而,考虑到大多数时候没有使用 io 操纵器,这似乎是相当大的开销。
在自定义输出运算符中“正确”处理 io-manipulators 的惯用方式是什么?
解决方案
恐怕没有简单的答案。如果您只需要处理std::setw
and ,您的解决方案是惯用的std::left
,但是对于其他操作,您必须决定格式化程序的行为。
例如,想象一下,如果你的结构有浮点数而不是整数:
struct foo { float a,b; };
然后,您的用户尝试这样做:
const long double pi = std::acos(-1.L);
std::cout << std::setprecision(10) << foo{0.0f, pi} << "!\n"
这是您必须决定的时候:您是要尊重输出流的精度属性,还是要忽略它?您当前的实现会忽略它,因为它在另一个流中进行实际转换。
为了尊重精度属性,您必须复制它:
std::ostream& operator<<(std::ostream& out, const foo& f) {
std::stringstream ss;
ss.precision(out.precision());
ss << f.a << f.b;
out << ss.str();
return out;
}
对于您的整数情况,您还必须考虑是否会兑现std::setbase
。
必须将相同的推理应用于其他操纵器,std::setfill
例如 。
推荐阅读
- html - 文本对齐如何在 HTML/CSS 中工作
- python - 如果消息有一定数量的反应,则将消息提取到另一个通道 - discord.py 重写
- r - 如何下载小于 3.6 的 R 版本的包“markovchain”
- timestamp - Postman:测试不同时间戳的断言
- powershell - Powershell 使用 System.Windows.Forms.SaveFileDialog 将目录位置选择到变量中
- react-native - 接收react-native应用程序ble发送的数据
- sml - 展平 SML 获取问题的数据类型列表
- javascript - 随机消息回复 Discord.js 2020
- google-bigquery - 如何在 Bigquery 中更改列模式
- python - 使用 numPy 和 matplotlib 绘制函数相对于两个变量的最大值