Вариант 1:
Как @ PaulR предлагает , вы можете использовать внешний процесс, такой как tee (в Linux / Mac / Unix), или написать собственный процесс для чтения из stdin в цикле и записи в stdout и другие. файл.
Вариант 2:
Я сделал это много лет назад с std :: basic_ios :: rdbuf для std::cout
. Все, что нужно сделать, это определить класс (см. std::filebuf
и std::streambuf
):
class tee_buf : public std::filebuf {
public:
// Not an owing pointer
tee_buf(std::streambuf * other_stream)
: m_other_stream(other_stream) {}
void swap( tee_buf& rhs );
// No need to override open/close since we need to manage only the file.
// The open/close calls don't touch the other_stream.
protected:
int_type overflow(int_type c = traits_type::eof()) override;
// The parent calls this->overflow(), but then still need to call
// m_other_stream->sync(). This is problematic since m_other_stream
// gets flushed twice.
int sync() override;
pos_type seekoff( off_type off,
std::ios_base::seekdir dir,
std::ios_base::openmode which) override {
return pos_type(off_type(-1)); // ???
}
pos_type seekpos( pos_type sp,
std::ios_base::openmode which) override {
return pos_type(off_type(-1)); // ???
}
....
Это более эффективно для интенсивного ввода-вывода, так как избегает посредников. Но в большинстве случаев это более простое и предпочтительное решение. Если производительность является проблемой (а в большинстве случаев это не так), то возможно, что оба потоковых буфера совместно используют один буфер памяти. Также возможно использовать асинхронный ввод-вывод для параллельной записи в оба потока.
Использование с утечкой памяти:
std::cout.rdbuf(new tee_buf(std::cout.rdbuf());
Использование без утечки памяти:
Напишите класс RAII, содержащий tee_buf
, чтобы сохранить оригинал и установить новый std::cout.rdbuf()
. При уничтожении восстановить состояние std::cout.rdbuf()
. Сделайте один экземпляр этого класса, который будет выполнять грязную работу при его строительстве и разрушении.
Что касается стиля C stdout
: я не верю, что есть способ переопределить его поведение. В лучшем случае можно играть с буферной памятью, но этого недостаточно для получения желаемой функциональности. С stdout
единственное, что можно сделать, это использовать tee
-подобное решение.