Я немного кручусь с потоками и не могу опустить голову вокруг следующего.
Здесь у нас есть базовый ptr, который настроен на разные выходные потоки, будь то cout
, cerr
или file
.
// ostream ptr
std::ostream* outstream;
// set output ostream
void setOutput(std::ostream & os)
{
outstream = &os;
}
// write message to ostream
void writeData(const std::string & msg)
{
*outstream << msg << '\n';
}
int main (int argc, char * const argv[])
{
// init to std out
setOutput(std::cout);
writeData("message to cout");
setOutput(std::cerr);
writeData("message to cerr");
std::ofstream fileout("test.txt", std::ofstream::out | std::ofstream::app);
setOutput(fileout);
writeData("message to file");
//fileout.close();
setOutput(std::cout);
writeData("message2 to cout");
return 0;
}
Вышеописанное прекрасно работает и показывает силу реализации iOS-образа С++. Отлично.
Однако, поскольку setOutput
устанавливается по ссылке, объект, на который ссылается, должен оставаться в области видимости. Именно здесь возникает проблема. Я хочу выяснить способ вывода по умолчанию на std::cout
, если поток или любой другой поток недействителен. То есть ссылочный объект выходит за пределы области видимости.
Например:
// write message to ostream
void writeData(const std::string & msg)
{
if (/*stream or memory is invalid*/)
setOutput(std::cout);
*outstream << msg << '\n';
}
// local fileout goes out of scope
void foo()
{
std::ofstream fileout("test.txt", std::ofstream::out | std::ofstream::app);
setOutput(fileout);
writeData("message to file");
}
int main (int argc, char * const argv[])
{
setOutput(std::cout);
writeData("message to cout");
foo();
/* problem the local fileout is no longer referenced by the ostream ptr*/
/* the following should be redirected to std::cout cuz of default*/
writeData("message2 to cout");
return 0;
}
Вышеуказанное прекрасно, пока foo()
не вернется к основной функции. Там это выглядит ужасно, потому что локально определенный ofstream
недоступен.
Очевидно, это нецелесообразно, и пользователь должен это осознать. Однако я хочу обернуть все это в класс журнала и, таким образом, сохранить состояние объекта, даже считая, что это неправильное использование может случиться. Это приведет к недействительным нарушениям доступа, которые трудно найти.
Конкретный вопрос. Есть ли способ выяснить, все ли ptr или любой ptr по-прежнему ссылаются на действительный объект или ячейку памяти?
ps: Я мог бы использовать память кучи и делать что-то с умными указателями, но, откровенно говоря, я хотел бы сохранить его таким образом, если возможно