Есть ли способ создать общий объект потока вывода для печати на консоли и в файл на С++?

Я пишу код, в котором мне нужно печатать одни и те же данные на консоли и в файл. Есть ли способ заполнить общий объект выходного потока, а затем отобразить его на консоли с помощью cout и экспортировать в файл с использованием библиотек fstream и iostream?


person Fatima Tariq    schedule 30.11.2014    source источник
comment
Используйте boost::iostreams::tee_device.   -  person 0x499602D2    schedule 30.11.2014
comment
Я бы порекомендовал вам сделать это в вызывающей среде.   -  person Lightness Races in Orbit    schedule 30.11.2014


Ответы (1)


Конечно. Вы просто создадите подходящий буфер потока, который, вероятно, сохранит в других буферах потока, в которые он записывает внутренне. Используя этот буфер потока, вы затем создадите std::ostream, в который вы пишете.

Например, вот простая реализация этого подхода:

#include <streambuf>
#include <ostream>

class teebuf
    : public std::streambuf
{
    std::streambuf* sb1_;
    std::streambuf* sb2_;

    int overflow(int c) {
        typedef std::streambuf::traits_type traits;
        bool rc(true);
        if (!traits::eq_int_type(traits::eof(), c)) {
            traits::eq_int_type(this->sb1_->sputc(c), traits::eof())
                && (rc = false);
            traits::eq_int_type(this->sb2_->sputc(c), traits::eof())
                && (rc = false);
        }
        return rc? traits::not_eof(c): traits::eof();
    }
    int sync() {
        bool rc(false);
        this->sb1_->pubsync() != -1 || (rc = false);
        this->sb2_->pubsync() != -1 || (rc = false);
        return rc? -1: 0;
    }
public:
    teebuf(std::streambuf* sb1, std::streambuf* sb2)
        : sb1_(sb1), sb2_(sb2) {
    }
};

class oteestream
    : private virtual teebuf
    , public std::ostream {
public:
    oteestream(std::ostream& out1, std::ostream& out2)
        : teebuf(out1.rdbuf(), out2.rdbuf())
        , std::ostream(this) {
        this->init(this);
    }
};

#include <fstream>
#include <iostream>

int main()
{
    std::ofstream fout("tee.txt");
    oteestream    tee(fout, std::cout);
    tee << "hello, world!\n";
}
person Dietmar Kühl    schedule 30.11.2014
comment
Однако пользовательский потоковый буфер здесь может быть излишним. Сохранения в stringstream и вывода дважды может быть достаточно. Во всяком случае, хороший. (Кстати: у вас завалялся этот код?) - person Deduplicator; 30.11.2014
comment
@Deduplicator: да, есть решение, которое можно использовать PITA, и правильное решение, которое приятно использовать. Обертывание буфера потока в std::ostream делает буфер потока tee довольно удобным в использовании. ... и, да, у меня завалялся этот код: я не набираю это быстро :-) - person Dietmar Kühl; 30.11.2014