我正在尝试将流操作符重载为我代码中各种对象的诊断工具。理想情况下,我希望能够使用这些流修改器标志动态修改流,但是这些非常有限,我并不想在每个对象中撒上setVerbose标志。我最终得到了以下相当差但工作正常的解决方案
#include <iostream>
#include <string>
#include <vector>
struct StructA {
std::string mLongName;
std::string mShortName;
inline friend std::ostream& operator << (std::ostream& os, const StructA& rStruct) {
// I dont know how to use a generic verbose flag - so use this - very bad idea
// but perhaps the stackoverflow people can help out with a good suggestion
if (os.flags() & os.skipws) {
os << rStruct.mShortName << std::endl;
} else {
os << rStruct.mLongName << std::endl;
}
return os;
}
};
int main()
{
StructA test {"Verbose Name", "Short Name"};
std::cout << test << std::noskipws << test << test << std::skipws << test;
}
我创建了上面的live example来演示我的观点,并打印出以下输出:
Short Name
Verbose Name
Verbose Name
Short Name
正如你所看到的,我正在使用一个完全不合适的&#39; skipws&#39; stream modifier标志作为一个穷人的1级详细标志 - 这只是为了显示我正在寻找的in stream方法而没有havnig为我的每个可打印对象添加一个成员对象(所有建议更好的方法将是欢迎,但我想尽量减少每个可打印对象的更改 - 因为我有很多)。其次,该标志是持久的,直到稍后重置 - 其他一些流标志仅持续下一个流操作符,但我不确定它是如何工作的,第三个
答案 0 :(得分:2)
在这种情况下,您似乎也不愿意出于某种原因创建抽象。不要单独接受这个我只写这个,因为我曾经太犹豫不决,但创建抽象。通过继承或包含您可以修改的行为,基于iostream创建Logger类。假设记录器有像
这样的选项enum {SHORT,VERBOSE,DEBUG};
让此选项为静态,以便它对所有实例具有应用程序范围的影响。真的只需要一个实例吗?
我意识到所有可打印对象都需要以一致的方式支持各种打印选项,即所有都需要shortName和longName。
答案 1 :(得分:2)
您可以在流实例中存储自定义状态:
#include <iostream>
static int const index = std::ios_base::xalloc();
std::ostream& verbose(std::ostream& stream) {
stream.iword(index) = 1;
return stream;
}
std::ostream& noverbose(std::ostream& stream) {
stream.iword(index) = 0;
return stream;
}
struct StructA {
std::string mLongName;
std::string mShortName;
inline friend std::ostream& operator << (std::ostream& os, const StructA& rStruct) {
switch (os.iword(index)) {
case 1: return os << rStruct.mLongName;
case 0:
default: return os << rStruct.mShortName;
}
}
};
int main()
{
StructA a;
a.mLongName = "loooooooooooooooooooong names are tedious";
a.mShortName = "succinctness";
std::cout << a << '\n';
std::cout << verbose;
std::cout << a << '\n';
std::cout << noverbose;
std::cout << a << '\n';
}
如果您需要大量的状态/逻辑,则必须考虑灌输自定义区域设置方面。他的回答也显示了这种方法的基础。