ex1led
ex1led

Reputation: 469

How to redirect std::cout to file conditionally

In my code I have a a function that takes as argument a boolean variable. If this variable is true then the output shall be redirected to a file. If not, then to std::cout

The code looks like this and Its been inspired by a relevant question [1]

void MyClass::PPrint(bool ToFile)
{
    
        std::streambuf *coutBufferBak = std::cout.rdbuf();
        std::ofstream   out("out.txt");
        
        if (ToFile) { std::cout.rdbuf(out.rdbuf()); }

        std::cout << "Will I be written to a file or to cout ?\n";

        if (ToFile) {std::cout.rdbuf(coutBufferBak);} // reset cout
  
}

But in the case that the ToFile flag is false the file will be generated nonetheless and it will be empty. Is there a way to do it so that the file won't be generated ? If for example I try to include on the first IF statement the std::ofstream out("out.txt"); then I will get a SegFault due to the the variable scope being limited to that if.

Upvotes: 0

Views: 714

Answers (2)

Caleth
Caleth

Reputation: 62694

Don't redirect std::cout. Write your print in terms of a std::ostream & parameter, and choose an appropriate std::ostream to pass.

void MyClass::PPrintImpl(std::ostream & out)
{
    out << "Will I be written to a file or to cout ?\n";
}

// a.k.a 

std::ostream & operator <<(std::ostream & out, const MyClass &)
{
    return out << "Will I be written to a file or to cout ?\n";
}

void MyClass::PPrint(bool ToFile) {
    if (ToFile) {
        std::ofstream fout("out.txt");
        PPrintImpl(fout);
    } else {
        PPrintImpl(std::cout);
    }
}

We pass std::ostreams by reference because we the identity, not just the value of the stream object matters. We know this because they aren't copyable (the copy constructor is deleted)

Upvotes: 3

Daniel
Daniel

Reputation: 31579

You can open the file conditionally:

std::ofstream out;
if(...)
    out.open("out.txt");

Upvotes: 2

Related Questions