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 или потока выходного файла с 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 находится в чистом состоянии.