I need a class that redirects one ostream to another ostream during the lifetime of its object. After some tinkering I came up with this:
#include
The reason those lines are the same is because what you're doing is swapping the buffers. (That is, you "redirect" by swapping the original buffer with the redirect buffer; restoration is the swap back.)
While this might give you the intended effect with respect to the output stream, it's not correct because the redirect stream now outputs somewhere else. To redirect means to take one stream and make it output somewhere else; note this doesn't effect that 'somewhere else'.
Your class is not a redirect; as is, it should really be named ScopedStreamSwap
. For example, try this instead:
#include <iostream>
#include <fstream>
class ScopedRedirect
{
public:
ScopedRedirect(std::ostream & inOriginal, std::ostream & inRedirect) :
mOriginal(inOriginal),
mRedirect(inRedirect)
{
mOriginal.rdbuf(mRedirect.rdbuf(mOriginal.rdbuf()));
}
~ScopedRedirect()
{
mOriginal.rdbuf(mRedirect.rdbuf(mOriginal.rdbuf()));
}
private:
ScopedRedirect(const ScopedRedirect&);
ScopedRedirect& operator=(const ScopedRedirect&);
std::ostream & mOriginal;
std::ostream & mRedirect;
};
int main()
{
std::cout << "Before redirect." << std::endl;
std::ofstream filestream("redirected.txt");
{
ScopedRedirect redirect(std::cout, filestream);
std::cout << "During redirect." << std::endl;
// oops:
filestream << "also to the file, right?...nope" << std::endl;
filestream << "ah, why am i on the screen?!" << std::endl;
}
std::cout << "After redirect." << std::endl;
// in main, return 0 is implicit, if there is no return statement;
// helpful to keep in mind in snippets and short things
}
What you want is this:
#include <iostream>
#include <fstream>
class ScopedRedirect
{
public:
ScopedRedirect(std::ostream & inOriginal, std::ostream & inRedirect) :
mOriginal(inOriginal),
mOldBuffer(inOriginal.rdbuf(inRedirect.rdbuf()))
{ }
~ScopedRedirect()
{
mOriginal.rdbuf(mOldBuffer);
}
private:
ScopedRedirect(const ScopedRedirect&);
ScopedRedirect& operator=(const ScopedRedirect&);
std::ostream & mOriginal;
std::streambuf * mOldBuffer;
};
int main()
{
std::cout << "Before redirect." << std::endl;
std::ofstream filestream("redirected.txt");
{
ScopedRedirect redirect(std::cout, filestream);
std::cout << "During redirect." << std::endl;
// yay:
filestream << "also to the file, right?...yes" << std::endl;
filestream << "i am not on the screen" << std::endl;
}
std::cout << "After redirect." << std::endl;
return 0;
}