I got tired of recreating something like it.
LoggingHack.h
#ifdef LOGGING_HACK
class JLogStream
{
public:
 virtual ~JLogStream() {
 }
};
extern JLogStream* jlogs;
extern JLogStream& operator<< (JLogStream& rlog, const std::string& val);
extern JLogStream& operator<< (JLogStream& rlog, const std::wstring& val);
extern JLogStream& operator<< (JLogStream& rlog, const char* zStr);
extern JLogStream& operator<< (JLogStream& rlog, const wchar_t* zStr);
extern JLogStream& operator<< (JLogStream& rlog, int val);
extern JLogStream& operator<< (JLogStream& rlog, std::stringstream &val);
extern JLogStream& operator<< (JLogStream& rlog, std::wstringstream &val);
#define JLOG( x ) { (*jlogs) << x << "\n"; }
#else
#define JLOG( x ) ;
#endif
LoggingHack.cpp
#ifdef LOGGING_HACK
#include <sstream>
#include "LoggingHack.h"
class JLogStreamImpl : public JLogStream
{
private:
 FILE* jlog_fout1;
 FILE* jlog_fout2;
 FILE* jlog_fout3;
public:
 JLogStreamImpl()
 {
  std::stringstream ss1;
  ss1 << "c:\\delme\\" << LOGGING_HACK_FILE_BASE_NAME << ".log";
  std::stringstream ss2;
  ss2 << "c:\\delme\\" << LOGGING_HACK_FILE_BASE_NAME << " - " << ::GetTickCount() << ".log";
  std::stringstream ss3;
  ss3 << "c:\\delme\\" << LOGGING_HACK_FILE_BASE_NAME << "-rolling.log";
  fopen_s(&jlog_fout1, ss1.str().c_str(), "wt");
  fopen_s(&jlog_fout2, ss2.str().c_str(), "wt");
  fopen_s(&jlog_fout3, ss3.str().c_str(), "at");
  log(ss1.str().c_str());
 }
 void log(const char* zStr)
 {
  fwrite(zStr, strlen(zStr), 1, jlog_fout1);
  fwrite(zStr, strlen(zStr), 1, jlog_fout2);
  fwrite(zStr, strlen(zStr), 1, jlog_fout3);
  fflush(jlog_fout1);
  fflush(jlog_fout2);
  fflush(jlog_fout3);
 }
 void log(const wchar_t* zStr)
 {
  int ncharLen;
  ncharLen = WideCharToMultiByte(CP_UTF8, 0, zStr, -1, NULL, 0, NULL, NULL);
  char* zstr = new char[ncharLen];
  WideCharToMultiByte(CP_UTF8, 0, zStr, -1, zstr, ncharLen, NULL, NULL);
  log("UNICODE:");
  log(zstr);
 }
 void log(int val)
 {
  std::stringstream ss;
  ss << val;
  log(ss);
 }
 void log(std::stringstream &val)
 {
  log(val.str().c_str());
 }
 void log(std::wstringstream &val)
 {
  log(val.str().c_str());
 }
};
extern JLogStream& operator<< (JLogStream& rlog, const std::string& val)
{
 dynamic_cast<JLogStreamImpl*>(&rlog)->log(val.c_str());
 return rlog;
}
extern JLogStream& operator<< (JLogStream& rlog, const std::wstring& val)
{
 dynamic_cast<JLogStreamImpl*>(&rlog)->log(val.c_str());
 return rlog;
}
extern JLogStream& operator<< (JLogStream& rlog, const char* zStr)
{
 dynamic_cast<JLogStreamImpl*>(&rlog)->log(zStr);
 return rlog;
}
extern JLogStream& operator<< (JLogStream& rlog, const wchar_t* zStr)
{
 dynamic_cast<JLogStreamImpl*>(&rlog)->log(zStr);
 return rlog;
}
extern JLogStream& operator<< (JLogStream& rlog, int val)
{
 dynamic_cast<JLogStreamImpl*>(&rlog)->log(val);
 return rlog;
}
extern JLogStream& operator<< (JLogStream& rlog, std::stringstream &val)
{
 dynamic_cast<JLogStreamImpl*>(&rlog)->log(val);
 return rlog;
}
extern JLogStream& operator<< (JLogStream& rlog, std::wstringstream &val)
{
 dynamic_cast<JLogStreamImpl*>(&rlog)->log(val);
 return rlog;
}
JLogStreamImpl theLogStream;
JLogStream* jlogs = &theLogStream;
#else
#define jlog(s) ;
#define jlog(s1, s2) ;
#endif
Include this in one cpp file of the dll or exe: Replacing LogBaseName with the desired name
#define LOGGING_HACK
#define LOGGING_HACK_FILE_BASE_NAME "LogBaseName"
#include "..\..\..\..\LoggingHack.cpp"
Include this in the other cpp files of the module:
#define LOGGING_HACK
#include "..\..\..\..\LoggingHack.h"
Use it like this:
JLOG(__FILE__ << "@" << __LINE__);
