cbizz
cbizz

Reputation: 61

Redirecting C++ fstream

So I have a C++ program, that normally when it executes writes out things to a log file. This is done using an fstream. However, now I want to include functionality to turn the logging off. Essentially, my code looks like this:

bool isLogging;
fstream* logFilePtr;

throughout my code, there are a bunch of statements like:

(*logFilePtr) << "    Kernel call time in seconds: " << kTime << endl;
...

Now, if the "isLogging" is true, I don't want these to print. I could just go surround them with a bunch of if statements, but I'd prefer something cleaner than that. I thought there was some way to take a C++ stream and redirect it to point to "nothing" so that when the << operator is used, nothing will print.

Does anyone know how to redirect the stream, or have any other ideas on how to handle this in an elegant way?

Thanks, Colin

Upvotes: 0

Views: 2069

Answers (7)

oz10
oz10

Reputation: 158364

Under "other ideas on how to handle this":

  1. Use the state pattern to eliminate the need for the if checks around all code.
  2. Use the policy pattern (compile time strategy pattern) with a Logging policy object.

Upvotes: 0

mcandre
mcandre

Reputation: 24612

std::ostream& Debug(int level) {
  std::clog.clear(levell <= shown_level ? std::ios_base::goodbit: std::ios_base::badbit);
  return std::clog;
}

From comp.lang.c++.

Upvotes: 0

Marc Mutz - mmutz
Marc Mutz - mmutz

Reputation: 25293

std::iostream doesn't allow OS-level redirection, however, you can share std::streambufs between std::iostreams:

int main() {
    // redirect stdout to stderr:
    std::streambuf * const oldstdout = std::cout.rdbuf();
    std::cout.rdbuf( std::cerr.rdbuf() );

    // test
    std::cout << "Hello ";
    std::cerr << "World" << std::endl;

    // re-set, so streambufs are properly deleted:
    std::cout.rdbuf( oldstdout );

    // test
    std::cout << "Hello ";
    std::cerr << "World" << std::endl;

    return 0;
}

This way, you can redirect logging to somewhere else (e.g. "/dev/null" :), or, if you follow avakar's answer, use nullbuf.

Upvotes: 1

avakar
avakar

Reputation: 32635

Take a look at rdbuf member function. You can create a discarding stream buffer and associate it with your stream.

struct nullbuf: std::streambuf
{
    int overflow(int c) { return traits_type::not_eof(c); }
};

Upvotes: 4

Budric
Budric

Reputation: 3699

I use POCO library's logging feature. It supports configuring channels - console, file, both. Configuring format of output and logging levels (trace, debug, error etc). I then surround the logging functionality with functions such as

inline void logError(const std::string & str)
{
#ifdef COMPILE_ERROR_LOGGING
   g_pMyPocoLogger->error(str);
#endif
}

You can choose not to use the library but I still recommend surrounding your logging with a wrapper.

Upvotes: 0

Federico klez Culloca
Federico klez Culloca

Reputation: 27119

platform? if you are under unix you can write the file to /dev/null

Upvotes: 0

eduffy
eduffy

Reputation: 40224

You could wrap it up in a class.

class Log {
  Log (fstream &s) : stream(s), enabled(false) { }
  void Enable () { enabled = true; }
  void Disable () { enabled = false; }

  template<class T>
  Log &operator<< (T const& rhs) {
    if (enabled) stream << rhs;
    return *this;
  }

private:
  fstream &stream;
  bool enabled;
};

this isn't tested .. but the basic idea should be there.

Upvotes: 6

Related Questions