Obtain a std::ostream either from std::cout or std::ofstream(file)
如何根据特定程序条件将
1 | std::ostream out = condition ? &std::cout : std::ofstream(filename); |
我看到了一些异常安全的示例,例如http://www2.roguewave.com/support/docs/sourcepro/edition9/html/stdlibug/34-2.html中的示例:
1 2 3 4 5 6 7 8 9 10 11 12 | 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; } |
有谁知道更好的,异常安全的解决方案?
1 2 3 4 5 6 7 8 9 10 11 | 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",它将最终到达正确的目的地。 如果您只希望将要进入
1 2 3 4 | 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执行此操作的类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | 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都处于干净状态。
这是异常安全的:
1 2 3 4 5 6 7 8 9 10 11 | void process(std::ostream &os); int main(int argc, char *argv[]) { std::ostream* fp = &cout; std::ofstream fout; if (argc > 1) { fout.open(argv[1]); fp = &fout; } process(*fp); } |
编辑:Herb Sutter在文章切换流(本周专家)中解决了此问题。
1 2 | std::ofstream of; std::ostream& out = condition ? std::cout : of.open(filename); |
从这篇文章引用。
您可以应用类似的方法。
1 2 3 | struct noop { void operator()(...) const {} }; |
1 2 3 4 5 6 | std::shared_ptr<std::ostream> of; if (condition) { of.reset(new std::ofstream(filename, std::ofstream::out)); } else { of.reset(&std::cout, noop()); } |
作为C ++的新手,我不知道这是否是异常安全的,但是我通常这样做是这样的:
1 | std::ostream& output = (condition)?*(new std::ofstream(filename)):std::cout; |
以下简单代码对我有用:
1 2 3 4 5 6 7 8 9 10 | int main(int argc, char const *argv[]){ std::ofstream outF; if (argc > 1) { outF = std::ofstream(argv[1], std::ofstream::out); } std::ostream& os = (argc > 1)? outF : std::cout; } |