Вы не хотите изменять std::cout
.
Вместо этого вы хотите создать специализированный std::streambuf
, который записывает два буфера, а не один. Например;
#include <streambuf>
template <typename char_type,
typename traits = std::char_traits<char_type> >
class basic_teebuf:
public std::basic_streambuf<char_type, traits>
{
public:
typedef typename traits::int_type int_type;
basic_teebuf(std::basic_streambuf<char_type, traits> * sb1,
std::basic_streambuf<char_type, traits> * sb2)
: sb1(sb1)
, sb2(sb2)
{
}
protected: // override virtuals inherited from std::basic_streambuf
virtual int sync()
{
int const r1 = sb1->pubsync();
int const r2 = sb2->pubsync();
return r1 == 0 && r2 == 0 ? 0 : -1;
}
virtual int_type overflow(int_type c)
{
int_type const eof = traits::eof();
if (traits::eq_int_type(c, eof))
{
return traits::not_eof(c);
}
else
{
char_type const ch = traits::to_char_type(c);
int_type const r1 = sb1->sputc(ch);
int_type const r2 = sb2->sputc(ch);
return
traits::eq_int_type(r1, eof) ||
traits::eq_int_type(r2, eof) ? eof : c;
}
}
private:
std::basic_streambuf<char_type, traits> * sb1;
std::basic_streambuf<char_type, traits> * sb2;
};
typedef basic_teebuf<char> teebuf;
Затем вам нужно создать специализированный ostream
, который использует такой буфер
#include <ostream>
class teestream : public std::ostream
{
public:
// Construct an ostream which tees output to the supplied
// ostreams.
teestream(std::ostream & o1, std::ostream & o2);
private:
teebuf tbuf;
};
teestream::teestream(std::ostream & o1, std::ostream & o2)
: std::ostream(&tbuf)
, tbuf(o1.rdbuf(), o2.rdbuf())
{
}
Все вышеперечисленное делает это создание специализированного std::ostream
, который использует наш специализированный буфер, который, в свою очередь, делает использование двух буферов ,
Теперь наш teestream
необходимо инициализировать двумя потоками. Например
#include <fstream>
#include <iostream>
// include the preceding definition of teestream here
int main()
{
std::ofstream logfile("hello-world.log");
teestream tee(std::cout, logfile);
// tee is now a stream that writes the same output to std::cout and logfile
tee << "Hello, world!\n";
return 0;
}
Преимущество этого в том, что все потоковых Вставки (оператор <<
) будут работать с нашим teestream
- даже для классов с перегруженными версиями.
Когда main()
возвращается, потоки также будут закрыты чисто.
Я написал specalised streambuf
в качестве шаблона (std::streambuf
- это специализация шаблонного класса std::basic_streambuf
). Для общности, вероятно, было бы лучше сделать то же самое с потоком (используя тот факт, что std::ostream
также является специализацией шаблона std::basic_ostream
). Я оставляю такое обобщение как упражнение.
Возможно, у вас должен быть регистратор на основе экземпляра с помощью метода '.log()', который, в зависимости от реализации, может записывать в файл, писать на stdout и т. Д., А не пытаться перегрузить свободные функции из пространства имен std. Это будет намного больше OO и выглядеть немного дерьмо. –
Как насчет использования ['std :: clog'] (http://www.cplusplus.com/reference/iostream/cout/) и перенаправления его вывода в файл: [' std :: cout.rdbuf (logfile.rdbuf());] (http://www.cplusplus.com/reference/ios/ios/rdbuf/)? – 865719
Посмотрите, Натан, у меня также есть метод .log(), но я хотел бы знать, как выполнить то, что я описал выше, поэтому я поднял этот вопрос. Если бы я хотел знать, было ли это дерьмо или нет, я бы сформулировал это по-другому. – varantir