从std :: cout或std :: ofstream(file)获取一个std :: ostream
我如何将std::ostream
绑定到std::cout
或std::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);