我如何绑定std::ostream
到任一std::cout
或到一个std::ofstream
对象,取决于特定的程序条件?尽管由于多种原因这无效,但我希望实现语义上与以下内容等效的东西:
std::ostream out = condition ? &std::cout : std::ofstream(filename);
我见过一些不是异常安全的例子,例如来自http://www2.roguewave.com/support/docs/sourcepro/edition9/html/stdlibug/34-2.html http://www2.roguewave.com/support/docs/sourcepro/edition9/html/stdlibug/34-2.html:
int main(int argc, char *argv[])
{
std::ostream* fp; //1
if (argc > 1)
fp = new std::ofstream(argv[1]); //2
else
fp = &std::cout //3
*fp << "Hello world!" << std::endl; //4
if (fp!=&std::cout)
delete fp;
}
有谁知道更好的、异常安全的解决方案?
std::streambuf * buf;
std::ofstream of;
if(!condition) {
of.open("file.txt");
buf = of.rdbuf();
} else {
buf = std::cout.rdbuf();
}
std::ostream out(buf);
它将 cout 或输出文件流的底层 Streambuf 关联到 out。之后,您可以写入“out”,它将最终到达正确的目的地。如果你只是想让一切顺利std::cout
进入一个文件,你也可以这样做
std::ofstream file("file.txt");
std::streambuf * old = std::cout.rdbuf(file.rdbuf());
// do here output to std::cout
std::cout.rdbuf(old); // restore
第二种方法的缺点是它不是异常安全的。您可能想编写一个使用 RAII 执行此操作的类:
struct opiped {
opiped(std::streambuf * buf, std::ostream & os)
:os(os), old_buf(os.rdbuf(buf)) { }
~opiped() { os.rdbuf(old_buf); }
std::ostream& os;
std::streambuf * old_buf;
};
int main() {
// or: std::filebuf of;
// of.open("file.txt", std::ios_base::out);
std::ofstream of("file.txt");
{
// or: opiped raii(&of, std::cout);
opiped raii(of.rdbuf(), std::cout);
std::cout << "going into file" << std::endl;
}
std::cout << "going on screen" << std::endl;
}
现在,无论发生什么,std::cout 都处于干净状态。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)