从std :: cout或std :: ofstream(file)获取一个std :: ostream

我如何将std::ostream绑定到std::coutstd::ofstream对象,具体取决于特定的程序条件? 虽然这个失效的原因很多,但是我想达到的东西在语义上等同于以下几点:

 std::ostream out = condition ? &std::cout : std::ofstream(filename); 

我见过一些不是exception安全的例子,比如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; } 

有谁知道一个更好的,exception安全的解决scheme?

 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或输出文件stream的底层streambuf关联。 之后,你可以写出“出”,它将在正确的目的地结束。 如果你只是想要所有的东西都去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; } 

现在,不pipe发生什么,std :: cout都处于清理状态。

这是exception安全的:

 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); } 

编辑:香草萨特已经在文章切换stream(本周大师)中解决了这个问题。

 std::ofstream of; std::ostream& out = condition ? std::cout : of.open(filename);