«Если вам нужна дополнительная поддержка для управления временем жизни объекта, вам нужно что-то более сложное - например, хранение прокси-объектов, которые знают, владеет ли регистратор данным потоком». - бесполезно
Текущее решение этой проблемы в моем текущем проекте выглядит примерно так:
using ostream_deleter = std::function<void(std::ostream *)>;
using ostream_ptr = std::unique_ptr<std::ostream, ostream_deleter>;
Это позволяет вам сохранить новый объект потока с владельцем, например,
ostream_deleter d{std::default_delete<std::ostream>{}};
ostream_ptr fileStream{new std::ofstream{"/tmp/example.foo"}, std::move(d)};
Обратите внимание, что сначала вы должны создать стертое при удалении типа из соображений безопасности исключений.
Это также позволяет вам использовать глобальные потоки, которые, как известно, переживают ваш регистратор:
ostream_ptr coutStream{&std::cout, [](std::ostream &) {}};
Существует также null_deleter
в Boost , если вы хотите больше самодокументируемого синтаксиса.
К сожалению, все еще существует проблема с потоками, которые могут быть внутренне перенаправлены . Действительно, C ++ поддерживает перенаправление вывода (или ввода из) любого потока в другой буфер потока, например,
std::ofstream logStream{"/tmp/my.log"};
const auto oldBuf = std::cout.rdbuf(logStream.rdbuf());
std::cout << "Hello World.\n"; // output redirected to /tmp/my.log
std::cout.rdbuf(oldBuf); // undo redirection
Проблема в том, что время жизни потокового буфера связано с logStream
, а не std::cout
. Это усложняет любой срок службы rsp. делает полностью общее решение о невозможном. Конечно, дисциплина и соглашение все еще должны сильно помогать, и, по общему признанию, перенаправление потока является довольно неясной и редко используемой функцией.