Search code examples
c++fstreamostream

Discrimination between file and console streams


How to determine weather ostream is a file or a console stream. In the following program I want to print "Hello file!" while writing to a file and "Hello console!" while writing to console. What condition should I specify at line 17?

#include <fstream>
#include<iostream>
#include <string>
using namespace std;

class A{
public:
        A(string msg):_str(msg){}
        string str()const {return _str;};
private:
        string _str;
};

ostream & operator << (ostream & os, const A & a)
{
        if (os is ofstream) //this is line 17
                os << "Hello file! " << a.str() << endl;
        else
                os << "Hello console! " << a.str() << endl;

        return os;
}

int main()
{
        A a("message");
        ofstream ofile("test.txt");
        if (!ofile)
                cerr << "Unable to open file";
        else
                ofile << a;  // "Hello file"

        cout << a << endl; // "Hello console"
}

Solution

  • Maybe not pretty, but

    std::streambuf const * coutbuf = std::cout.rdbuf();
    std::streambuf const * cerrbuf = std::cerr.rdbuf();
    
    ostream & operator << (ostream & os, const A & a)
    {
            std::streambuf const * osbuf = os.rdbuf();
    
            if ( osbuf == coutbuf || osbuf == cerrbuf )
                    os << "Hello console! " << a.str() << endl;
            else
                    os << "Hello file! " << a.str() << endl;
    
            return os;
    }
    

    We could use &os == &std::cout, but the Standard output might be redirected to file, so I think it is better to use the streambuf object instead. (See this answer for better understanding as to how the redirection works, and why comparing streambuf solves the problem safely! )