I am toying around with streams for a bit and can't get my head around the following.
Here we have a basic ostream ptr that is set to different output streams, whether it is cout
, cerr
or a 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;
}
The above works perfectly and shows the strength of the c++ iostream implementation. Perfect.
However, since the setOutput
is set by reference the referenced object has to stay in scope. This is where the issue emerges. I want to figure out a way to default the output to std::cout
if the ofstream or any other ostream is invalidated. That is, referenced object is or went out of scope.
For example:
// 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;
}
The above is fine until the foo()
returns to the main function. There it goes horrible wrong because the locally defined ofstream
is not reachable anymore.
Obviously this is not advisable and the user should realise this. However I want to wrap all this in a logging class and thus keep the state of the object valid even thought this misuse might happen. It will cause an invalidate access violation which can be hard to find.
Concrete question. Is there any way to figure out whether an ostream ptr or any ptr for that matter is still referencing a valid object or memory location?
ps: I could use heap memory and do something with smart pointers but frankly I'd want to keep it like this if possible
std::ostream*
can point to it. – Ransom